Пример #1
0
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();
    }
Пример #2
0
void testSimpleVectorDataAccess() {
    SimpleVector v = createSimpleVector(3);

    BOOST_CHECK( v.getElement(0) == 0 );
    BOOST_CHECK( v.getElement(1) == 1 );
    BOOST_CHECK( v.getElement(2) == 2 );
}
Пример #3
0
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;
    }
Пример #4
0
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;
    }
Пример #5
0
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 );
}
Пример #6
0
static toolRecord *getToolRecord( int inObjectID ) {
    
    if( getToolInRange( inObjectID ) ) {
        return tools.getElement( idToIndexMap[inObjectID] );
        }
    else {
        return tools.getElement( 0 );
        }
    }
Пример #7
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;    
    }
Пример #8
0
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 );
            }
        }
    }
Пример #9
0
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;
    }
Пример #10
0
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;
    }
Пример #11
0
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();
    }
Пример #12
0
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;
    }
Пример #13
0
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;
    }
Пример #14
0
// -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;
    }
Пример #15
0
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;
    }
Пример #16
0
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;
    }
Пример #17
0
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;
        }
    }
Пример #18
0
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;
        }
    }
Пример #19
0
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;
    }
Пример #20
0
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;
    
    }
Пример #21
0
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;
    
    }
Пример #22
0
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;
    }
Пример #23
0
// returns NULL if index out of range
Emotion *getEmotion( int inIndex ) {
    if( inIndex < 0 || inIndex >= emotions.size() ) {
        return NULL;
        }
    return emotions.getElement( inIndex );
    }
Пример #24
0
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--;
            }
        }
    }
Пример #25
0
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, &currentAngle,
                                currentScale * radius * 1.05 );
                    }
                
                // draw leaf
                setGLColor( &thisLevelColor );
                
                mLeaf.draw( &leafPosition, &currentAngle,
                            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( &currentAngle );

        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, &currentAngle,
                                partialJoint * currentScale * radius * 1.05 );
                    }
                
                setGLColor( &thisLevelColor );

                mLeaf.draw( &leafPosition, &currentAngle,
                            // 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 ) );
        }
    }
Пример #26
0
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;
            }
        }
    }