/* $Id: mapstuff.cpp,v 1.13 2005/06/28 13:55:20 chfreund Exp $ */ #include "mapstuff.hpp" /**********************************************************/ // setting attributes #define SATTR (Setting::COMMA_SEPARATED | \ Setting::EXPLICIT_ASSIGNMENT | \ Setting::CONFIG_FILE_ONLY) #define SATTRM (SATTR | Setting::MANDATORY) #define RND_SSTR(ID) MapStuff::m_rndSettingDef[ID].m_IDString #define FXD_SSTR(ID) MapStuff::m_fxdSettingDef[ID].m_IDString #define RND_STR2SET(ID) getSetting(RND_SSTR(ID)) #define FXD_STR2SET(ID) getSetting(FXD_SSTR(ID)) #define RANDOM_MAPSTUFF_SECTION "RANDOM" #define FIXED_MAPSTUFF_SECTION "FIXED" /**********************************************************/ const SettingDef MapStuff:: m_rndSettingDef[MapStuff::RND_NUM_SSDEFS+1] = { SettingDef("sets", NULL, Setting::STRING, 1, -1, SATTR), SettingDef("odds", NULL, Setting::INT, 1, -1, SATTR), SettingDef() }; const SettingDef MapStuff:: m_fxdSettingDef[MapStuff::FXD_NUM_SSDEFS+1] = { SettingDef("sets", NULL, Setting::STRING, 3, -1, SATTR), SettingDef("items", NULL, Setting::STRING, 5, -1, SATTR), SettingDef() }; /**********************************************************/ MapStuff::MapStuff( const Uint32 randomseed ) : m_Random(randomseed) { for( int i = 0; i < MapStuffSet::NUM_MATERIALS; i++ ) { m_MaterialPresent[i] = false; } } /**********************************************************/ MapStuff::~MapStuff() { reset(); } /**********************************************************/ int MapStuff::getRandomItem( const Sprite** item, int material ) { if( !CHECK( material < MapStuffSet::NUM_MATERIALS, "MapStuff::getRandomItem: material = %d is out of range " "-> ignored, choosing arbitrary item\n", material ) ) { material = MapStuffSet::UNDEFINED; } // check, if there are any map stuff sets if( m_randomSets.getSize() == 0 ) { *item = NULL; return MapStuffSet::UNDEFINED; } // check if the demanded material is present if( material != MapStuffSet::UNDEFINED && false == hasItemOfMaterial(material) ) { *item = NULL; return MapStuffSet::UNDEFINED; } int iset = 0; // choose map stuff set randomly, until the correct // material has been found do { iset = m_Random.getWeightedUint32(); } while( material > MapStuffSet::UNDEFINED && material != m_randomSets[iset]->getMaterial() ); *item = m_randomSets[iset]->getRandomItem(); return m_randomSets[iset]->getMaterial(); } /**********************************************************/ int MapStuff::getFixedItem( const int index, const Uint32 mapWidth, const Uint32 mapHeight, const Sprite **item, Sint32 &x, Sint32 &y ) { // check, if there are any map stuff sets if( m_fixedSets.getSize() == 0 ) { *item = NULL; return MapStuffSet::UNDEFINED; } if( !CHECK( 0 <= index && index < m_fixedDefs.getSize(), "MapStuff::getFixedItem: index [%d] is out of " "valid range [0,%d]\n", index, m_fixedDefs.getSize()-1 ) ) { item = NULL; return MapStuffSet::UNDEFINED; } // negative coordinates (x,y) mean: // position = (map width - x, map height - y) x = m_fixedDefs[index]->getX(); if( x < 0 ) x += mapWidth; x += m_Random.getSint32Between(-m_fixedDefs[index]->getDX(), m_fixedDefs[index]->getDX() ); y = m_fixedDefs[index]->getY(); if( y < 0 ) y += mapHeight; y += m_Random.getSint32Between(-m_fixedDefs[index]->getDY(), m_fixedDefs[index]->getDY() ); *item = m_fixedSets[m_fixedDefs[index]->getIndex()]->getRandomItem(); return m_fixedSets[m_fixedDefs[index]->getIndex()]->getMaterial(); } /**********************************************************/ bool MapStuff::load( const String& path, const String& configfile ) { reset(); DBG(2) INFO( "MapStuff::load: loading map stuff from \"%s\"\n", (char*)configfile ); return loadRandomSets( path, configfile ) && loadFixedSets( path, configfile ); } /**********************************************************/ bool MapStuff::loadRandomSets( const String& path, const String& configfile ) { const char fn[] = "MapStuff::loadRandomSets"; SettingDataBase settings; String fullpath = path; fullpath += '/'; fullpath += configfile; // restrict reading to random section settings.restrictToSection( RANDOM_MAPSTUFF_SECTION ); // read configuration for map stuff if( !CHECK(settings.readSettings(m_rndSettingDef, fullpath), "%s: could not read settings for map stuff\n", fn) // check correctness || !CHECK(settings.finalCheck(m_rndSettingDef), "%s: configuration for map stuff not complete\n", fn) ) { return false; } const Setting *odds = settings.getSetting(RND_SSTR(RND_ODDS_SSDEFS)), *sets = settings.getSetting(RND_SSTR(RND_SETS_SSDEFS)); // if there are no ore incomplete definitions for // random map stuff, simply skip it. if( !sets || !odds ) return true; // check correctness of set specification if( !CHECK(sets->getNumParameters() % 2 == 0, "%s: the specification of \"%s\" in file \"%s\" must consist " "of pairs (path,configfile)\n", fn, RND_SSTR(RND_SETS_SSDEFS), (char*)fullpath) ) { return false; } // load the map stuff sets for( int i = 0; i < sets->getNumParameters()/2; i++ ) { MapStuffSet* set = NULL; String mapstuffpath( path ); mapstuffpath += '/'; // create and load new map stuff set if( !CHECK( NULL != (set = NEW MapStuffSet(m_Random.getUint32()&0xffff)), "%s: could not create map stuff set object nr. %d\n", fn, i ) // load the new map stuff set || !CHECK( set->load((char*)(mapstuffpath+sets->getString(2*i )), (char*)( sets->getString(2*i + 1))), "%s: could not load map stuff set nr. %d: \"%s\", \"%s\"\n", fn, i, sets->getString(2*i), sets->getString(2*i + 1) ) ) { return false; } // register the material as present m_MaterialPresent[set->getMaterial()] = true; // insert in into the map stuff vector m_randomSets.append( set ); } // prepare the random number generator if( odds ) { // check, if number of odds and number of map stuff sets match if( CHECK( 2*odds->getNumParameters() == sets->getNumParameters(), "%s: number of specified map stuff sets (%d, setting " "\"%s\") and the number of specified odds (%d \"%s\") " "do not match -> using uniform distribution\n", fn, sets->getNumParameters() / 2, RND_SSTR(RND_SETS_SSDEFS), odds->getNumParameters(), RND_SSTR(RND_ODDS_SSDEFS) ) ) { // set the probability weights m_Random.setWeights( m_randomSets.getSize(), odds->getIntPtr() ); } else { return false; } } else { m_Random.setWeights( m_randomSets.getSize() ); } DBG(2) INFO( "%s: loaded %d random map stuff sets\n", fn, m_randomSets.getSize() ); return true; } /**********************************************************/ bool MapStuff::loadFixedSets( const String& path, const String& configfile ) { const char fn[] = "MapStuff::loadFixedSets"; SettingDataBase settings; String fullpath = path; fullpath += '/'; fullpath += configfile; // restrict reading to random section settings.restrictToSection( FIXED_MAPSTUFF_SECTION ); // read configuration for map stuff if( !CHECK(settings.readSettings(m_fxdSettingDef, fullpath), "%s: could not read settings for map stuff\n", fn) // check correctness || !CHECK(settings.finalCheck(m_fxdSettingDef), "%s: configuration for map stuff not complete\n", fn) ) { return false; } PointerVector fixedNames; const Setting *sets = settings.FXD_STR2SET(FXD_SETS_SSDEFS), *items = settings.FXD_STR2SET(FXD_ITEMS_SSDEFS); // if there are no ore incomplete definitions for // fixed map stuff, simply skip it. if( !sets || !items ) return true; // check correctness of set specification if( !CHECK(sets->getNumParameters() % 3 == 0, "%s: the specification of \"%s\" in file \"%s\" must consist " "of tripples (name,path,configfile)\n", fn, FXD_SSTR(FXD_SETS_SSDEFS), (char*)fullpath) ) { return false; } // check correctness of item specification if( !CHECK(items->getNumParameters() % 5 == 0, "%s: the specification of \"%s\" in file \"%s\" must " "consist of five tupples (name,x,y,dx,dy)\n", fn, FXD_SSTR(FXD_ITEMS_SSDEFS), (char*)fullpath) ) { return false; } // load the map stuff sets for( int i = 0; i < sets->getNumParameters()/3; i++ ) { MapStuffSet* set = NULL; String mapstuffpath( path ); mapstuffpath += '/'; // create and load new map stuff set if( !CHECK( NULL != (set = NEW MapStuffSet(m_Random.getUint32()&0xffff)), "%s: could not create map stuff set object nr. %d\n", fn, i ) // load the new map stuff set || !CHECK( set->load((char*)(mapstuffpath+sets->getString(3*i + 1)), (char*)( sets->getString(3*i + 2))), "%s: could not load map stuff set nr. %d: \"%s\", " "\"%s\", \"%s\"\n", fn, i, sets->getString(3*i ), sets->getString(3*i + 1), sets->getString(3*i + 2) ) ) { return false; } // DO NOT register the material as present, since these are // the fixed sets. // Insert in into the map stuff vector m_fixedSets.append( set ); // append the name of the map stuff set String *name = NEW String(sets->getString(3*i)); fixedNames.append( name ); } // load the list of items for( int i = 0; i < items->getNumParameters()/5; i++ ) { int ind = 0; // search index of item while( ind < fixedNames.getSize() ) { if( !strcmp(*fixedNames[ind], items->getString(5*i)) ) { break; } ind++; } if( !CHECK( ind < fixedNames.getSize(), "%s: item name \"%s\" could not be found in loaded" " list\n", fn, items->getString(5*i) ) ) { return false; } // append new item definition m_fixedDefs.append( NEW FixedMapStuffDef( ind, atoi(items->getString(5*i +1)), atoi(items->getString(5*i +2)), atoi(items->getString(5*i +3)), atoi(items->getString(5*i +4)) ) ); // check correctness of settings ASSERT( m_fixedDefs[m_fixedDefs.getSize()-1]->getDX() >= 0 && m_fixedDefs[m_fixedDefs.getSize()-1]->getDY() >= 0, "%s: tolerance for position of fixed map stuff must " "be given as non-negative numbers (found (%d,%d))\n", fn, m_fixedDefs[m_fixedDefs.getSize()-1]->getDX(), m_fixedDefs[m_fixedDefs.getSize()-1]->getDY() ); } DBG(2) INFO( "%s: loaded %d fixed map stuff sets\n", fn, m_fixedSets.getSize() ); return true; } /**********************************************************/ void MapStuff::reset() { m_randomSets.reset(); m_fixedSets.reset(); m_fixedDefs.reset(); for( int i = 0; i < MapStuffSet::NUM_MATERIALS; i++ ) { m_MaterialPresent[i] = false; } } /**********************************************************/