Pożar lasu

    -- Sebastian Pawlak, 2003.


Pożar lasu został zaimplementowany z wykorzystaniem biblioteki graficznej SDL w Microsoft Visual Studio. Lewym przyciskiem myszy wznieca się pożar. Prawym przyciskiem myszy tworzy się ziemną przeszkodę dla ognia. Las odrasta.


Kod źródłowy pliku "las.cpp":

/******************************
 *         POZAR LASU         *
 *      Sebastian Pawlak      *
 ******************************/

#include <math.h>
#include <stdlib.h>
#include "..\SDL-1.2.5\include\sdl.h"
#include "..\SDL-1.2.5\include\SDL_endian.h"

void Slock(SDL_Surface *screen)
{
    if (SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0)
        return;
}


void Sulock(SDL_Surface *screen)
{
    if (SDL_MUSTLOCK(screen))
        SDL_UnlockSurface(screen);
}


void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B)
{
    Uint32 color = SDL_MapRGB(screen->format, R, G, B);

    if (SDL_MUSTLOCK(screen) && SDL_LockSurface(screen) < 0)
        return;

    switch (screen->format->BytesPerPixel) {
        case 1: { /* 8-bpp */
            Uint8 *bufp;

            bufp = (Uint8 *)screen->pixels + y * screen->pitch + x;
            *bufp = color;
        }
        break;

        case 2: { /* 15-bpp lub 16-bpp */
            Uint16 *bufp;

            bufp = (Uint16 *)screen->pixels + y * screen->pitch / 2 + x;
            *bufp = color;
        }
        break;

        case 3: { /* powolony tryb 24-bpp */
            Uint8 *bufp;

            bufp = (Uint8 *)screen->pixels + y * screen->pitch + x * 3;
            if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {
                bufp[0] = color;
                bufp[1] = color >> 8;
                bufp[2] = color >> 16;
            } else {
                bufp[2] = color;
                bufp[1] = color >> 8;
                bufp[0] = color >> 16;
            }
        }
        break;

        case 4: { /* 32-bpp */
            Uint32 *bufp;

            bufp = (Uint32 *)screen->pixels + y * screen->pitch / 4 + x;
            *bufp = color;
        }
        break;
    }

    if (SDL_MUSTLOCK(screen))
        SDL_UnlockSurface(screen);
}


enum {
    MAXX = 512,  /* rozmiar planszy */
    MAXY = 512
};


/* zawartosc pojedynczej komorki */
typedef struct _komorka {
    char stan;
    int czas;
    int miliczas;
} komorka;

komorka plansza[MAXX][MAXY];  /* plansza aktualna */
komorka plansza2[MAXX][MAXY]; /* plansza po przeksztalceniach */


int main(int argc, char* argv[])
{
    /* losowe tworzenie planszy poczatkowej */
    for (int x = 0; x < MAXX; x++)
        for (int y = 0; y < MAXY; y++) {
            int w = rand() % 9;
            plansza[x][y].miliczas = plansza2[x][y].miliczas = 0;
            plansza[x][y].czas = plansza2[x][y].czas = 0;

            if (w < 3)
                plansza[x][y].stan = 'E', plansza[x][y].miliczas = rand() % 100;
            else if (w == 4)
                plansza[x][y].stan = 'G';
            else if (w == 5)
                plansza[x][y].stan = 'W';
            else
                plansza[x][y].stan = 'F'; 

            plansza2[x][y].stan = plansza[x][y].stan;
        }

    /* inicjalizacja biblioteki SDL */
    SDL_Init(SDL_INIT_VIDEO);
    atexit ( SDL_Quit ) ;
    SDL_Surface *pSurface = SDL_SetVideoMode(MAXX, MAXY, 0, SDL_ANYFORMAT);
    SDL_Event event;
    SDL_WM_SetCaption("Pożar lasu", NULL);

    while (1) {

        Slock(pSurface);

        for (x = 1; x < MAXX - 1; x++)
            for (int y = 1; y < MAXY - 1; y++) {

                /* zmiana stanu automatu */
                if (plansza[x][y].stan == 'I' && plansza[x][y].czas == 0)
                    plansza2[x][y].stan = 'E',
                    plansza2[x][y].czas = 0,
                    plansza2[x][y].miliczas = rand() % 100;
                else if (plansza[x][y].stan == 'E' && plansza[x][y].czas == 1)
                    plansza2[x][y].stan = 'G',
                    plansza2[x][y].czas = 2;
                else if (plansza[x][y].stan == 'G' && plansza[x][y].czas == 4)
                    plansza2[x][y].stan = 'W',
                    plansza2[x][y].czas = 5;
                else if (plansza[x][y].stan == 'W' && plansza[x][y].czas == 49)
                    plansza2[x][y].stan = 'F',
                    plansza2[x][y].czas = 50;
 
                /* wyswietlanie komorki na ekranie */
                switch(plansza[x][y].stan) {
                    case 'I': DrawPixel(pSurface, x, y, 200 + plansza[x][y].czas * 3, 0, 0);
                              break;
                    case 'E': DrawPixel(pSurface, x, y, 166, 124, 82);
                              break;
                    case 'G': DrawPixel(pSurface, x, y, 0, 150 + plansza[x][y].czas * 25, 0);
                              break;
                    case 'W': DrawPixel(pSurface, x, y, 0, 200 + plansza[x][y].czas, 0);
                              break;
                    case 'F': DrawPixel(pSurface, x, y, 0, 255, 0);
                              break;
                }


                /* podpalanie lasu */
                if (plansza[x][y].stan == 'I' && plansza[x][y].czas != 0) {
                    if (plansza[x][y].czas > 0 && plansza2[x][y].czas)
                        plansza2[x][y].czas--;

                    char t[] = "FWG";
                    int c[] = { 15, 3, 3 };

                    for (int i = 0; i < 3; i++) {
                        if (plansza[x-1][y].stan == t[i])
                            plansza2[x-1][y].stan = 'I',
                            plansza2[x-1][y].czas = c[i],
                            plansza2[x-1][y].miliczas = 0;
                        if (plansza[x][y-1].stan == t[i])
                            plansza2[x][y-1].stan = 'I',
                            plansza2[x][y-1].czas = c[i],
                            plansza2[x][y-1].miliczas = 0;
                        if (plansza[x][y+1].stan == t[i])
                            plansza2[x][y+1].stan = 'I',
                            plansza2[x][y+1].czas = c[i],
                            plansza2[x][y+1].miliczas = 0;
                        if (plansza[x+1][y].stan == t[i])
                            plansza2[x+1][y].stan = 'I',
                            plansza2[x+1][y].czas = c[i],
                            plansza2[x+1][y].miliczas = 0;
                    }				
                } 
            }

        Sulock(pSurface);
        SDL_Flip(pSurface);

        for (x = 0; x < MAXX; x++)
            for (int y = 0; y < MAXY; y++)
                plansza[x][y].stan = plansza2[x][y].stan,
                plansza[x][y].czas = plansza2[x][y].czas,
                plansza[x][y].miliczas = plansza2[x][y].miliczas;


        /* obsluga zdarzen */
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT)
                exit(0);

            if (event.type == SDL_MOUSEBUTTONDOWN)
                if (event.button.button == SDL_BUTTON_LEFT) {
                    plansza[event.button.x][event.button.y].stan = 'I',
                    plansza[event.button.x][event.button.y].czas = 1;
                } else if (event.button.x >= 3 && event.button.x <= MAXX - 4 &&
                           event.button.y >= 3 && event.button.y <= MAXY - 4)
                    for(int x = -3; x < 5; x++)
                        for(int y = -3; y < 5; y++)
                            plansza2[event.button.x+x][event.button.y+y].stan = 'E',
                            plansza2[event.button.x+x][event.button.y+y].czas = 0;
        }


        /* obsluga czasu */
        for(int x = 0; x < MAXX; x++)
            for(int y = 0; y < MAXY; y++)
                if (plansza[x][y].stan != 'I') {
                    plansza2[x][y].miliczas++;
                    if(plansza[x][y].miliczas > 300)
                        plansza2[x][y].miliczas = 0, plansza2[x][y].czas++;
                }
    }

    return 0;
}
w3cw3c
automatyka przemysłowa