/* XBubble - xbubble.c Copyright (C) 2002 Ivan Djelic 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 */ #include #include #include #include #include #include #include #include "setting.h" #include "gettext.h" /* #include */ #include "cell.h" #include "game.h" #include "timer.h" #include "screens.h" #include "init.h" Display *display; Visual *visual; Window root; Window win; int screen; int depth; Colormap colormap; int scale; int win_width; int win_height; int fps; unsigned long frame_duration; char *data_dir; char *theme; int colors[NB_CELLS]; int nb_levels; int level[MAX_NB_LEVELS][NB_CELLS]; #define level_handicap(X) ( DEFAULT_HANDICAP + 3000*( NORMAL - (X))) void usage() { printf(_("Usage: xbubble [-d display] [-s scale] [-f framerate] [-r resourcepath] [-t theme]\n\n")); exit(1); } static void create_randome_level( int nb_rows ) { int i; /* preload bubbles */ for ( i = 0; i < nb_rows*COLS; i++ ) colors[i] = rnd( NB_COLORS ) + 1; for ( i = nb_rows*COLS; i < NB_CELLS; i++ ) colors[i] = 0; } void play_single_player_game( int *handicap ) { int i; int won = 1; int again = 1; int score[2] = { 0, 0 }; RuleSet_t ruleset=DEFAULT_RULE_SET; enum GameResult result; Game game; ruleset.max_fire_delay = handicap[0]; for ( i = 0; again && i < nb_levels; won && i++ ) { game = new_game( SINGLE_PLAYER, &ruleset, level[i], i+1, score, NORMAL ); result = play_game(game); won = ( result == PLAYER1_WON ); again = ( result != ABORTED ); delete_game( game, again && ( !won || ( i+1 < nb_levels ))); } if ( won ) printf(_("CONGRATULATIONS !!!\n")); } void play_challenge_game( int *handicap ) { enum GameResult result; int level=1; int score[2] = { 0, 0 }; RuleSet_t ruleset=DEFAULT_RULE_SET; Game game; ruleset.max_fire_delay = handicap[0]; /* preload bubbles */ do { create_randome_level(5); game = new_game( SINGLE_PLAYER, &ruleset, colors, level, score, NORMAL ); result=play_game(game); if (result == PLAYER1_WON) level++; delete_game( game, False ); } while (result != ABORTED); } void play_match( enum GameMode mode, int *handicap, enum Level level ) { int round; int done; int score[2]; int games[2] = { 0, 0 }; int rounds[2] = { 0, 0 }; RuleSet_t ruleset[2]={ DEFAULT_RULE_SET, DEFAULT_RULE_SET }; enum GameResult result; Game game; ruleset[0].max_fire_delay = handicap[0]; ruleset[1].max_fire_delay = handicap[1]; do { score[0] = 0; score[1] = 0; done = 0; for ( round = 1; !done; round++ ) { /* preload bubbles */ create_randome_level(5); game = new_game( mode, ruleset, colors, round, score, level); result = play_game(game); done = score[1]==2 || score[0]==2 || result == ABORTED; //not_done= (!(((score[1]>=5)&&(score[1]-score[0]>1)) || // ((score[0]>=5)&&(score[0]-score[1]>1))) && // ( result != ABORTED )); delete_game( game, !done ); } /* update stats */ rounds[0] += score[0]; rounds[1] += score[1]; if ( result != ABORTED ) { games[0] += ( score[0] > score[1] )? 1 : 0 ; games[1] += ( score[1] > score[0] )? 1 : 0 ; } } while ( screen_2p( mode, rounds, games ) == S3_CONTINUE ); } void play_demo( enum Level level ) { int not_done; RuleSet_t ruleset[2]={ DEFAULT_RULE_SET, DEFAULT_RULE_SET }; int score[2] = { 0, 0 }; Game game; ruleset[0].max_fire_delay = level_handicap(NORMAL); ruleset[1].max_fire_delay = level_handicap(NORMAL); do { create_randome_level(5); game = new_game( DEMO, ruleset, colors, 1, score, level ); not_done = ( play_game(game) != ABORTED ); delete_game( game, not_done ); } while ( not_done ); } void play_xbubble() { int quit, level; int choice[2]; int handicap[2]; quit = 0; while ( ! quit ) { handicap[0] = level_handicap(NORMAL); handicap[1] = level_handicap(NORMAL); switch ( screen_main() ) { case S1_SINGLE_PLAYER: /* select handicap */ choice[0] = screen_1p_handicap(); if ( choice[0] != S5_ESCAPE ) { handicap[0] = level_handicap( choice[0] ); play_single_player_game( handicap ); } break; case S1_TWO_PLAYERS: /* select players handicaps */ if ( screen_2p_handicap(choice) == S4_OK ) { /* player 1 is on the left */ handicap[0] = level_handicap( choice[1] ); handicap[1] = level_handicap( choice[0] ); play_match( TWO_PLAYERS, handicap, NORMAL ); } break; case S1_PLAYER_VS_COMPUTER: /* select computer skill */ level = screen_computer_skill(); if ( level != S2_ESCAPE ) { level += VERY_EASY - S2_VERY_EASY; play_match( PLAYER_VS_COMPUTER, handicap, level ); } break; case S1_CHALLENGE: /* select handicap */ choice[0] = screen_1p_handicap(); if ( choice[0] != S5_ESCAPE ) { handicap[0] = level_handicap( choice[0] ); play_challenge_game( handicap ); } break; case S1_DEMO: play_demo( VERY_HARD ); break; case S1_ESCAPE: case S1_QUIT: quit = 1; break; default: break; } } } int main( int argc, char ** argv ) { int c; double zoom; char *display_name; char app_name[256]; int max_win_width; int pscale; struct timeval tv; XSizeHints xsh; XWMHints wm_hint; XClassHint class_hint; /* NLS nuisances */ #if ENABLE_NLS setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif /* default values */ fps = DEFAULT_FPS; data_dir = DATADIR; theme = "fancy"; pscale = 0; display_name = NULL; /* mtrace(); */ /* parse options */ while (( c = getopt( argc, argv, "s:f:r:t:d:" )) != -1 ) { switch (c) { case 's': /* scale */ if ( sscanf( optarg, "%d", &pscale ) != 1 ) { fprintf( stderr, _("Invalid scale: %s.\n"), optarg); usage(); } break; case 'f': /* frame rate */ if ( sscanf( optarg, "%d", &fps ) != 1 ) { fprintf( stderr, _("Invalid frame rate: %s.\n"), optarg); usage(); } break; case 'r': /* resources */ data_dir = optarg; break; case 't': /* themes */ theme = optarg; break; case 'd': /* display */ display_name = optarg; break; default: usage(); } } init_display( display_name ); /* adjust frame rate */ fps = clip( fps, 10, 100 ); frame_duration = get_closest_itimer_interval(1000000/fps); fps = 1000000 / frame_duration; /* adjust scale */ max_win_width = game_win_width(MAX_SCALE); if ( ! pscale ) /* automagically adjust window size to 100% of screen width */ pscale = DEFAULT_SCALE*WidthOfScreen(DefaultScreenOfDisplay(display))/max_win_width; pscale = clip( pscale, 5, 100 ); scale = pscale*MAX_SCALE/100; zoom = 1.0*scale/MAX_SCALE; win_width = game_win_width(scale); win_height = game_win_height(scale); /* create main window */ win = XCreateSimpleWindow( display, root, 0, 0, win_width, win_height,0,0,0); XSelectInput( display, win, ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask ); if ( depth == 8 ) XSetWindowColormap( display, win, colormap ); /* we don't want window resizing */ xsh.flags = PBaseSize | PMinSize | PMaxSize; xsh.min_width = xsh.max_width = xsh.base_width = win_width; xsh.min_height = xsh.max_height = xsh.base_height = win_height; XSetWMNormalHints( display, win, &xsh ); /* set window title name, name, class, etc. */ sprintf( app_name, _("XBubble @ %d fps v%s"), fps, VERSION ); XStoreName( display, win, app_name ); class_hint.res_name = "xbubble"; class_hint.res_class = "XBubble"; wm_hint.flags = InputHint | StateHint; wm_hint.input = True; wm_hint.initial_state = NormalState; XSetClassHint( display, win, &class_hint ); XSetWMHints( display, win, &wm_hint ); /* new randomize seed */ gettimeofday( &tv, NULL ); srand( tv.tv_usec ); splash_screen(zoom); play_xbubble(); cleanup_graphics(); XDestroyWindow( display, win ); if ( depth == 8 ) XFreeColormap( display, colormap ); XCloseDisplay( display ); return 0; }