// $Id: playerdata.cc,v 1.5 2006/08/07 17:24:48 matthew Exp $ // Fish Supper // Copyright (C) 2006 Matthew Clarke // // 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 "playerdata.h" // ******************* // *** CONSTRUCTOR *** // ******************* FS::PlayerData::PlayerData() { crystals_held_allocated = false; erase_rect.y = CRYSTALS_HELD_Y; erase_rect.w = CRYSTAL_WIDTH; erase_rect.h = CRYSTAL_HEIGHT; dest_rect.y = CRYSTALS_HELD_Y; dirty_rect.x = CRYSTALS_HELD_X_OFFSET; dirty_rect.y = CRYSTALS_HELD_Y; dirty_rect.h = CRYSTAL_HEIGHT; } // FS::PlayerData::PlayerData() // ****************** // *** DESTRUCTOR *** // ****************** FS::PlayerData::~PlayerData() { if (crystals_held_allocated) { delete [] crystals_held; } // if } // FS::PlayerData::~PlayerData() // ************************ // *** MEMBER FUNCTIONS *** // ************************ // ************************************************** /* void FS::PlayerData::reset(int n) { level = 1; // levels start at ONE!!! num_lives = STARTING_NUM_LIVES; score = 0; max_crystals = n; if (crystals_held_allocated) { delete [] crystals_held; } // if crystals_held = new CrystalColor[max_crystals]; crystals_held_allocated = true; //for (int i = 0; i < MAX_CRYSTALS_HELD; ++i) //{ // crystals_held[i] = crystals[i]; //} // for } // FS::PlayerData::reset() */ // ************************************************** void FS::PlayerData::reset(int start_level) { level = start_level; // levels start at ONE!!! num_lives = STARTING_NUM_LIVES; score = 0; } // FS::PlayerData::reset() // ************************************************** void FS::PlayerData::set_max_crystals(int mc) { max_crystals = mc; if (crystals_held_allocated) { delete [] crystals_held; } // if crystals_held = new CrystalColor[max_crystals]; crystals_held_allocated = true; // This only needs to be set once at the start of each new level. dirty_rect.w = (max_crystals * /*BLOCK_WIDTH*/CRYSTAL_WIDTH) + ((max_crystals - 1) * CRYSTALS_HELD_X_GAP); } // FS::PlayerData::set_max_crystals() // ************************************************** void FS::PlayerData::print_crystals_held() const { for (int i = 0; i < MAX_CRYSTALS_HELD; ++i) { std::cout << "crystal #" << i << ": "; switch ( crystals_held[i] ) { case C_RED: std::cout << "RED, "; break; case C_YELLOW: std::cout << "YELLOW, "; break; case C_BLUE: std::cout << "BLUE, "; break; case C_WHITE: std::cout << "WHITE, "; break; case C_NONE: std::cout << "NONE, "; break; } // switch } // for std::cout << std::endl; } // FS::PlayerData::print_crystals_held() // ************************************************** bool FS::PlayerData::is_allowed_on_log(LogColor lc, PlayDisplay * pd) { bool is_ok = false; // Quick check to see if player's holding a white crystal // and record index if they are. Can be used later as a // 'last resort'. int white_found = -1; for (int i = 0; i < max_crystals; ++i) { if ( crystals_held[i] == C_WHITE ) { white_found = i; } // if } // for switch (lc) { case L_RED: case L_YELLOW: case L_BLUE: for (int i = 0; i < max_crystals; ++i) { if ( crystals_held[i] == ((CrystalColor) lc) ) { crystals_held[i] = C_NONE; is_ok = true; break; } // if } // for break; case L_ORANGE: is_ok = check_crystals(C_RED, C_YELLOW); break; case L_GREEN: is_ok = check_crystals(C_BLUE, C_YELLOW); break; case L_PURPLE: is_ok = check_crystals(C_BLUE, C_RED); break; case L_BROWN: return true; // no need to tidy up! break; // Should never happen - just to avoid warnings from compiler... case L_BACKGROUND: break; } // switch // If we haven't got an exact colour-match, is there a white // crystal to save the day? if ( (!is_ok) && (white_found >= 0) ) { crystals_held[white_found] = C_NONE; is_ok = true; } // if if (is_ok) { tidy_up_crystals(); //draw_crystals_held(pd); } // if return is_ok; } // FS::PlayerData::is_allowed_on_log() // ************************************************** bool FS::PlayerData::check_crystals(CrystalColor color_0, CrystalColor color_1) { int color_0_index = -1; int color_1_index = -1; int i = 0; do { if ( crystals_held[i] == C_NONE ) { break; } else if ( crystals_held[i] == color_0 ) { color_0_index = i; } else if ( crystals_held[i] == color_1 ) { color_1_index = i; } // if ... else ++i; } while ( (color_0_index < 0 || color_1_index < 0) && (i < max_crystals) ); if ( color_0_index >= 0 && color_1_index >= 0 ) { crystals_held[color_0_index] = C_NONE; crystals_held[color_1_index] = C_NONE; return true; } else { return false; } // if ... else } // FS::PlayerData::check_crystals() // ************************************************** void FS::PlayerData::tidy_up_crystals() { int next_to_fill = 0; for (int i = 0; i < max_crystals; ++i) { if (crystals_held[i] != C_NONE) { if (i != next_to_fill) { crystals_held[next_to_fill] = crystals_held[i]; crystals_held[i] = C_NONE; } // if ++next_to_fill; } // if } // for } // FS::PlayerData::tidy_up_crystals() // ************************************************** FS::CrystalColor FS::PlayerData::add_crystal(CrystalColor cc, PlayDisplay * pd) { // Simple case - see if we've already got a spare 'slot'. for (int i = 0; i < max_crystals; ++i) { if (crystals_held[i] == C_NONE) { crystals_held[i] = cc; //draw_crystals_held(pd); return C_NONE; // nothing swapped } // if } // for // If get to here, no spare slot was found, so remove one from 'front' and // shift everything else left to make room. CrystalColor removed = crystals_held[0]; for (int i = 0; i < (max_crystals - 1); ++i) { crystals_held[i] = crystals_held[i+1]; } // for // Add new crystal to the end. crystals_held[max_crystals-1] = cc; //draw_crystals_held(pd); return removed; } // FS::PlayerData::add_crystal() // ************************************************** void FS::PlayerData::draw_crystals_held(PlayDisplay * pd) { for (int i = 0; i < max_crystals; ++i) { if (crystals_held[i] == C_NONE) { erase_rect.x = CRYSTALS_HELD_X_OFFSET + (i * CRYSTAL_WIDTH) + (i * CRYSTALS_HELD_X_GAP); pd->request_erase(&erase_rect); } else { dest_rect.x = CRYSTALS_HELD_X_OFFSET + (i * CRYSTAL_WIDTH) + (i * CRYSTALS_HELD_X_GAP); pd->request_blit( ((ImageIDs) (IMAGE_ID_CRYSTAL_OFFSET + crystals_held[i])), NULL, &dest_rect); } // if ... else } // for pd->request_update(dirty_rect); } // FS::PlayerData::draw_crystals_held() // ************************************************** void FS::PlayerData::set_crystals_held(CrystalColor * crystals, int n) { for (int i = 0; i < max_crystals; ++i) { if (i < n) { crystals_held[i] = crystals[i]; } else { crystals_held[i] = C_NONE; } // if ... else } // for } // FS::PlayerData::set_crystals_held() // ************************************************** // Returns true if there's another level to play, otherwise false. bool FS::PlayerData::inc_level() { ++level; return true; } // FS::PlayerData::inc_level() // ************************************************** // ************************************************** // ************************************************** // ************************************************** // **************************************************