/*====================================================================== Columns Copyright (C) 1999,2000 Daniel Heck This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. Daniel Heck dheck@ix.urz.uni-heidelberg.de ======================================================================*/ #include #include #include #ifndef __STDC__ #include #endif #include #include #include #define HIGHSCORE_X 10 #define HIGHSCORE_Y 30 #define HELP_X 430 #define HELP_Y 180 #define PREVIEW_X 530 #define PREVIEW_Y 30 #define SCORE_X 430 #define SCORE_Y 30 #define SCORE_W 80 #define SCORE_H 120 #define ARENA_W 5 #define ARENA_H 14 #define ARENA_X 250 #define ARENA_Y 5 #define TILE_W 28 #define TILE_H 28 #define NTILES 8 // eight different tiles char *find_datafile(char *filename) { static char *str = NULL; if (str != NULL) free(str); str = (char*) malloc(sizeof(DATADIR)+strlen(filename)+2); strcpy(str,DATADIR); strcat(str, "/"); strcat(str, filename); return str; } #define CLAMP(val,low,hi) ((val)<(low) ? (low) : (val)>(hi) ? (hi) : (val)) void tint_region(SDL_Surface *surface, SDL_Rect *rect, int rtint, int gtint, int btint) { int bypp = surface->format->BytesPerPixel; Uint8 *fb = (Uint8*)surface->pixels + rect->y*surface->pitch + rect->x*bypp; switch (bypp) { case 2: for (int j=rect->h; j; --j) { Uint16 *p = (Uint16*) fb; for (int i=rect->w; i; --i) { Uint8 r1, g1, b1; SDL_GetRGB(*p, surface->format, &r1, &g1, &b1); int r = r1 + rtint; int g = g1 + gtint; int b = b1 + btint; *p++ = SDL_MapRGB(surface->format, CLAMP(r,0,255), CLAMP(g,0,255), CLAMP(b,0,255)); } fb += surface->pitch; } break; default: printf("unsupported video format.\n"); } } /*---------------------------------------------------------------------- SOUND CODE. ----------------------------------------------------------------------*/ struct Wave { SDL_AudioSpec spec; Uint8 *data; Uint32 length; Uint8 *data_pos; Uint32 length_left; }; #define MAX_CHANNELS 8 static struct { Uint8 *pos[MAX_CHANNELS]; int left[MAX_CHANNELS]; int active_channels; bool no_sound; } audio_state; SDL_AudioSpec audio_spec; void audio_mixer(void *, Uint8 *stream, int len) { if (audio_state.active_channels == 0) return; for (int i=0; idata; audio_state.left[audio_state.active_channels] = wave->length; ++audio_state.active_channels; SDL_PauseAudio(0); } SDL_UnlockAudio(); } } Wave *audio_load(const char *fname) { if (audio_state.no_sound) return NULL; Wave *w = (Wave*) malloc(sizeof(Wave)); if (w != NULL) { if (SDL_LoadWAV(fname, &w->spec, &w->data, &w->length) == NULL) { fprintf(stderr, "couldn't load `%s': %s\n", fname, SDL_GetError()); free (w); w = NULL; } else { // convert audio data // doesn't work as expected -- bug in SDL? SDL_AudioCVT cvt; w->spec.size = w->length; if (SDL_BuildAudioCVT(&cvt, w->spec.format, w->spec.channels, w->spec.freq, audio_spec.format, audio_spec.channels, audio_spec.freq) < 0) { fprintf (stderr, "couldn't build audio convert structure: %s\n", SDL_GetError ()); } else { if ( cvt.len_mult == 1 ) { cvt.len = w->length; cvt.buf = w->data; } else { cvt.len = w->length; cvt.buf = (Uint8 *) malloc(cvt.len*cvt.len_mult); memcpy (cvt.buf, w->data, w->length); free(w->data); } if (SDL_ConvertAudio (&cvt) < 0) { fprintf (stderr, "couldn't convert audio: %s\n", SDL_GetError()); } else { w->data = cvt.buf; w->length = cvt.len_cvt; } } } } else { fprintf (stderr, "couldn't load `%s': out of memory\n", fname); } return w; } void audio_init () { audio_spec.freq = 22050; audio_spec.format = AUDIO_S8; audio_spec.channels = 1; audio_spec.samples = 1024; audio_spec.callback = audio_mixer; audio_spec.userdata = NULL; for (int i=0; iformat->BytesPerPixel; switch (bypp) { case 2: { Uint16 *p = (Uint16*)((Uint8*)sfc->pixels + y*sfc->pitch + x*bypp); *p = color; } break; case 4: { Uint32 *p = (Uint32*)((Uint8*)sfc->pixels + y*sfc->pitch + x*bypp); *p = color; } break; default: ; } } Font *load_font(const char *fname) { FILE *fp = fopen (fname, "rb"); if (fp == NULL) return NULL; if (fgetc (fp)!='O' || fgetc(fp)!='F' || fgetc(fp)!='N' || fgetc (fp)!='T') return NULL; // header not right Font *fnt = (Font *) malloc(sizeof(Font)); if (fnt == NULL) return NULL; Uint8 *data[256]; for (int i=0; i<256; i++) { data[i] = NULL; fnt->w[i] = fnt->h[i]= fnt->x[i] = 0; } // read character chunks one by one int total_width = 0; while (fgetc(fp)=='O' && fgetc(fp)=='C' && fgetc(fp)=='H' && fgetc(fp)=='R') { int c = fgetc (fp); fnt->w[c] = fgetc(fp)<<8 | fgetc(fp); fnt->h[c] = fgetc(fp)<<8 | fgetc(fp); int size = fnt->w[c]*fnt->h[c]*2; data[c] = (Uint8*) malloc (size); // we're assuming 16 bit data here if (data[c] == NULL) break; fread (data[c], size, 1, fp); total_width += fnt->w[c]; if (fnt->h[c]>fnt->strut) fnt->strut = fnt->h[c]; } fclose (fp); /* Allocate a new surface and put the font data on it*/ fnt->surface = SDL_AllocSurface(SDL_SWSURFACE, total_width, fnt->strut, 16, 0, 0, 0, 0); if (fnt->surface != NULL) { int xoff = 0; for (int i=0; i<256; xoff+=fnt->w[i], i++) { Uint8 *p = data[i]; if (fnt->w[i] == 0) continue; fnt->x[i] = xoff; for (int y=0; yh[i]; y++) { for (int x=0; xw[i]; x++) { Uint32 col = *p++; col |= (*p++) << 8; set_pixel(fnt->surface, x+xoff, y, col); } } } SDL_SetColorKey(fnt->surface, SDL_SRCCOLORKEY, 0); } for (int i=0; i<256; i++) if (data[i] != NULL) free (data[i]); return fnt; } void put_char (SDL_Surface *sfc, Font *fnt, int x, int y, char c) { SDL_Rect sr, dr; sr.x = fnt->x[c]; sr.y = 0; dr.w = sr.w = fnt->w[c]; dr.h = sr.h = fnt->h[c]; dr.x = x; dr.y = y; SDL_BlitSurface(fnt->surface, &sr, sfc, &dr); } void put_string (SDL_Surface *sfc, Font *fnt, int x, int y, char *str) { int xpos = x; char *p = str; while (*p) { if (*p == ' ') xpos += fnt->strut/3; else { put_char(sfc, fnt, xpos, y, *p); xpos += fnt->w[(int)*p] +1; } p++; } } /*====================================================================== HIGHSCORE ======================================================================*/ struct highscore_entry { char name[30]; int score; }; #define HIGHSCORE_ENTRIES 10 highscore_entry highscore[HIGHSCORE_ENTRIES]; void highscore_save() { char *fname = find_datafile("columns.hsc"); FILE *fp = fopen(fname,"wb"); if (fp != NULL) { for (int i=0; i= highscore[i].score) break; } return i==HIGHSCORE_ENTRIES ? -1 : i; } void highscore_insert(char *name, int score) { int i = highscore_find_rank(score); if (i >= 0) { memmove(&highscore[i+1], &highscore[i], (HIGHSCORE_ENTRIES-i-1)*sizeof(highscore_entry)); strncpy(highscore[i].name, name, sizeof(highscore[0].name)-1); (highscore[i].name)[29] = '\0'; highscore[i].score = score; } } /*====================================================================== THE MAIN PROGRAM. ======================================================================*/ /*---------------------------------------- Types. ----------------------------------------*/ struct { int changed; int x, y; int oldx, oldy; } block; enum snd_e { snd_drop, snd_bye, snd_rotate, snd_level, snd_move, snd_remove, snd_magic, snd_hello, snd_perfect, snd_applause, snd_COUNT }; class a2 { public: int Width, Height; int *Array; a2(int w, int h) : Width(w), Height(h) { Array = new int[Width*Height]; clear(); } void clear() { for (int i=Width*Height-1; i>=0; --i) Array[i] = 0; } int get(int x, int y) { if (x<0 || y<0 || x>=Width || y>=Height) return -1; else return Array[x + y*Width]; } int& operator()(int x, int y) { return Array[x + y*Width]; } void set(int x, int y, int val) { Array[x+y*Width] = val; } }; /*---------------------------------------- Global variables. ----------------------------------------*/ /* Data */ SDL_Surface *screen; SDL_Surface *background; SDL_Surface *tiles; SDL_Rect tilerect[NTILES]; Font *small_font, *big_font; Font *big_blue; Wave *sound_effects[snd_COUNT]; char *background_file = NULL; char *username; /* Game state */ int cur_block[3]; int nxt_block[3]; int score; int colors = 5; int level; // between 0 and 9 a2 arena (ARENA_W, ARENA_H); a2 flags (ARENA_W, ARENA_H); int highlighted_highscore = -1; /* Flags */ bool leave_program = false; bool show_preview = true; bool no_sound = false; /* Static tables */ unsigned int speed[] = { 1000,900,800,700,600,500,400,270,170,130,100 }; /*---------------------------------------- Functions. ----------------------------------------*/ void fatal(char *str, ...) { va_list ap; va_start (ap, str); vfprintf (stderr, str, ap); va_end (ap); exit(1); } #define FLAG_BLINK 0x1 #define FLAG_CHANGED 0x2 #define FLAG_WHITE 0x4 int get_flag(int x, int y, int mask) { return (flags(x,y) & mask) != 0; } void set_flag(int x, int y, int mask) { flags(x,y) |= mask; } void clear_flag(int x, int y, int mask) { flags(x,y) &= ~mask; } void toggle_flag(int x, int y, int mask) { flags(x,y) ^= mask; } void clear_flag(int mask) { for (int y=0; ystrut+3; char str[100]; sprintf (str, "%d", score); put_string (screen, big_font, SCORE_X, y, str); y+= big_font->strut; y+= small_font->strut/2; put_string (screen, small_font, SCORE_X, y, "level"); sprintf (str, "%d", level); y+= small_font->strut; put_string (screen, big_font, SCORE_X, y, str); y+= big_font->strut; SDL_UpdateRect (screen, SCORE_X, SCORE_Y, SCORE_W, y-SCORE_Y); } void draw_tile(int x, int y, int tile) { SDL_Rect sr, dr; sr.x = dr.x = x; sr.y = dr.y = y; sr.w = dr.w = TILE_W; sr.h = dr.h = TILE_H; SDL_BlitSurface(tiles, &tilerect[tile], screen, &dr); } void draw_tile_light(int x, int y, int tile) { SDL_SetAlpha(tiles, SDL_SRCALPHA, 100); draw_tile(x,y, tile); SDL_SetAlpha(tiles, 0, 0); } void draw_block () { SDL_Rect sr, dr; if (block.oldx != block.x || block.oldy != block.y) { sr.x = dr.x = block.oldx*TILE_W + ARENA_X; sr.y = dr.y = block.oldy*TILE_H + ARENA_Y; sr.w = dr.w = TILE_W; sr.h = dr.h = TILE_H * 3; SDL_BlitSurface (background, &sr, screen, &dr); block.changed = true; } if (block.changed) { int i; for (i=0; i<3; i++) { sr.x = dr.x = block.x*TILE_W+ARENA_X; sr.y = dr.y = (block.y+i)*TILE_H+ARENA_Y; sr.w = dr.w = TILE_W; sr.h = dr.h = TILE_H; SDL_BlitSurface (background, &sr, screen, &dr); draw_tile(block.x*TILE_W+ARENA_X, (block.y+i)*TILE_H+ARENA_Y, cur_block[i]); } dr.x = block.oldx*TILE_W + ARENA_X; dr.y = block.oldy*TILE_H + ARENA_Y; dr.w = TILE_W; dr.h = TILE_H * 3; SDL_UpdateRects(screen, 1, &dr); dr.x = block.x*TILE_W + ARENA_X; dr.y = block.y*TILE_H + ARENA_Y; SDL_UpdateRects (screen, 1, &dr); block.changed = false; } } void draw_arena_field(int x, int y) { SDL_Rect sr,dr; sr.x = dr.x = x*TILE_W + ARENA_X; sr.y = dr.y = y*TILE_H + ARENA_Y; sr.w = dr.w = TILE_W; sr.h = dr.h = TILE_H; SDL_BlitSurface(background, &sr, screen, &dr); dr.x = x*TILE_W + ARENA_X; dr.y = y*TILE_H + ARENA_Y; dr.w = TILE_W; dr.h = TILE_H; if (get_flag(x,y, FLAG_WHITE)) draw_tile_light(dr.x, dr.y, arena.get(x,y)); else draw_tile(dr.x, dr.y, arena.get(x,y)); SDL_UpdateRects(screen, 1, &dr); } void draw_arena_field_light(int x, int y) { SDL_SetAlpha(tiles, SDL_SRCALPHA, 100); draw_arena_field(x,y); SDL_SetAlpha(tiles, 0, 0); } void draw_arena() { for (int y=0; ystrut; int entry = 0; for (int rank=1; rank<=HIGHSCORE_ENTRIES; rank++) { sprintf(str, "%d.", rank); if (rank-1 == highlighted_highscore) { put_string(screen, big_font, x, y, str); put_string(screen, small_font, x+30, y, username); sprintf(str, "%d", score); } else { put_string(screen, small_font, x, y, str); put_string(screen, small_font, x+30, y, highscore[entry].name); sprintf(str, "%d", highscore[entry].score); entry++; } put_string(screen, small_font, x+170, y, str); y+=big_font->strut; } r.x = HIGHSCORE_X; r.y = HIGHSCORE_Y; r.w = 240; r.h = 360; SDL_UpdateRects(screen, 1, &r); } void draw_preview() { SDL_Rect sr, dr; sr.x = dr.x = PREVIEW_X; sr.y = dr.y = PREVIEW_Y + small_font->strut+3; sr.w = dr.w = TILE_W; sr.h = dr.h = TILE_H*3; SDL_BlitSurface(background, &sr, screen, &dr); if (show_preview) { put_string(screen, small_font, PREVIEW_X, PREVIEW_Y, "preview"); for (int i=0; i<3; i++) { dr.x = PREVIEW_X; dr.y = PREVIEW_Y + i*TILE_H + small_font->strut+3; dr.w = TILE_W; dr.h = TILE_H; SDL_BlitSurface(tiles, &tilerect[nxt_block[i]], screen, &dr); } } SDL_UpdateRect(screen, PREVIEW_X, PREVIEW_Y, TILE_W, TILE_H*3+small_font->strut+3); } void draw_help () { int x = HELP_X; int y = HELP_Y; int s1 = big_font->strut; int s2 = small_font->strut; int s3 = s1; put_string (screen, small_font, x, y, "start game"); y+=s2; put_string (screen, big_font, x, y, "S/ENTER"); y+=s3; put_string (screen, small_font, x, y, "leave game"); y+=s2; put_string (screen, big_font, x,y, "Q/ESCAPE"); y+=s3; put_string (screen, small_font, x, y, "move/rotate"); y+=s2; put_string (screen, big_font, x, y, "ARROW KEYS"); y+=s3; put_string (screen, small_font, x, y, "toggle preview/pause"); y+=s2; put_string (screen, big_font, x, y, "V/ P"); } void draw_screen() { SDL_Rect dr; dr.x = dr.y = 0; dr.w = background->w; dr.h = background->h; SDL_BlitSurface (background, NULL, screen, &dr); draw_help(); draw_arena(); draw_block(); draw_preview(); draw_score(); draw_highscore(); SDL_UpdateRect(screen, 0, 0, 0, 0); } /*---------------------------------------------------------------------- GAME CODE. ----------------------------------------------------------------------*/ int mark_triple_match(int x1, int y1, int x2, int y2, int x3, int y3) { int a = arena.get(x1,y1); if (a > 0 && a == arena.get(x2,y2) && a == arena.get(x3,y3)) { set_flag(x1, y1, FLAG_BLINK); set_flag(x2, y2, FLAG_BLINK); set_flag(x3, y3, FLAG_BLINK); return 1; } else return 0; } /* Mark any occurrence of three or more adjacent stones with the same color. */ int mark_matches() { int matches = 0; int x, y; clear_flag(FLAG_BLINK); // horizontal matches for (y=0; y 0) { play_sound(snd_remove); /* Increase the score */ for (y=0; y=0; --y) { while (get_flag(x,y, FLAG_BLINK)) { for (int i=y; i>=1; --i) { arena(x,i) = arena(x,i-1); flags(x,i) = flags(x,i-1); set_flag(x,i,FLAG_CHANGED); } clear_flag(x,0, FLAG_BLINK | FLAG_CHANGED); } if (arena.get(x,y) == 0) break; } } draw_arena(); /* Give a special bonus for removing all stones */ if (score > 0) { for (y=0; y 0) goto no_bonus; play_sound(snd_applause); play_sound(snd_perfect); score += (level+1) * 20; } no_bonus: ; } score+=level+1; highlighted_highscore = highscore_find_rank(score); draw_highscore(); if (total_matches >= 14) play_sound(snd_applause); else if (total_matches > 10) play_sound(snd_perfect); } bool arena_free(int x, int y) { if (y+3 >ARENA_H) return false; else return (arena.get(x,y)==0 && arena.get(x,y+1)==0 && arena.get(x,y+2)==0); } void init_block() { nxt_block[0] = rand() % colors +1; nxt_block[1] = rand() % colors +1; nxt_block[2] = rand() % colors +1; } void new_block() { block.oldx = block.x = ARENA_W/2; block.oldy = block.y = 0; block.changed = true; cur_block[0] = nxt_block[0]; cur_block[1] = nxt_block[1]; cur_block[2] = nxt_block[2]; init_block (); } void make_screenshot () { static int cnt = 0; char fname[256]; sprintf(fname, "col%03d.bmp", cnt); printf("%s\n", fname); FILE *fp = fopen(fname, "rb"); while (fp != NULL && cnt < 999) { fclose (fp); cnt++; sprintf(fname, "col%03d.bmp", cnt); printf("%s\n", fname); fp = fopen(fname, "rb"); } if (cnt < 999) SDL_SaveBMP(screen, fname); else fclose(fp); SDL_Delay (100); } bool leave_mainloop; bool drop; Uint32 time_since_step; Uint32 time_since_leveljump; int pause_block_bak[3]; Uint32 pause_time_since_blink; bool game_paused; int pause_blink_flag; void pause_start() { for (int i=0; i<3; i++) pause_block_bak[i] = cur_block[i]; pause_time_since_blink = 0; pause_blink_flag = 1; game_paused = true; } void pause_update(Uint32 dtime) { SDL_Event e; if (SDL_PollEvent (&e)) { if (e.type == SDL_KEYDOWN) { game_paused = false; for (int i=0; i<3; i++) cur_block[i] = pause_block_bak[i]; draw_block(); return; } } pause_time_since_blink += dtime; if (pause_time_since_blink > 300) { if (pause_blink_flag) for (int i=0; i<3; i++) cur_block[i] = 7; else { for (int i=0; i<3; i++) cur_block[i] = pause_block_bak[i]; } block.changed = true; draw_block(); pause_blink_flag = !pause_blink_flag; pause_time_since_blink = 0; } } void init_game() { static bool flag = false; if (flag) { play_sound(snd_magic); for (int y=ARENA_H-1; y>=0; y--) { for (int x=0; x 1000*30 && level < 10) { time_since_leveljump = 0; play_sound(snd_level); level++; draw_score(); } } void eventhandler_update(Uint32 dtime) { SDL_Event e; if (!SDL_PollEvent(&e)) return; if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_p: pause_start(); break; case SDLK_ESCAPE: case SDLK_q: leave_mainloop = true; break; case SDLK_F2: make_screenshot(); break; case SDLK_v: show_preview = !show_preview; draw_preview(); break; case SDLK_SPACE: if (!drop) { play_sound(snd_drop); drop = true; } break; case SDLK_LEFT: if (block.x>0 && arena_free(block.x-1, block.y)) { block.x--; play_sound(snd_move); } break; case SDLK_RIGHT: if (block.x < ARENA_W-1 && arena_free(block.x+1, block.y)) { block.x++; play_sound(snd_move); } break; case SDLK_UP: { int a = cur_block[0]; cur_block[0] = cur_block[1]; cur_block[1] = cur_block[2]; cur_block[2] = a; block.changed = true; play_sound(snd_rotate); } break; case SDLK_DOWN: { int a = cur_block[0]; cur_block[0] = cur_block[2]; cur_block[2] = cur_block[1]; cur_block[1] = a; block.changed = true; play_sound(snd_rotate); } break; default: ; } } } void block_update(Uint32 dtime) { time_since_step += dtime; if (time_since_step > speed[level] || (drop && time_since_step>30)) { time_since_step = 0; // try to move the block one position down if (arena_free(block.x, block.y+1)) block.y++; else { draw_block(); arena.set(block.x, block.y, cur_block[0]); arena.set(block.x, block.y+1, cur_block[1]); arena.set(block.x, block.y+2, cur_block[2]); check_arena(); new_block(); if (!arena_free (block.x, block.y)) leave_mainloop = true; drop = false; draw_arena(); draw_preview(); draw_score(); SDL_Delay(100); } } draw_block(); } void game_update(Uint32 dtime) { block.oldx = block.x; block.oldy = block.y; if (game_paused) pause_update(dtime); else { eventhandler_update(dtime); arena_update(dtime); block_update(dtime); levelno_update(dtime); } } void game_end() { play_sound(snd_magic); highlighted_highscore = -1; highscore_insert(username, score); draw_highscore(); for (int y=ARENA_H-1; y>=0; y--) { for (int x=0; xw; dr.h = background->h; SDL_BlitSurface(background, NULL, screen, &dr); draw_help(); draw_preview(); draw_score(); draw_highscore(); SDL_UpdateRect(screen, 0, 0, 0, 0); } void fadein_effect() { } void fadeout_effect() { SDL_Delay(800); } void mainmenu() { play_sound(snd_hello); draw_mainmenu (); leave_program = false; while (!leave_program) { SDL_Event e; if (SDL_PollEvent (&e)) { if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_RETURN: case SDLK_s: game(); break; case SDLK_q: case SDLK_ESCAPE: leave_program = true; break; default: break; // do nothing } } else if(e.type == SDL_QUIT) { leave_program = true; return; } } SDL_Delay (10); } play_sound(snd_bye); fadeout_effect(); } void init_sound() { if (no_sound) return; audio_init(); sound_effects[snd_drop] = audio_load(find_datafile("drop.wav")); sound_effects[snd_rotate] = audio_load(find_datafile("rotate.wav")); sound_effects[snd_move] = audio_load(find_datafile("move.wav")); sound_effects[snd_magic] = audio_load(find_datafile("magic.wav")); sound_effects[snd_hello] = audio_load(find_datafile("hello.wav")); sound_effects[snd_perfect] = audio_load(find_datafile("perfect.wav")); sound_effects[snd_applause] = audio_load(find_datafile("applause.wav")); sound_effects[snd_remove] = audio_load(find_datafile("remove.wav")); sound_effects[snd_level] = audio_load(find_datafile("level.wav")); sound_effects[snd_bye] = audio_load(find_datafile("bye.wav")); } void highlight_arena() { SDL_Rect r; r.x = ARENA_X-5; r.y = 0; r.w = ARENA_W*TILE_W+10; r.h = background->h; tint_region(background, &r, 70, 70, 70); } /* load bitmaps */ void init_gfx () { SDL_Surface *img; img = SDL_LoadBMP(find_datafile("tiles.bmp")); if (img == NULL) fatal("Couldn't load `tiles.bmp'.\n"); tiles = SDL_DisplayFormat(img); SDL_FreeSurface(img); SDL_SetColorKey(tiles, SDL_SRCCOLORKEY, 0); if (background_file == NULL) background_file = find_datafile("bg.bmp"); FILE *fp = fopen(background_file, "rb"); background = NULL; if (fp != NULL) { fclose (fp); img = SDL_LoadBMP(background_file); if (img == NULL) { fprintf (stderr, "couldn't load `bg.bmp': %s\n", SDL_GetError ()); } else { background = SDL_DisplayFormat(img); SDL_FreeSurface(img); } } /* Use a black surface if the background picture could not be loaded. */ if (background == NULL) { background = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480, 16, 0, 0, 0, 0); SDL_Rect dr; dr.x = dr.y = 0; dr.w = background->w; dr.h = background->h; SDL_FillRect(background, &dr, 0); } highlight_arena(); } void init_fonts() { /* Load font data. */ small_font = load_font(find_datafile("small.fnt")); big_font = load_font(find_datafile("big.fnt")); if (small_font == NULL || big_font == NULL) { fprintf(stderr, "couldn't load fonts\n"); exit (1); } } void eval_args(int argc, char **argv) { bool show_usage = false; for (int i=1; i