void LocalAddressReceiver::removeReceiveAddress( char *inAddress ) { mReceiveAddressLock->lock(); int index = findAddressIndex( inAddress ); if( index != -1 ) { delete [] *( mAddressVector->getElement( index ) ); mAddressVector->deleteElement( index ); SimpleVector<char *> *currentMessageQueue = *( mMessageQueueVector->getElement( index ) ); SimpleVector<char *> *currentFromAddressQueue = *( mFromAddressQueueVector->getElement( index ) ); int numInQueue = currentMessageQueue->size(); for( int j=0; j<numInQueue; j++ ) { delete [] *( currentMessageQueue->getElement( j ) ); delete [] *( currentFromAddressQueue->getElement( j ) ); } delete currentMessageQueue; delete currentFromAddressQueue; mMessageQueueVector->deleteElement( index ); mFromAddressQueueVector->deleteElement( index ); } mReceiveAddressLock->unlock(); }
void testSimpleVectorDataAccess() { SimpleVector v = createSimpleVector(3); BOOST_CHECK( v.getElement(0) == 0 ); BOOST_CHECK( v.getElement(1) == 1 ); BOOST_CHECK( v.getElement(2) == 2 ); }
const char *TranslationManager::translate( char *inTranslationKey ) { char *translatedString = NULL; SimpleVector<char *> *keys = mStaticMembers.mTranslationKeys; SimpleVector<char *> *naturalLanguageStrings = mStaticMembers.mNaturalLanguageStrings; if( keys != NULL ) { int numKeys = keys->size(); for( int i=0; i<numKeys && translatedString == NULL; i++ ) { if( strcmp( inTranslationKey, *( keys->getElement( i ) ) ) == 0 ) { // keys match translatedString = *( naturalLanguageStrings->getElement( i ) ); } } } if( translatedString == NULL ) { translatedString = inTranslationKey; } return translatedString; }
LocalAddressReceiver::~LocalAddressReceiver() { mReceiveAddressLock->lock(); int numAddresses = mAddressVector->size(); int i; for( i=0; i<numAddresses; i++ ) { delete [] *( mAddressVector->getElement( i ) ); SimpleVector<char *> *currentMessageQueue = *( mMessageQueueVector->getElement( i ) ); SimpleVector<char *> *currentFromAddressQueue = *( mFromAddressQueueVector->getElement( i ) ); int numInQueue = currentMessageQueue->size(); for( int j=0; j<numInQueue; j++ ) { delete [] *( currentMessageQueue->getElement( j ) ); delete [] *( currentFromAddressQueue->getElement( j ) ); } delete currentMessageQueue; delete currentFromAddressQueue; } delete mAddressVector; delete mMessageQueueVector; delete mFromAddressQueueVector; mReceiveAddressLock->unlock(); if (!mHandlerLock->tryLockForWrite(2000)) { //FIXME : if no lock obtaine after 2 seconds : what to do ? printf("strange, lock for write in ~LocalAddressReceiver not obtained!!!\n"); } int numHandlers = mMessageHandlerVector->size(); for( i=0; i<numHandlers; i++ ) { MessageHandlerWrapper *wrapper = *( mMessageHandlerVector->getElement( i ) ); delete wrapper; } delete mMessageHandlerVector; numHandlers = mGlobalMessageHandlerVector->size(); for( i=0; i<numHandlers; i++ ) { MessageHandlerWrapper *wrapper = *( mGlobalMessageHandlerVector->getElement( i ) ); delete wrapper; } delete mGlobalMessageHandlerVector; mHandlerLock->unlock(); delete mHandlerLock; delete mReceiveAddressLock; }
void testSimpleVectorMultiply() { SimpleVector v = createSimpleVector(3); // [0,1,2] * 3 = [0,3,6] v.multiply(3); BOOST_CHECK( v.getElement(0) == 0 ); BOOST_CHECK( v.getElement(1) == 3 ); BOOST_CHECK( v.getElement(2) == 6 ); }
static toolRecord *getToolRecord( int inObjectID ) { if( getToolInRange( inObjectID ) ) { return tools.getElement( idToIndexMap[inObjectID] ); } else { return tools.getElement( 0 ); } }
unsigned int LocalAddressReceiver::getReceivedMessages( char *inAddress, unsigned int inNumMessages, char ***outMessages, char ***outFromAddresses ) { mReceiveAddressLock->lock(); int index = findAddressIndex( inAddress ); int returnValue; char **messages; char **fromAddresses; if( index != -1 ) { SimpleVector<char *> *currentMessageQueue = *( mMessageQueueVector->getElement( index ) ); SimpleVector<char *> *currentFromAddressQueue = *( mFromAddressQueueVector->getElement( index) ); int numToGet = inNumMessages; int numAvailable = currentMessageQueue->size(); if( numToGet > numAvailable ) { numToGet = numAvailable; } messages = new char*[numToGet]; fromAddresses = new char*[numToGet]; for( int i=0; i<numToGet; i++ ) { messages[i] = *( currentMessageQueue->getElement(0) ); fromAddresses[i] = *( currentFromAddressQueue->getElement(0) ); currentMessageQueue->deleteElement( 0 ); currentFromAddressQueue->deleteElement( 0 ); } returnValue = numToGet; } else { returnValue = 0; messages = new char*[0]; fromAddresses = new char*[0]; } *outMessages = messages; *outFromAddresses = fromAddresses; mReceiveAddressLock->unlock(); return returnValue; }
void markEmotionsLive() { for( int i=0; i<emotions.size(); i++ ) { Emotion *e = emotions.getElement( i ); if( e->eyeEmot > 0 ) { addBaseObjectToLiveObjectSet( e->eyeEmot ); } if( e->mouthEmot > 0 ) { addBaseObjectToLiveObjectSet( e->mouthEmot ); } if( e->otherEmot > 0 ) { addBaseObjectToLiveObjectSet( e->otherEmot ); } if( e->faceEmot > 0 ) { addBaseObjectToLiveObjectSet( e->faceEmot ); } if( e->bodyEmot > 0 ) { addBaseObjectToLiveObjectSet( e->bodyEmot ); } if( e->headEmot > 0 ) { addBaseObjectToLiveObjectSet( e->headEmot ); } } }
char *readStreamUpToTagAndGetToken( InputStream *inInputStream, char *inTag, int inMaxCharsToRead, int inTokenNumber ) { // read the string char *readString = readStreamUpToTag( inInputStream, inTag, inMaxCharsToRead ); if( readString == NULL ) { return NULL; } SimpleVector<char *> *readTokens = tokenizeString( readString ); delete [] readString; // second token should be their key char *selectedToken = NULL; int numTokens = readTokens->size(); if( numTokens > inTokenNumber ) { selectedToken = stringDuplicate( *( readTokens->getElement( inTokenNumber ) ) ); } else { char *message = autoSprintf( "Looking for token %d, but only %d tokens available\n", inTokenNumber, numTokens ); AppLog::error( "readStreamUpToTagAndGetToken", message ); } for( int i=0; i<numTokens; i++ ) { delete [] *( readTokens->getElement( i ) ); } delete readTokens; // will be NULL if not enough tokens read return selectedToken; }
int getToolID( const char *inName ) { for( int i=0; i<tools.size(); i++ ) { toolRecord *r = tools.getElement( i ); if( strcmp( r->name, inName ) == 0 ) { return r->id; } } return -1; }
void freeLineageLog() { if( lineageServerURL != NULL ) { delete [] lineageServerURL; lineageServerURL = NULL; } if( serverID != NULL ) { delete [] serverID; serverID = NULL; } for( int i=0; i<records.size(); i++ ) { delete records.getElement(i)->request; delete [] records.getElement(i)->email; delete [] records.getElement(i)->name; delete [] records.getElement(i)->lastSay; } records.deleteAll(); }
int *getFullToolIDList( int *outNumIDs ) { *outNumIDs = tools.size(); int *returnList = new int[ *outNumIDs ]; for( int i=0; i<*outNumIDs; i++ ) { toolRecord *r = tools.getElement( i ); returnList[i] = r->id; } return returnList; }
char *SettingsManager::getStringSetting( const char *inSettingName ) { char *value = NULL; SimpleVector<char *> *settingsVector = getSetting( inSettingName ); int numStrings = settingsVector->size(); if( numStrings >= 1 ) { char *firstString = *( settingsVector->getElement( 0 ) ); value = stringDuplicate( firstString ); } for( int i=0; i<numStrings; i++ ) { char *nextString = *( settingsVector->getElement( i ) ); delete [] nextString; } delete settingsVector; return value; }
// -1 if no emotion triggered int getEmotionIndex( const char *inSpeech ) { char *upperSpeech = stringToUpperCase( inSpeech ); for( int i=0; i<emotions.size(); i++ ) { if( strstr( upperSpeech, emotions.getElement(i)->triggerWord ) == upperSpeech ) { // starts with trigger delete [] upperSpeech; return i; } } delete [] upperSpeech; return -1; }
char OutboundChannel::sendMessage( char * inMessage, int inPriority ) { mLock->lock(); char sent; if( !mConnectionBroken ) { // add it to the queue SimpleVector<char *> *queueToUse; if( inPriority <=0 ) { queueToUse = mMessageQueue; } else { queueToUse = mHighPriorityMessageQueue; } queueToUse->push_back( stringDuplicate( inMessage ) ); sent = true; if( queueToUse->size() > mMaxQueueSize ) { // the queue is over-full // drop the oldest message char *message = *( queueToUse->getElement( 0 ) ); queueToUse->deleteElement( 0 ); delete [] message; mDroppedMessageCount++; } } else { // channel no longer working sent = false; } mLock->unlock(); if( sent ) { mMessageReadySemaphore->signal(); } return sent; }
char *WebClient::receiveData( SocketStream *inSocketStream, int *outContentLength ) { SimpleVector<char> *receivedVector = new SimpleVector<char>(); char connectionBroken = false; long bufferLength = 5000; unsigned char *buffer = new unsigned char[ bufferLength ]; while( !connectionBroken ) { int numRead = inSocketStream->read( buffer, bufferLength ); if( numRead != bufferLength ) { connectionBroken = true; } if( numRead > 0 ) { for( int i=0; i<numRead; i++ ) { receivedVector->push_back( buffer[i] ); } } } delete [] buffer; // copy our vector into an array int receivedSize = receivedVector->size(); char *received = new char[ receivedSize + 1 ]; for( int i=0; i<receivedSize; i++ ) { received[i] = *( receivedVector->getElement( i ) ); } received[ receivedSize ] = '\0'; delete receivedVector; *outContentLength = receivedSize; return received; }
void freeTools() { for( int i=0; i<tools.size(); i++ ) { toolRecord r = *( tools.getElement( i ) ); delete [] r.name; delete [] r.description; delete [] r.descriptionPlural; freeSprite( r.sprite ); } tools.deleteAll(); if( idToIndexMap != NULL ) { delete [] idToIndexMap; idToIndexMap = NULL; } }
void initTools() { File elementsDir( NULL, "gameElements" ); if( !elementsDir.exists() || !elementsDir.isDirectory() ) { return; } File *toolsDir = elementsDir.getChildFile( "tools" ); if( toolsDir == NULL ) { return; } else if( !toolsDir->exists() || !toolsDir->isDirectory() ) { delete toolsDir; return; } int numTools; File **toolNameDirs = toolsDir->getChildFiles( &numTools ); delete toolsDir; if( toolNameDirs == NULL ) { return; } for( int i=0; i<numTools; i++ ) { File *f = toolNameDirs[i]; if( f->exists() && f->isDirectory() ) { char completeRecord = true; toolRecord r; r.name = f->getFileName(); r.description = NULL; r.descriptionPlural = NULL; r.sprite = NULL; File *infoFile = f->getChildFile( "info.txt" ); completeRecord = readInfoFile( infoFile, &( r.id ), &( r.description ) ); delete infoFile; if( completeRecord ) { File *pluralFile = f->getChildFile( "plural.txt" ); completeRecord = readPluralFile( pluralFile, &( r.descriptionPlural ) ); delete pluralFile; } if( completeRecord ) { // read reach, if present (if not, default to 1) r.reach = 1; File *reachFile = f->getChildFile( "reach.txt" ); if( reachFile->exists() ) { char *reach = reachFile->readFileContents(); sscanf( reach, "%d", &( r.reach ) ); delete [] reach; } delete reachFile; File *reachSigFile = f->getChildFile( "reachSignature.txt" ); char *reachSigContents = NULL; if( reachSigFile->exists() ) { reachSigContents = reachSigFile->readFileContents(); } delete reachSigFile; char reachSigOK = true; if( regenerateReachSignatures ) { // ignore reachSignature.txt and generate a new one char *newSig = computeReachSignature( &r ); File *childFile = f->getChildFile( "reachSignature.txt" ); if( childFile != NULL ) { childFile->writeToFile( newSig ); delete childFile; } delete [] newSig; } else if( reachSigContents == NULL ) { reachSigOK = false; } else { // else check it char *sig = trimWhitespace( reachSigContents ); char *trueSig = computeReachSignature( &r ); if( strcmp( trueSig, sig ) != 0 ) { reachSigOK = false; } delete [] sig; delete [] trueSig; } if( reachSigContents != NULL ) { delete [] reachSigContents; } if( !reachSigOK ) { char *dirName = f->getFullFileName(); char *message = autoSprintf( "%s\n%s", translate( "badReachSignature" ), dirName ); delete [] dirName; loadingFailed( message ); delete [] message; } // look for sprite TGA int numChildFiles; File **childFiles = f->getChildFiles( &numChildFiles ); char *tgaPath = NULL; char *shadeMapTgaPath = NULL; for( int j=0; j<numChildFiles; j++ ) { File *f = childFiles[j]; char *name = f->getFileName(); if( strstr( name, "_shadeMap.tga" ) != NULL ) { if( shadeMapTgaPath != NULL ) { delete [] shadeMapTgaPath; } shadeMapTgaPath = f->getFullFileName(); } else if( strstr( name, ".tga" ) != NULL ) { if( tgaPath != NULL ) { delete [] tgaPath; } tgaPath = f->getFullFileName(); } delete [] name; delete childFiles[j]; } delete [] childFiles; if( tgaPath != NULL ) { // assume only one orientation here // discard extras SpriteHandle readSprites[ MAX_ORIENTATIONS ]; int numOrientations = readShadeMappedSprites( tgaPath, shadeMapTgaPath, readSprites ); if( numOrientations == 0 ) { completeRecord = false; } else { r.sprite = readSprites[0]; for( int o=1; o<numOrientations; o++ ) { freeSprite( readSprites[o] ); } } } else { if( shadeMapTgaPath != NULL ) { delete [] shadeMapTgaPath; } completeRecord = false; } } if( completeRecord ) { if( r.id >= idSpaceSize ) { idSpaceSize = r.id + 1; } tools.push_back( r ); } else { delete [] r.name; if( r.description != NULL ) { delete [] r.description; } if( r.descriptionPlural != NULL ) { delete [] r.descriptionPlural; } if( r.sprite != NULL ) { freeSprite( r.sprite ); } } } delete f; } delete [] toolNameDirs; // build map idToIndexMap = new int[idSpaceSize]; for( int i=0; i<idSpaceSize; i++ ) { idToIndexMap[i] = -1; } for( int i=0; i<tools.size(); i++ ) { toolRecord r = *( tools.getElement( i ) ); idToIndexMap[r.id] = i; } }
Plant *GardenerAI::getClosestPlantInGardenerPlot( Gardener *inGardener ) { SimpleVector<Plant *> *ourPlants = mWorld->getPlotPlants( mGardener ); SimpleVector<Plant *> *otherPlants = mWorld->getPlotPlants( inGardener ); if( otherPlants == NULL ) { if( ourPlants != NULL ) { delete ourPlants; } return NULL; } // first, filter otherPlants to remove overlaps with ourPlants int i=0; while( i < otherPlants->size() ) { Plant *plant = *( otherPlants->getElement( i ) ); if( ourPlants != NULL && ourPlants->getElementIndex( plant ) != -1 ) { // overlap otherPlants->deleteElement( i ); } else { // no overlap i++; } } if( ourPlants != NULL ) { delete ourPlants; } Plant *returnPlant = NULL; int numPlants = otherPlants->size(); if( numPlants > 0 ) { // look for closest to us Vector3D *ourPostion = mWorld->getGardenerPosition( mGardener ); double closestDistance = DBL_MAX; for( i=0; i<numPlants; i++ ) { Plant *plant = *( otherPlants->getElement( i ) ); Vector3D *plantPosition = mWorld->getPlantPosition( plant ); double distance = plantPosition->getDistance( ourPostion ); delete plantPosition; if( distance < closestDistance ) { closestDistance = distance; returnPlant = plant; } } delete ourPostion; } delete otherPlants; return returnPlant; }
void initEmotion() { char *cont = SettingsManager::getSettingContents( "emotionWords", "" ); if( strcmp( cont, "" ) == 0 ) { delete [] cont; return; } int numParts; char **parts = split( cont, "\n", &numParts ); delete [] cont; for( int i=0; i<numParts; i++ ) { if( strcmp( parts[i], "" ) != 0 ) { Emotion e = { stringToUpperCase( parts[i] ), 0, 0, 0 }; emotions.push_back( e ); } delete [] parts[i]; } delete [] parts; // now read emotion objects cont = SettingsManager::getSettingContents( "emotionObjects", "" ); if( strcmp( cont, "" ) == 0 ) { delete [] cont; return; } parts = split( cont, "\n", &numParts ); delete [] cont; for( int i=0; i<numParts; i++ ) { if( strcmp( parts[i], "" ) != 0 ) { Emotion *e; if( i < emotions.size() ) { e = emotions.getElement( i ); } else { // the list extends beyond emotion words // put dummy trigger in place for these // * is a character that the end user cannot type Emotion eNew = { stringDuplicate( "DUMMY*TRIGGER" ), 0, 0, 0 }; emotions.push_back( eNew ); e = emotions.getElement( emotions.size() - 1 ); } e->eyeEmot = 0; e->mouthEmot = 0; e->otherEmot = 0; e->faceEmot = 0; e->bodyEmot = 0; e->headEmot = 0; sscanf( parts[i], "%d %d %d %d %d %d", &( e->eyeEmot ), &( e->mouthEmot ), &( e->otherEmot ), &( e->faceEmot ), &( e->bodyEmot ), &( e->headEmot ) ); } delete [] parts[i]; } delete [] parts; }
void GardenerAI::passTime( double inTimeDeltaInSeconds ) { // before doing anything else, check if we are still following parent Gardener *parent = mGardener->getParentToFollow(); if( parent != NULL && ! parent->isDead() ) { // follow it if we get too far away Vector3D *destination; if( mWorld->getGardenerDistance( mGardener, parent ) > 10 ) { // move closer destination = mWorld->getGardenerPosition( parent ); } else { // stay where we are destination = mWorld->getGardenerPosition( mGardener ); } mGardener->setDesiredPosition( destination ); delete destination; return; } mSecondsSinceLastGift += inTimeDeltaInSeconds; mSecondsSinceLastRevenge += inTimeDeltaInSeconds; // first check if hungry int lowIndex = -1; for( int i=0; i<3; i++ ) { if( mGardener->getNutrientLevel(i) == 0 ) { lowIndex = i; } } if( lowIndex != -1 ) { // low in at least one nutrient // try to find a fruit high in that nutrient int index = mGardener->getIndexOfFruitHighInNutrient( lowIndex ); if( index != -1 ) { mGardener->setSelectedObjectIndex( index ); // eat selected fruit mGardener->eat(); } } // next deal with creating plot Vector3D *plotCenter = mWorld->getPlotCenter( mGardener ); if( plotCenter == NULL ) { // need to pick a new plot // walk toward water until we hit it, or until we get // too close to other gardeners Vector3D *waterPoint = mWorld->getClosestWater( mGardener ); double minPleasantDistance = 10; char tooCloseToOtherGardeners = false; Gardener *closestGardener = mWorld->getClosestGardener( mGardener ); if( closestGardener != NULL ) { Vector3D *ourPosition = mWorld->getGardenerPosition( mGardener ); Vector3D *closestGardenerPosition = mWorld->getGardenerPosition( closestGardener ); double distance = ourPosition->getDistance( closestGardenerPosition ); if( distance < minPleasantDistance ) { tooCloseToOtherGardeners = true; } delete ourPosition; delete closestGardenerPosition; } if( ! tooCloseToOtherGardeners && ! mWorld->isInWater( mGardener ) ) { mGardener->setDesiredPosition( waterPoint ); } else { // we just hit the water, or we came too close to other // gardeners // create our plot Vector3D *position = mWorld->getGardenerPosition( mGardener ); Vector3D a( position ); // vector pointing away from water center Vector3D rayFromWaterPoint( position ); rayFromWaterPoint.subtract( waterPoint ); rayFromWaterPoint.normalize(); // plot diagonal of 20 world units rayFromWaterPoint.scale( 20 ); // add this ray to our position position->add( &rayFromWaterPoint ); Vector3D b( position ); delete position; // thus, we pick a plot bordering the water that has a diagonal // length roughly equal to the water's radius // this can be a "skinny" rectangle, though, so widen it if // needed double diffX = fabs( a.mX - b.mX ); double diffY = fabs( a.mY - b.mY ); if( diffX < diffY ) { // taller than wide double increase = diffY - diffX; if( a.mX < b.mX ) { b.mX += increase; } else { a.mX += increase; } } if( diffY < diffX ) { // wider than tall double increase = diffX - diffY; if( a.mY < b.mY ) { b.mY += increase; } else { a.mY += increase; } } mWorld->setGardenerPlot( mGardener, &a, &b ); } delete waterPoint; return; } // we have a plot // check that there are enough plants in it int targetPlantCount = (int)( mGardener->mGenetics.getParameter( desiredPlantCount ) ); SimpleVector<Plant*> *plants = mWorld->getPlotPlants( mGardener ); int numPlants = plants->size(); SimpleVector<Seeds*> *seedsVector = mGardener->getAllSeeds(); int numSeeds = seedsVector->size(); delete seedsVector; if( numSeeds > 0 && numPlants < targetPlantCount ) { // plant more if( mNextPlantingLocation == NULL ) { // haven't picked a spot yet char foundPlantable = false; int numTries = 0; int maxNumTries = 10; while( !foundPlantable && numTries < maxNumTries ) { Vector3D *cornerA, *cornerB; mWorld->getGardenerPlot( mGardener, &cornerA, &cornerB ); double x = globalRandomSource.getRandomBoundedDouble( cornerA->mX, cornerB->mX ); double y = globalRandomSource.getRandomBoundedDouble( cornerA->mY, cornerB->mY ); mNextPlantingLocation = new Vector3D( x, y, 0 ); delete cornerA; delete cornerB; if( mWorld->canPlant( mNextPlantingLocation ) ) { foundPlantable = true; } else { // try again delete mNextPlantingLocation; mNextPlantingLocation = NULL; } numTries++; } } if( mNextPlantingLocation != NULL ) { Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( mNextPlantingLocation ) ) { // move to next plant location mGardener->setDesiredPosition( mNextPlantingLocation ); } else { // at next location: // make sure we can still plant // else pick another location at next time step if( mWorld->canPlant( mNextPlantingLocation ) ) { // plant here double soilCondition = mWorld->getSoilCondition( mNextPlantingLocation ); SimpleVector<Seeds*> *seedsVector = mGardener->getAllSeeds(); // find best for this soil Seeds *best = NULL; double minSoilDistance = 2; for( int i=0; i<seedsVector->size(); i++ ) { Seeds *seeds = *( seedsVector->getElement( i ) ); double distance = fabs( seeds->mIdealSoilType - soilCondition ); if( distance < minSoilDistance ) { minSoilDistance = distance; best = seeds; } } delete seedsVector; if( best != NULL ) { mWorld->addPlant( mGardener, new Plant( soilCondition, best ), mNextPlantingLocation ); mGardener->removeSeeds( best ); } } delete mNextPlantingLocation; mNextPlantingLocation = NULL; } delete gardenerPosition; } else { // tried to pick a plantable location, but failed // expand plot Vector3D *a, *b; mWorld->getGardenerPlot( mGardener, &a, &b ); // compute a vector stretching from b to a Vector3D b_to_a( a ); b_to_a.subtract( b ); // expand plot by 10% in each direction b_to_a.scale( 0.10 ); // push a away from b a->add( &b_to_a ); // also push b away from a // opposite direction b_to_a.scale( -1 ); b->add( &b_to_a ); mWorld->setGardenerPlot( mGardener, a, b ); delete a; delete b; } delete plants; delete plotCenter; return; } // else we have enough plants (or no seeds left) // if any are ripe, harvest them Plant *ripePlant = NULL; int i; for( i=0; i<numPlants && ripePlant == NULL; i++ ) { Plant *thisPlant = *( plants->getElement( i ) ); if( thisPlant->isRipe() ) { ripePlant = thisPlant; } } if( ripePlant != NULL ) { // move toward it Vector3D *plantPosition = mWorld->getPlantPosition( ripePlant ); Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( plantPosition ) ) { // move to plant mGardener->setDesiredPosition( plantPosition ); } else { // already at plant // harvest it mWorld->harvestPlant( mGardener, ripePlant ); } delete gardenerPosition; delete plantPosition; delete plants; delete plotCenter; return; } // else no ripe plants // water plants Plant *driestPlant = NULL; // ignore plants that have at least 1/4 water double driestWaterStatus = 0.25; for( int i=0; i<numPlants; i++ ) { Plant *thisPlant = *( plants->getElement( i ) ); double waterStatus = thisPlant->getWaterStatus(); if( waterStatus < driestWaterStatus ) { driestPlant = thisPlant; driestWaterStatus = waterStatus; } } if( mGardener->getCarryingWater() ) { // already carrying water // move to the driest plant if( driestPlant != NULL ) { // found driest // walk to it Vector3D *plantPosition = mWorld->getPlantPosition( driestPlant ); Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( plantPosition ) ) { // move to plant mGardener->setDesiredPosition( plantPosition ); } else { // already at plant // dump water mGardener->setCarryingWater( false ); mWorld->dumpWater( mGardener ); } delete gardenerPosition; delete plantPosition; } else { // else no dry plant found // wait and do nothing // head to plot center and wait mGardener->setDesiredPosition( plotCenter ); } } else if( driestPlant != NULL ) { // there is a dry plant, and we're not carrying water // fetch water if( ! mWorld->isInWater( mGardener ) ) { Vector3D *waterPoint = mWorld->getClosestWater( mGardener ); mGardener->setDesiredPosition( waterPoint ); delete waterPoint; } else { // grab water mGardener->setCarryingWater( true ); } } else { // no dry plant, and not carrying water char tryingToMate = false; // if not pregnant // and not target of another pregancy // hand have enough fruit to feel secure if( ! mGardener->isPregnant() && ! mWorld->isTargetOfPregnancy( mGardener ) && mGardener->getStoredFruitCount() >= mGardener->mGenetics.getParameter( storedFruitsBeforeMating ) ) { // we are not pregnant already // we have enough fruit stored // consider mating double ourThreshold = mGardener->mGenetics.getParameter( matingThreshold ); Gardener *mostLiked = mGardener->getMostLikedGardener(); if( mostLiked != NULL ) { double mostLikedMatingThreshold = mostLiked->mGenetics.getParameter( matingThreshold ); if( mGardener->getLikeMetric( mostLiked ) >= ourThreshold && mostLiked->getLikeMetric( mGardener ) >= mostLikedMatingThreshold && ! mostLiked->isPregnant() && ! mWorld->isTargetOfPregnancy( mostLiked ) ) { // we like them enough to mate // and // they like us enough to mate // and // they are not already pregnant // and // they are not already target of another pregnancy tryingToMate = true; Vector3D *ourPosition = mWorld->getGardenerPosition( mGardener ); Vector3D *otherPosition = mWorld->getGardenerPosition( mostLiked ); double distance = ourPosition->getDistance( otherPosition ); if( distance < getMaxDistanceForTransactions() ) { mWorld->mateGardeners( mGardener, mostLiked ); } else { // move toward friend mGardener->setDesiredPosition( otherPosition ); } delete ourPosition; delete otherPosition; } } } // check if we should give fruit to a neighbor char tryingToGiveFruit = false; // wait five seconds between gifts to give them // time to arrive before we reasses the situation if( !tryingToMate && mSecondsSinceLastGift > 5 ) { Gardener *mostLiked = mGardener->getMostLikedGardener(); if( mostLiked != NULL ) { // only give if we have 2+ more fruits than them // (to avoid back and forth giving when there is an // odd number of fruits between the two of us) if( mGardener->getStoredFruitCount() > mostLiked->getStoredFruitCount() + 1 ) { // we have fruit to spare compared to our best friend tryingToGiveFruit = true; Vector3D *ourPosition = mWorld->getGardenerPosition( mGardener ); Vector3D *otherPosition = mWorld->getGardenerPosition( mostLiked ); double distance = ourPosition->getDistance( otherPosition ); if( distance < getMaxDistanceForTransactions() ) { // close enough to give // find out which nutrient they are low in int lowIndex = -1; double lowValue = 2; for( int i=0; i<3; i++ ) { double value = mostLiked->getNutrientLevel(i); if( value < lowValue ) { lowIndex = i; lowValue = value; } } // try to find a fruit high in that nutrient int index = mGardener->getIndexOfFruitHighInNutrient( lowIndex ); // we will always get a valid index here, because // we have checked that we have stored fruit above mGardener->setSelectedObjectIndex( index ); mWorld->giveFruit( mGardener, mostLiked, // don't save seeds, but get any fruit, even // if fruit not selected mGardener->getSelectedFruit( false, true ) ); // reset timer mSecondsSinceLastGift = 0; // every time we give a gift, // our friendliness toward this gardener is depleted // a bit // Actually, don't do this for now, since for mating // purposes, we want to retain our friendliness // mGardener->getAngry( mostLiked ); } else { // move toward friend mGardener->setDesiredPosition( otherPosition ); } delete ourPosition; delete otherPosition; } } } char gettingRevenge = false; if( !tryingToMate && !tryingToGiveFruit ) { // consider getting revenge if( mSecondsSinceLastRevenge > 5 ) { Gardener *leastLiked = mGardener->getLeastLikedGardener(); if( leastLiked != NULL ) { Plant *plantToTake = getClosestPlantInGardenerPlot( leastLiked ); if( plantToTake != NULL ) { expandOurPlotToContainPlant( plantToTake ); gettingRevenge = true; // reset timer mSecondsSinceLastRevenge = 0; // every time we take revenge, our anger // toward this gardener lessens a bit mGardener->getFriendly( leastLiked ); } else { // none to take (our plots overlap perfectly) // try looking for a plant to poison Plant *plantToPoison = mWorld->getTendedPlant( leastLiked ); if( plantToPoison != NULL ) { // found candidate gettingRevenge = true; // walk to it Vector3D *plantPosition = mWorld->getPlantPosition( plantToPoison ); Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( plantPosition ) ) { // move to plant mGardener->setDesiredPosition( plantPosition ); } else { // already at plant mWorld->dumpPoison( mGardener ); // reset timer mSecondsSinceLastRevenge = 0; // every time we take revenge, our anger // toward this gardener lessens a bit mGardener->getFriendly( leastLiked ); } delete gardenerPosition; delete plantPosition; } } } } } if( !tryingToMate && !tryingToGiveFruit && !gettingRevenge ) { // head to plot center and wait mGardener->setDesiredPosition( plotCenter ); } } if( plotCenter != NULL ) { delete plotCenter; } delete plants; }
char pathFind( int inMapH, int inMapW, char *inBlockedMap, GridPos inStart, GridPos inGoal, int *outFullPathLength, GridPos **outFullPath ) { // watch for degen case where start and goal are equal if( equal( inStart, inGoal ) ) { if( outFullPathLength != NULL ) { *outFullPathLength = 0; } if( outFullPath != NULL ) { *outFullPath = NULL; } return true; } // insertion-sorted queue of records waiting to be searched pathSearchQueue recordsToSearch; // keep records here, even after we're done with them, // to ensure they get deleted SimpleVector<pathSearchRecord*> searchQueueRecords; SimpleVector<pathSearchRecord> doneQueue; int numFloorSquares = inMapH * inMapW; // quick lookup of touched but not done squares // indexed by floor square index number char *openMap = new char[ numFloorSquares ]; memset( openMap, false, numFloorSquares ); char *doneMap = new char[ numFloorSquares ]; memset( doneMap, false, numFloorSquares ); pathSearchRecord startRecord = { inStart, inStart.y * inMapW + inStart.x, 0, getGridDistance( inStart, inGoal ), getGridDistance( inStart, inGoal ), -1, NULL }; // can't keep pointers in a SimpleVector // (change as vector expands itself) // push heap pointers into vector instead pathSearchRecord *heapRecord = new pathSearchRecord( startRecord ); searchQueueRecords.push_back( heapRecord ); recordsToSearch.head = heapRecord; openMap[ startRecord.squareIndex ] = true; char done = false; //while( searchQueueRecords.size() > 0 && !done ) { while( recordsToSearch.head != NULL && !done ) { // head of queue is best pathSearchRecord bestRecord = *( recordsToSearch.head ); recordsToSearch.head = recordsToSearch.head->nextSearchRecord; if( false ) printf( "Best record found: " "(%d,%d), cost %d, total %f, " "pred %d, this index %d\n", bestRecord.pos.x, bestRecord.pos.y, bestRecord.cost, bestRecord.total, bestRecord.predIndex, doneQueue.size() ); doneMap[ bestRecord.squareIndex ] = true; openMap[ bestRecord.squareIndex ] = false; doneQueue.push_back( bestRecord ); int predIndex = doneQueue.size() - 1; if( equal( bestRecord.pos, inGoal ) ) { // goal record has lowest total score in queue done = true; } else { // add neighbors GridPos neighbors[4]; GridPos bestPos = bestRecord.pos; neighbors[0].x = bestPos.x; neighbors[0].y = bestPos.y - 1; neighbors[1].x = bestPos.x; neighbors[1].y = bestPos.y + 1; neighbors[2].x = bestPos.x - 1; neighbors[2].y = bestPos.y; neighbors[3].x = bestPos.x + 1; neighbors[3].y = bestPos.y; // one step to neighbors from best record int cost = bestRecord.cost + 1; for( int n=0; n<4; n++ ) { int neighborSquareIndex = neighbors[n].y * inMapW + neighbors[n].x; if( ! inBlockedMap[ neighborSquareIndex ] ) { // floor char alreadyOpen = openMap[ neighborSquareIndex ]; char alreadyDone = doneMap[ neighborSquareIndex ]; if( !alreadyOpen && !alreadyDone ) { // for testing, color touched nodes // mGridColors[ neighborSquareIndex ].r = 1; // add this neighbor double dist = getGridDistance( neighbors[n], inGoal ); // track how we got here (pred) pathSearchRecord nRecord = { neighbors[n], neighborSquareIndex, cost, dist, dist + cost, predIndex, NULL }; pathSearchRecord *heapRecord = new pathSearchRecord( nRecord ); searchQueueRecords.push_back( heapRecord ); insertSearchRecord( &recordsToSearch, heapRecord ); openMap[ neighborSquareIndex ] = true; } else if( alreadyOpen ) { pathSearchRecord *heapRecord = pullSearchRecord( &recordsToSearch, neighborSquareIndex ); // did we reach this node through a shorter path // than before? if( cost < heapRecord->cost ) { // update it! heapRecord->cost = cost; heapRecord->total = heapRecord->estimate + cost; // found a new predecessor for this node heapRecord->predIndex = predIndex; } // reinsert insertSearchRecord( &recordsToSearch, heapRecord ); } } } } } char failed = false; if( ! done ) { failed = true; } delete [] openMap; delete [] doneMap; for( int i=0; i<searchQueueRecords.size(); i++ ) { delete *( searchQueueRecords.getElement( i ) ); } if( failed ) { return false; } // follow index to reconstruct path // last in done queue is best-reached goal node int currentIndex = doneQueue.size() - 1; pathSearchRecord *currentRecord = doneQueue.getElement( currentIndex ); pathSearchRecord *predRecord = doneQueue.getElement( currentRecord->predIndex ); done = false; SimpleVector<GridPos> finalPath; finalPath.push_back( currentRecord->pos ); while( ! equal( predRecord->pos, inStart ) ) { currentRecord = predRecord; finalPath.push_back( currentRecord->pos ); predRecord = doneQueue.getElement( currentRecord->predIndex ); } // finally, add start finalPath.push_back( predRecord->pos ); SimpleVector<GridPos> finalPathReversed; int numSteps = finalPath.size(); for( int i=numSteps-1; i>=0; i-- ) { finalPathReversed.push_back( *( finalPath.getElement( i ) ) ); } if( outFullPathLength != NULL ) { *outFullPathLength = finalPath.size(); } if( outFullPath != NULL ) { *outFullPath = finalPathReversed.getElementArray(); } return true; }
// returns NULL if index out of range Emotion *getEmotion( int inIndex ) { if( inIndex < 0 || inIndex >= emotions.size() ) { return NULL; } return emotions.getElement( inIndex ); }
void stepLineageLog() { if( ! useLineageServer ) { return; } for( int i=0; i<records.size(); i++ ) { LineageRecord *r = records.getElement( i ); int result = r->request->step(); char recordDone = false; if( result == -1 ) { AppLog::info( "Request to lineage server failed." ); recordDone = true; } else if( result == 1 ) { // done, have result char *webResult = r->request->getResult(); if( r->sequenceNumber == -1 ) { // still waiting for sequence number response int numRead = sscanf( webResult, "%d", &( r->sequenceNumber ) ); if( numRead != 1 ) { AppLog::info( "Failed to read sequence number " "from lineage server response." ); recordDone = true; } else { delete r->request; // start lineage-posting request char *seqString = autoSprintf( "%d", r->sequenceNumber ); char *lineageServerSharedSecret = SettingsManager::getStringSetting( "lineageServerSharedSecret", "secret_phrase" ); char *hash = hmac_sha1( lineageServerSharedSecret, seqString ); delete [] lineageServerSharedSecret; delete [] seqString; char *encodedEmail = URLUtils::urlEncode( r->email ); char *encodedName = URLUtils::urlEncode( r->name ); char *encodedLastSay = URLUtils::urlEncode( r->lastSay ); int maleInt = 0; if( r->male ) { maleInt = 1; } char *url = autoSprintf( "%s?action=log_life" "&server=%s" "&email=%s" "&age=%f" "&player_id=%d" "&parent_id=%d" "&display_id=%d" "&killer_id=%d" "&name=%s" "&last_words=%s" "&male=%d" "&sequence_number=%d" "&hash_value=%s", lineageServerURL, serverID, encodedEmail, r->age, r->playerID, r->parentID, r->displayID, r->killerID, encodedName, encodedLastSay, maleInt, r->sequenceNumber, hash ); delete [] encodedEmail; delete [] encodedName; delete [] encodedLastSay; delete [] hash; r->request = new WebRequest( "GET", url, NULL ); printf( "Starting new web request for %s\n", url ); delete [] url; } } else { if( strstr( webResult, "DENIED" ) != NULL ) { AppLog::info( "Server log_life request rejected by lineage server" ); } recordDone = true; } delete [] webResult; } if( recordDone ) { delete r->request; delete [] r->email; delete [] r->name; delete [] r->lastSay; records.deleteElement( i ); i--; } } }
void Plant::draw( Vector3D *inPosition, double inScale, double inMaxZ, double inMinZ ) { if( mPoisoned && mPoisonStatus >= 1) { // draw nothing return; } double drawScale = inScale; if( mPoisoned ) { // shrink with poisoning drawScale *= ( 1 - mPoisonStatus ); } double radius = drawScale * ( mGrowth * 0.8 + 0.2 ); // leaves become black with poisoning // (shades of white to allow texture color to dominate) Color leafColor( 1 - mPoisonStatus, 1 - mPoisonStatus, 1 - mPoisonStatus, 1 ); if( ! Features::drawNicePlantLeaves ) { // set color to shades of green green for leaves if we're drawing // simple boxes, since there's no texture color leafColor.setValues( 0, 1 - mPoisonStatus, 0, 1 ); } Angle3D zeroAngle( 0, 0, 0 ); PlantGenetics *genetics = &( mSeeds.mGenetics ); int maxNumJoints = (int)( genetics->getParameter( jointCount ) ); double growthFactor = mGrowth * 0.8 + 0.2; int numFullJoints = (int)( growthFactor * maxNumJoints ); double partialJoint = growthFactor * maxNumJoints - numFullJoints; int numLeavesPerJoint = (int)( genetics->getParameter( leavesPerJoint ) ); Angle3D angleIncrement( 0, 0, 2 * M_PI / numLeavesPerJoint ); Angle3D startAngle( 0, 0, mStartZAngle ); double currentScale = 1; double scaleDecrement = currentScale / ( maxNumJoints + 1 ); Vector3D leafPosition( inPosition ); Vector3D positionIncrement( 0, 0, -0.5 ); Vector3D leafWalkerTerminus; SimpleVector<Vector3D *> thisLayerLeafTerminii; for( int j=0; j<numFullJoints; j++ ) { // lower leaves are darker double colorScaleFactor = (double)(j+1) / (double)maxNumJoints; // min scaling of 0.5 colorScaleFactor = colorScaleFactor * 0.5 + 0.5; Color thisLevelColor; thisLevelColor.setValues( &leafColor ); thisLevelColor.weightColor( colorScaleFactor ); Angle3D currentAngle( &startAngle ); double zValue = leafPosition.mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { // draw this joint for( int g=0; g<numLeavesPerJoint; g++ ) { if( Features::drawShadows ) { // draw shadow glColor4f( 0, 0, 0, 0.5 ); mLeaf.draw( &leafPosition, ¤tAngle, currentScale * radius * 1.05 ); } // draw leaf setGLColor( &thisLevelColor ); mLeaf.draw( &leafPosition, ¤tAngle, currentScale * radius, &leafWalkerTerminus ); thisLayerLeafTerminii.push_back( new Vector3D( &leafWalkerTerminus ) ); currentAngle.add( &angleIncrement ); } // finally cap this joint setGLColor( &thisLevelColor ); mJointCapTexture->enable(); glBegin( GL_QUADS ); { double capRadius = currentScale * radius * 0.1; double capZ = leafPosition.mZ; glTexCoord2f( 0, 0 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 0 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 1 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY + capRadius, capZ ); glTexCoord2f( 0, 1 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY + capRadius, capZ ); } glEnd(); mJointCapTexture->disable(); } Angle3D angleToNextJoint( &angleIncrement ); angleToNextJoint.scale( 0.5 ); currentAngle.add( &angleToNextJoint ); // start next joint at our current angle startAngle.setComponents( ¤tAngle ); currentScale -= scaleDecrement; leafPosition.add( &positionIncrement ); } if( partialJoint > 0 ) { Angle3D currentAngle( &startAngle ); // darker as growing completes // lower leaves are darker double colorScaleFactor = (double)(numFullJoints+1) / (double)maxNumJoints; // min scaling of 0.5 colorScaleFactor = colorScaleFactor * 0.5 + 0.5; // scale factor comes into effect as partial joint reaches 1 colorScaleFactor = (1 - partialJoint) + colorScaleFactor * partialJoint; Color thisLevelColor; thisLevelColor.setValues( &leafColor ); thisLevelColor.weightColor( colorScaleFactor ); double zValue = leafPosition.mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { // draw this joint for( int g=0; g<numLeavesPerJoint; g++ ) { if( Features::drawShadows ) { // draw shadow glColor4f( 0, 0, 0, 0.5 ); mLeaf.draw( &leafPosition, ¤tAngle, partialJoint * currentScale * radius * 1.05 ); } setGLColor( &thisLevelColor ); mLeaf.draw( &leafPosition, ¤tAngle, // scale down further by partial fraction partialJoint * currentScale * radius ); currentAngle.add( &angleIncrement ); } // finally cap this joint setGLColor( &thisLevelColor ); mJointCapTexture->enable(); glBegin( GL_QUADS ); { double capRadius = currentScale * radius * 0.1; double capZ = leafPosition.mZ; glTexCoord2f( 0, 0 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 0 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 1 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY + capRadius, capZ ); glTexCoord2f( 0, 1 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY + capRadius, capZ ); } glEnd(); mJointCapTexture->disable(); } } int numTerminii = thisLayerLeafTerminii.size(); int t; if( mGrowth >= 1 ) { // NOTE: // This method of collecting all leaf terminii for the plant ASSUMES // that each terminus is at a unique location // This seems like a safe assumption, given the way leaves are // arranged now, but it is not safe in the general case. // If two terminii are at the same location, the terminus collection // would finish before collecting all terminii if( !mLeafTerminiiSet ) { // not done collecting leaf terminii for full-growth plant int numExisting = mLeafTerminii.size(); char collision = false; for( int t=0; t<numTerminii && !collision; t++ ) { Vector3D *newTerminus = *( thisLayerLeafTerminii.getElement( t ) ); // make sure not the same as existing char same = false; for( int e=0; e<numExisting && !same; e++ ) { Vector3D *existing = *( mLeafTerminii.getElement( e ) ); if( existing->equals( newTerminus ) ) { same = true; collision = true; } } if( !same ) { // add to list of all terminii mLeafTerminii.push_back( new Vector3D( newTerminus ) ); } } if( collision ) { // we are back to drawing a layer that we've already drawn // before // so we're not gathering new leaf terminii anymore mLeafTerminiiSet = true; } } else { // don't try adding flowers if we already have more than // numTerminii // flowers int numTotalTerminii = mLeafTerminii.size(); int numFlowers = mFlowerTerminusIndicies.size(); int numFruit = mFruitTerminusIndices.size(); if( numFlowers < numTotalTerminii && mTimeSinceLastFlower >= genetics->getParameter( timeBetweenFlowers ) ) { // new flower // pick random, unflowered, unfruited terminus int numTries = 0; char found = false; int foundIndex = -1; while( ! found && numTries < 100 ) { foundIndex = globalRandomSource.getRandomBoundedInt( 0, numTotalTerminii - 1 ); found = true; int f; for( f=0; f<numFlowers && found; f++ ) { if( *( mFlowerTerminusIndicies.getElement( f ) ) == foundIndex ) { // collision with existing flower location found = false; } } for( f=0; f<numFruit && found; f++ ) { if( *( mFruitTerminusIndices.getElement( f ) ) == foundIndex ) { // collision with existing fruit location found = false; } } numTries++; } if( found ) { mFlowerTerminusIndicies.push_back( foundIndex ); mFlowerStages.push_back( 0 ); mFlowerAngles.push_back( new Angle3D( 0, 0, globalRandomSource.getRandomBoundedDouble( 0, 2 * M_PI ) ) ); } mTimeSinceLastFlower = 0; } // recount, since we may have added some numFlowers = mFlowerTerminusIndicies.size(); for( int f=0; f<numFlowers; f++ ) { int terminusIndex = *( mFlowerTerminusIndicies.getElement( f ) ); Vector3D *terminus = *( mLeafTerminii.getElement( terminusIndex ) ); double zValue = terminus->mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { Angle3D *flowerAngle = *( mFlowerAngles.getElement( f ) ); double flowerStage = *( mFlowerStages.getElement( f ) ); mFlower.draw( terminus, flowerAngle, drawScale, flowerStage ); } } } // draw fruit int numFruit = mFruit.size(); for( int f=0; f<numFruit; f++ ) { int terminusIndex = *( mFruitTerminusIndices.getElement( f ) ); Vector3D *terminus = *( mLeafTerminii.getElement( terminusIndex ) ); double zValue = terminus->mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { Angle3D *fruitAngle = *( mFruitAngles.getElement( f ) ); Fruit *thisFruit = *( mFruit.getElement( f ) ); double fruitScale = drawScale * 0.2; thisFruit->draw( terminus, fruitAngle, fruitScale ); if( mHighlightRipeFruit && thisFruit->isRipe() ) { // make sure this is the fruit that we will harvest // next // (the z-range drawing can screw us // up here, since we might draw fruits out-of-order) // thus, the first-drawn ripe fruit is not necessarily // the fruit that will be next harvested Fruit *fruitNextHarvested = peekAtRipeFruit(); if( thisFruit == fruitNextHarvested ) { // this fruit will be harvested next glColor4f( 1, 1, 1, 0.25 ); // highlight brightens only glBlendFunc( GL_SRC_ALPHA, GL_ONE ); drawBlurCircle( terminus, fruitScale ); // back to normal blend function glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // only highlight one mHighlightRipeFruit = false; } } } } } // delete this layer's terminus points for( t=0; t<numTerminii; t++ ) { delete *( thisLayerLeafTerminii.getElement( t ) ); } }
void BuyAuctionPage::step() { if( mWebRequest != -1 ) { int stepResult = stepWebRequestSerial( mWebRequest ); if( stepResult != 0 ) { setWaiting( false ); } switch( stepResult ) { case 0: break; case -1: mStatusError = true; mStatusMessageKey = "err_webRequest"; clearWebRequestSerial( mWebRequest ); mWebRequest = -1; mHomeButton.setVisible( true ); break; case 1: { char *result = getWebResultSerial( mWebRequest ); clearWebRequestSerial( mWebRequest ); mWebRequest = -1; printf( "Web result = %s\n", result ); if( strstr( result, "DENIED" ) != NULL ) { mStatusError = true; mStatusMessageKey = "auctionBuyFailed"; mHomeButton.setVisible( true ); } else { // auction successful SimpleVector<char *> *tokens = tokenizeString( result ); if( tokens->size() != 2 || strcmp( *( tokens->getElement( 1 ) ), "OK" ) != 0 ) { mStatusError = true; mStatusMessageKey = "err_badServerResponse"; } else { int price; sscanf( *( tokens->getElement( 0 ) ), "%d", &price ); mBoughtSlot.setObject( mObjectID ); mBoughtSlot.setVisible( true ); mLootValue -= price; if( strcmp( mGalleryContents, "#" ) == 0 ) { // was empty, just the one new item now delete [] mGalleryContents; mGalleryContents = autoSprintf( "%d", mObjectID ); } else { // prepend char *old = mGalleryContents; mGalleryContents = autoSprintf( "%d#%s", mObjectID, mGalleryContents ); delete [] old; } const char *objectDescription = getGalleryObjectDescription( mObjectID ); char *quotedDescription = autoSprintf( "\"%s\"", objectDescription ); char *statusString = autoSprintf( translate( "auctionBuySucceed" ), quotedDescription, price ); delete [] quotedDescription; setStatusDirect( statusString, false ); delete [] statusString; } mHomeButton.setVisible( true ); for( int i=0; i<tokens->size(); i++ ) { delete [] *( tokens->getElement( i ) ); } delete tokens; } delete [] result; } break; } } }