/* * Gnome Set game - gsetgame.c * Copyright 2007 Kirill Gorelov * * 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. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "gsetgame.h" #include "ui.h" #include "cfg.h" #include "debug.h" #include "bgrnd.h" #include "records.h" struct gsetgame_stats game_stats; struct gsetgame_high_scores high_scores; /******************************************************************************/ /* Game logic functions */ /******************************************************************************/ static gint gset_tick(gpointer data) { switch (game_stats.state) { case GAME_ABANDONED: case GAME_COMPLETED: return 0; case GAME_PAUSED: return TRUE; default: game_stats.time++; /* XXX P2: Redrawing the entire play canvas every second * sounds like pure evil :( */ ui_draw_playcanvas(); } return TRUE; } void gset_new_game(GAME_TYPE type) { DBG(GAME_DEBUG, "Creating new game\n"); game_stats.num_sets = 0; game_stats.time = 0; game_stats.time_tag = 0; game_stats.state = GAME_PLAYING; game_stats.game_type = type; /* Initialize the deck and the pack */ cards_deck_init(&card_deck); /* cards_pack_init margins: left, right, top, bottom, spacing */ cards_pack_init(&card_pack, 5, 5, 24, 5, 5); /* Draw cards from the deck */ cards_pack_fill(&card_pack, &card_deck); /* Start counting time */ game_stats.time_tag = g_timeout_add (1000, &gset_tick, NULL); /* Resize cards accordingly */ ui_resize_cards(); /* It is possible that there are no sets among cards drawn from * the deck. If the automatic nosets assiatance is on it should * take care of this immediately */ if ((cfg.nosets_auto) && (!are_there_sets_left(&card_pack))) gset_game_no_sets_left(); } void gset_game_over(GAMESTATE newstate) { DBG(GAME_DEBUG, "Gave over...\n"); g_source_remove (game_stats.time_tag); cards_deck_cleanup(&card_deck); game_stats.state = newstate; /* update records table */ if (newstate == GAME_COMPLETED) { if (records_check_record(gset_current_records_handle(), game_stats.time, game_stats.num_sets) >= 0) { records_commit_record(gset_current_records_handle(), game_stats.time, game_stats.num_sets, ui_ask_player_name()); } } ui_draw_playcanvas(); } struct gsetgame_stats *gset_game_get_stats() { return &game_stats; } void gset_game_no_sets_left() { /* If there are no cards in the deck left the game is over */ if (cards_deck_is_empty(&card_deck)) { gset_game_over(GAME_COMPLETED); ui_draw_playcanvas(); return; } /* Now resize the pack adding 3 more cards (one line) */ if (!cards_pack_resize(&card_pack, card_pack.ncards_x + 1, card_pack.ncards_y)) { gset_msg("Error: Unable to resize the pack."); return; } else { GtkWidget *gsetdrawing=NULL; gsetdrawing = glade_xml_get_widget(ui.xml, "gsetdrawing"); cards_pack_resize_cards(&card_pack, ui.cards_image, gsetdrawing->allocation.width, gsetdrawing->allocation.height); cards_pack_fill(&card_pack, &card_deck); ui_draw_playcanvas(); } } gboolean gset_game_step() { DBG(GAME_DEBUG, "Game step.\n"); /* Check if a set's been selected */ if (card_pack.nactive == 3) { if (cards_pack_check_set(&card_pack)) { /* Increase the score */ game_stats.num_sets++; /* Remove selected cards */ cards_pack_remove_selected(&card_pack); /* Try to shrink the pack if it's larger than 4x3 */ if (card_pack.ncards_x > 4) { DBG(GAME_DEBUG, "Time to shink the pack...\n"); if (cards_pack_resize(&card_pack, card_pack.ncards_x - 1, card_pack.ncards_y)) { ui_resize_cards(); } } /* Draw cards from the deck to fill the pack */ /* XXX P2: Add more grace to drawing cards from the deck * I don't like them to appear immediately */ cards_pack_fill(&card_pack, &card_deck); /* Automatically check if there are no sets left if allowed */ if ((cfg.nosets_auto) && (!are_there_sets_left(&card_pack))) gset_game_no_sets_left(); } else { gset_msg(_("This is not a set!")); cards_pack_reset(&card_pack); } } /* Check whether the game is now finished */ return TRUE; } void gset_game_pause_toggle() { if (game_stats.state == GAME_PAUSED) { game_stats.state = game_stats.prev_state; game_stats.prev_state = GAME_PAUSED; } else { game_stats.prev_state = game_stats.state; game_stats.state = GAME_PAUSED; } ui_draw_playcanvas(); } gboolean gset_game_is_paused() { return (game_stats.state == GAME_PAUSED); } void gset_game_penalty(gint seconds) { game_stats.time += seconds; } GAME_TYPE gset_game_type() { return game_stats.game_type; } GAMESTATE gset_game_state() { return game_stats.state; } int gset_records_handle(GAME_TYPE gametype) { switch (gametype) { case GAME_CLASSIC: return high_scores.classic_high_score_handle; case GAME_PUZZLE: return high_scores.puzzle_high_score_handle; } return -1; } int gset_current_records_handle() { return gset_records_handle(gset_game_type()); } /******************************************************************************/ /* Main function */ /******************************************************************************/ int main(int argc, char *argv[]) { INFO("GSet Game starting...\n"); #ifdef ENABLE_NLS bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); textdomain(PACKAGE); #endif #if defined(GNOME) /* Initialize GNOME */ gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE, argc, argv, GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR, NULL); #elif defined(MAEMO) // XXX 2Do: add osso stuff #else gtk_init(&argc, &argv); #endif /* Set random seed */ srand((unsigned)time(NULL)); /* Start the Glade UI */ ui_load(); /* Initialize high scores tables */ records_table_init(); high_scores.classic_high_score_handle = records_table_new(10); high_scores.puzzle_high_score_handle = records_table_new(10); if ((high_scores.classic_high_score_handle < 0) || (high_scores.puzzle_high_score_handle < 0)) { printf("Error: can not create record tables\n"); return 1; } /* Load the config file */ cfg_load(); /* Apply loaded configuration settings */ ui_set_config(); /* Load the background */ bgrnd_load(cfg.bgrnd_img); /* Start the game */ ui_start(); gset_new_game(cfg.default_game); /* Enter the main event loop */ gtk_main(); /* Save current configuration */ cfg_save(); gset_game_over(GAME_ABANDONED); /* Free the global structures */ bgrnd_free(); cfg_free(); ui_free(); return 0; }