Beispiel #1
0
SimpleVector<char *> *tokenizeString( char *inString ) {

    char *tempString = stringDuplicate( inString );

    char *restOfString = tempString;
    
    SimpleVector<char *> *foundTokens = new SimpleVector<char *>();

    SimpleVector<char> *currentToken = new SimpleVector<char>();


    while( restOfString[0] != '\0' ) {
        // characters remain

        // skip whitespace
        char nextChar = restOfString[0];
        while( nextChar == ' ' || nextChar == '\n' ||
               nextChar == '\r' || nextChar == '\t' ) {

            restOfString = &( restOfString[1] );
            nextChar = restOfString[0];
            }

        if( restOfString[0] != '\0' ) {

            // a token

            while( nextChar != ' ' && nextChar != '\n' &&
                   nextChar != '\r' && nextChar != '\t' &&
                   nextChar != '\0'  ) {

                // still not whitespace
                currentToken->push_back( nextChar );
                
                restOfString = &( restOfString[1] );
                nextChar = restOfString[0];
                }

            // reached end of token
            foundTokens->push_back( currentToken->getElementString() );
            currentToken->deleteAll();
            }        
        }

    delete [] tempString;

    delete currentToken;

    return foundTokens;
    }
Beispiel #2
0
int prm_setShadowCallback(const char *id, ShadowCallback callback)
{
	Shadow shadow, *pshadow;

	// can't create a shadow if it doesn't exist
	if (prm_find(id)==NULL)
		return -1;

	pshadow = prm_findShadow(id);
	if (pshadow) // shadow is already in the table
		pshadow->callback = callback;
	else // create new entry
	{
		uint32_t len = strlen(id)+1;
		shadow.id = (const char *)malloc(len);
		strcpy((char *)shadow.id, id);
		shadow.len = 0;
		shadow.data = NULL;
		shadow.callback = callback;

		g_shadowTable.push_back(shadow);
	}

	return 0;
}
void SettingsManager::setSetting( const char *inSettingName,
                                  const char *inSettingValue ) {
    SimpleVector<char *> *settingsVector = new SimpleVector<char *>( 1 );

    settingsVector->push_back( (char *)inSettingValue );

    setSetting( inSettingName, settingsVector );

    delete settingsVector; 
    }
Beispiel #4
0
SoundUsage scanSoundUsage( char *inString ) {
    SimpleVector<int> idVector;
    SimpleVector<double> volVector;

    int numParts = 0;

    char **parts = split( inString, "#", &numParts );
    

    for( int i=0; i<numParts; i++ ) {
        int id = -1;
        double vol = 1.0;
        
        sscanf( parts[i], "%d:%lf", &id, &vol );
        
        if( id != -1 && vol >=0 && vol <= 1.0 ) {
            idVector.push_back( id );
            volVector.push_back( vol );
            }
        delete [] parts[i];
        }
    delete [] parts;

    
    if( idVector.size() > 0 ) {
        
        if( idVector.size() == 1 &&
            idVector.getElementDirect( 0 ) == -1 ) {
            return blankSoundUsage;
            }

        SoundUsage u = { idVector.size(), idVector.getElementArray(),
                         volVector.getElementArray() };
        return u;
        }
    else {
        return blankSoundUsage;
        }
    }
Beispiel #5
0
char *base64Encode( unsigned char *inData, int inDataLength,
                    char inBreakLines ) {

    SimpleVector<char> *encodingVector = new SimpleVector<char>();

    int numInLine = 0;
    
    // take groups of 3 data bytes and map them to 4 base64 digits
    for( int i=0; i<inDataLength; i=i+3 ) {

        if( i+2 < inDataLength ) {
            // not at end yet

            unsigned int block =
                inData[i]   << 16 |
                inData[i+1] << 8 |
                inData[i+2];

            // base64 digits, with digitA at left
            unsigned int digitA = 0x3F & ( block >> 18 );
            unsigned int digitB = 0x3F & ( block >> 12 );
            unsigned int digitC = 0x3F & ( block >> 6 );
            unsigned int digitD = 0x3F & ( block );

            encodingVector->push_back( binaryToAscii[ digitA ] );
            encodingVector->push_back( binaryToAscii[ digitB ] );
            encodingVector->push_back( binaryToAscii[ digitC ] );
            encodingVector->push_back( binaryToAscii[ digitD ] );
            numInLine += 4;

            if( inBreakLines && numInLine == 76 ) {
                // break the line
                encodingVector->push_back( '\r' );
                encodingVector->push_back( '\n' );
                numInLine = 0;
                }
            
            }
        else {
Beispiel #6
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;
    }
Beispiel #7
0
void recordPlayerLineage( char *inEmail, double inAge,
                          int inPlayerID, int inParentID,
                          int inDisplayID, int inKillerID,
                          const char *inName,
                          const char *inLastSay,
                          char inMale ) {

    if( useLineageServer ) {

        if( inName == NULL ) {
            inName = "NAMELESS";
            }
        if( inLastSay == NULL ) {
            inLastSay = "";
            }
        
        
        WebRequest *request;
        
        char *encodedEmail = URLUtils::urlEncode( inEmail );

        char *url = autoSprintf( 
            "%s?action=get_sequence_number"
            "&email=%s",
            lineageServerURL,
            encodedEmail );
        
        delete [] encodedEmail;
        
        request = new WebRequest( "GET", url, NULL );
        printf( "Starting new web request for %s\n", url );
        
        delete [] url;

        LineageRecord r = { stringDuplicate( inEmail ), inAge, 
                            inPlayerID, inParentID, inDisplayID,
                            inKillerID,
                            stringDuplicate( inName ),
                            stringDuplicate( inLastSay ),
                            inMale,
                            request, -1 };
        records.push_back( r );
        }
    }
Beispiel #8
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;
    }
MusicNoteWaveTable::MusicNoteWaveTable( unsigned long inSamplesPerSecond ){


    // read frequencies and lengths from files
    

    SimpleVector<double> *frequencyVector = new SimpleVector<double>();
    SimpleVector<double> *lengthVector = new SimpleVector<double>();
    
    FILE *musicNotePitchesFILE = NULL;
    FILE *musicNoteLengthsFILE = NULL;
    

    if( musicNotePitchesFILE != NULL ) {

        double readValue;
        int numRead = 1;

        while( numRead == 1 ) {
            numRead = fscanf( musicNotePitchesFILE, "%lf", &readValue );
            
            if( numRead == 1 ) {
                frequencyVector->push_back( readValue );
                }
            }

        fclose( musicNotePitchesFILE );
        }
    else {
        // default pitches

        // Note  N,, means N two octaves down
        // N'' means two octaves up

        /*
        // This one sounds pretty good
        // but not enough notes, too bland
        
        // A,,
        frequencyVector->push_back( 110 );

        // D,
        frequencyVector->push_back( 146.832 );

        // A,
        frequencyVector->push_back( 220 );

        // D
        frequencyVector->push_back( 293.665 );

        // G
        frequencyVector->push_back( 391.995 );

        // C'
        frequencyVector->push_back( 523.251 );

        // E'
        frequencyVector->push_back( 659.255 );

        // G'
        frequencyVector->push_back( 783.991 );
        */


        // Instead, use entire two-octaves from c-major scale
        // Problem:  there can be some discords.
        // However:  much more interesting sounding than the two-chord version
        // above

        
        // base note:  C,
        double baseNote = 130.8127827;

        int majorScaleSteps[7] = {2,2,1,2,2,2,1};

        int scaleIndex = 0;
        int notePower = 0;

        // two octaves
        while( notePower < 25 ) {
            frequencyVector->push_back(
                baseNote * pow( 2, notePower / 12.0 ) );

            notePower += majorScaleSteps[ scaleIndex ];

            scaleIndex ++;
            if( scaleIndex >= 7 ) {
                // wrap around
                scaleIndex = 0;
                }
            }
        
                
        /*
          // These are the notes from Transcend level 001
        frequencyVector->push_back( 220 );
        frequencyVector->push_back( 277.183 );
        frequencyVector->push_back( 329.628 );
        frequencyVector->push_back( 440 );
        frequencyVector->push_back( 554.365 );
        frequencyVector->push_back( 659.255 );
        */
        }

    

    if( musicNoteLengthsFILE != NULL ) {

        double readValue;
        int numRead = 1;

        while( numRead == 1 ) {
            numRead = fscanf( musicNoteLengthsFILE, "%lf", &readValue );
            
            if( numRead == 1 ) {
                lengthVector->push_back( readValue );
                }
            }

        fclose( musicNoteLengthsFILE );
        }
    else {
        // default lengths
        lengthVector->push_back( globalLongestNoteLength );
        lengthVector->push_back( globalShortestNoteLength );
        }


    mFrequencyCount = frequencyVector->size();
    mLengthCount = lengthVector->size();

    double *frequencies = frequencyVector->getElementArray();
    mLengthsInSeconds = lengthVector->getElementArray();

    delete frequencyVector;
    delete lengthVector;
    
    
    
    
    mSampleTable = new float**[ mFrequencyCount ];
    mSampleCounts = new unsigned long[ mLengthCount ];

    for( int F=0; F<mFrequencyCount; F++ ) {

        mSampleTable[F] = new float*[ mLengthCount ];

        
        for( int L=0; L<mLengthCount; L++ ) {
            
            // construct a sample table for this freqency/length pair
            unsigned long lengthInSamples =
                (unsigned long)( mLengthsInSeconds[L] * inSamplesPerSecond );

            mSampleTable[F][L] = new float[ lengthInSamples ];


            // setting this inside a double-loop will set the same
            // value repeatedly with the same value, but this makes the code
            // cleaner (other options:  a separate loop to set this value, or
            //  an if statement to ensure that it is set only once)
            mSampleCounts[L] = lengthInSamples;

            

            // populate the sample table with a linearly decaying sine wave
            double frequencyInCyclesPerSecond = frequencies[F];


            double frequencyInCyclesPerSample =
                frequencyInCyclesPerSecond / inSamplesPerSecond;

            // sine function cycles every 2*pi
            // adjust so that it cycles according to our desired frequency
            double adjustedFrequency =
                frequencyInCyclesPerSample * ( 2 * M_PI );

            // try to fade in for 100 samples to avoid a click
            // at the start of the note
            unsigned long numFadeInSamples = 100;
            if( numFadeInSamples > lengthInSamples ) {
                numFadeInSamples = lengthInSamples / 2;
                }

            // optimizations (found with profiler)
            // pull these out of inner loop
            float lengthInSamplesMinusOne = (float)lengthInSamples - 1.0f;
            float inv_lengthInSamplesMinusOne =
                1.0f / lengthInSamplesMinusOne;
            float *theseSamples = mSampleTable[F][L];
            
            for( unsigned long i=0; i<lengthInSamples; i++ ) {

                // decay loudness linearly
                float loudness =
                    ( lengthInSamplesMinusOne - i )
                    * inv_lengthInSamplesMinusOne;
                    
                // fade in for the first 100 samples to avoid
                // a click

                if( i < numFadeInSamples ) {

                    float fadeInFactor =
                        (float)( i ) / (float)( numFadeInSamples - 1 );

                    // optimization:
                    // only do this extra multiplication for notes that
                    // are fading in
                    loudness *= fadeInFactor;
                    }
                
                theseSamples[i] =
                    loudness * (float)sin( i * adjustedFrequency );
                }
            }
        }

    
    delete [] frequencies;
    }
Beispiel #10
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;
    }
ParameterizedStereoSound::ParameterizedStereoSound( FILE *inFILE,
                                                    char *outError ) {

    char readError = false;

    // read the sound length
    int numRead = fscanf( inFILE, "%lf", &mSoundLengthInSeconds );

    if( numRead != 1 ) {
        readError = true;
        
        printf( "Error:  failed to read sound length from sound space.\n" );
        }
    
    SimpleVector<ParameterSpaceControlPoint *> *controlPoints =
        new SimpleVector<ParameterSpaceControlPoint*>();
    SimpleVector<double> *controlPointParameterAnchors =
        new SimpleVector<double>();

    // keep reading parameter anchors and control points until we
    // can read no more
    
    while( !readError ) {
        
        // read the parameter space anchor
        double anchor = 0;
        numRead = fscanf( inFILE, "%lf", &anchor );

        if( numRead != 1 ) {
            readError = true;
            }
        else {

            // read the control point
            StereoSoundParameterSpaceControlPoint *point =
                new StereoSoundParameterSpaceControlPoint( inFILE,
                                                      &readError );

            if( !readError ) {
                controlPointParameterAnchors->push_back( anchor );
                controlPoints->push_back( point );
                }
            else {
                delete point;
                }
            }
        }

    mNumControlPoints = controlPoints->size();
    mControlPoints = controlPoints->getElementArray();
    mControlPointParameterAnchors =
        controlPointParameterAnchors->getElementArray();

    delete controlPoints;
    delete controlPointParameterAnchors;

    if( mNumControlPoints >= 2 ) {
        *outError = false;
        }
    else {
        // we didn't read enough control points
        *outError = true;
        }
    }
Beispiel #12
0
char LocalAddressReceiver::messageReceived( char *inFromAddress,
                                            char *inToAddress,
                                            char *inBody,
                                            int *outUtilityGenerated ) {
    mReceiveAddressLock->lock();
    // track the utility that our handlers generate for this message
    int utility = 0;
    
    {
        int numHandlers = mGlobalMessageHandlerVector->size();
        for( int i=0; i<numHandlers; i++ ) {
            MessageHandlerWrapper *wrapper =
                *( mGlobalMessageHandlerVector->getElement( i ) );
          utility +=
            wrapper->mHandlerFunction(
                        inFromAddress, inToAddress, inBody,
                        wrapper->mExtraHandlerArgument );
        }
    }
    int index = findAddressIndex( inToAddress ); 
    if( index != -1 ) {
        // received locally

                    
        if (!mHandlerLock->tryLockForRead(2000))
        {
        //FIXME : if no lock obtained after 2 seconds : what to do ?
          printf("strange, lock for read in messageREceived not obtained!!!\n");
        }
        int numHandlers = mMessageHandlerVector->size();
        
        if( numHandlers <= 0 ) {
            mHandlerLock->unlock();
            // no handlers, so queue messages
            
            SimpleVector<char *> *currentMessageQueue
                = *( mMessageQueueVector->getElement( index ) );
            SimpleVector<char *> *currentFromAddressQueue
                = *( mFromAddressQueueVector->getElement( index) );

            currentMessageQueue->push_back( stringDuplicate( inBody ) );
            currentFromAddressQueue->push_back(
                stringDuplicate( inFromAddress ) );

            mReceiveAddressLock->unlock();
            }
        else {
            // pass message to each handler
            
            // unlock so that handlers can modify receive addresses
            mReceiveAddressLock->unlock();

            
            for( int i=0; i<numHandlers; i++ ) {
                MessageHandlerWrapper *wrapper =
                    *( mMessageHandlerVector->getElement( i ) );

                utility +=
                    wrapper->mHandlerFunction(
                        inFromAddress, inToAddress, inBody,
                        wrapper->mExtraHandlerArgument );
                }
            mHandlerLock->unlock();
            }

        // message was received locally
        *outUtilityGenerated = utility;
        return true;
        }
    else {
        mReceiveAddressLock->unlock();
        *outUtilityGenerated = utility;
	// utility >= 1000 when chunk returned from cache
	if (utility >= 1000)
	  return true;
        return false;
        }
    }
Beispiel #13
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 ) );
        }
    }
Beispiel #14
0
float initCategoryBankStep() {
        
    if( currentFile == cache.numFiles ) {
        return 1.0;
        }
    
    int i = currentFile;

                
    char *txtFileName = getFileName( cache, i );
            
    if( strstr( txtFileName, ".txt" ) != NULL ) {
                            
        // a category txt file!
                    
        char *categoryText = getFileContents( cache, i );
        
        if( categoryText != NULL ) {
            int numLines;
                        
            char **lines = split( categoryText, "\n", &numLines );
                        
            delete [] categoryText;

            if( numLines >= 2 ) {
                CategoryRecord *r = new CategoryRecord;
                            
                int next = 0;
                
                r->parentID = 0;
                sscanf( lines[next], "parentID=%d", 
                        &( r->parentID ) );
                
                if( r->parentID > maxID ) {
                    maxID = r->parentID;
                    }
                
                next++;
                
                r->isPattern = false;
                r->isProbabilitySet = false;
                
                if( strstr( lines[next], "pattern" ) != NULL ) {
                    r->isPattern = true;
                    next++;
                    }
                else if( strstr( lines[next], "probSet" ) != NULL ) {
                    r->isProbabilitySet = true;
                    next++;
                    }
                

                int numObjects = 0;
                sscanf( lines[next], "numObjects=%d", 
                        &( numObjects ) );
                            
                next++;

                for( int i=0; i<numObjects; i++ ) {
                    int objID = 0;
                    float prob = 0.0f;
                    
                    if( r->isProbabilitySet ) {
                        sscanf( lines[next], "%d %f", &objID, &prob );
                        }
                    else {
                        sscanf( lines[next], "%d", &objID );
                        }
                    
                    next++;
                    
                    if( objID > 0 ) {
                        if( objID > maxObjectID ) {
                            maxObjectID = objID;
                            }
                        r->objectIDSet.push_back( objID );
                        r->objectWeights.push_back( prob );
                        }
                    }
                
                records.push_back( r );
                }
                            
            for( int i=0; i<numLines; i++ ) {
                delete [] lines[i];
                }
            delete [] lines;
            }
        }
                
    delete [] txtFileName;


    currentFile ++;
    return (float)( currentFile ) / (float)( cache.numFiles );
    }
Beispiel #15
0
void saveCategoryToDisk( int inParentID ) {
    CategoryRecord *r = getCategory( inParentID );
    

    if( r == NULL ) {
        return;
        }
    
    File categoriesDir( NULL, "categories" );
            
    if( !categoriesDir.exists() ) {
        categoriesDir.makeDirectory();
        }
    
    if( ! categoriesDir.exists() || ! categoriesDir.isDirectory() ) {

        printf( "Failed to make categories directory\n" );
        
        return;
        }


    
    File *cacheFile = categoriesDir.getChildFile( "cache.fcz" );

    cacheFile->remove();
    
    delete cacheFile;


        
    char *fileName = autoSprintf( "%d.txt", inParentID );


    File *categoryFile = categoriesDir.getChildFile( fileName );

    if( r->objectIDSet.size() == 0 ) {
        // empty category, simply remove it
        
        categoryFile->remove();
        }
    else {
        // resave
    
        SimpleVector<char*> lines;
        
        lines.push_back( autoSprintf( "parentID=%d", inParentID ) );

        if( r->isPattern ) {
            lines.push_back( stringDuplicate( "pattern" ) );
            }
        else if( r->isProbabilitySet ) {
            lines.push_back( stringDuplicate( "probSet" ) );
            }
        
        // start with 0 objects in a new category
        lines.push_back( autoSprintf( "numObjects=%d", 
                                      r->objectIDSet.size() ) );
        
        for( int i=0; i<r->objectIDSet.size(); i++ ) {
            if( r->isProbabilitySet ) {
                lines.push_back( 
                    autoSprintf( "%d %f", 
                                 r->objectIDSet.getElementDirect(i),
                                 r->objectWeights.getElementDirect(i) ) );
                }
            else {
                lines.push_back( 
                    autoSprintf( "%d", r->objectIDSet.getElementDirect(i) ) );
                }
            }
        
        
        char **linesArray = lines.getElementArray();
        
        
        char *contents = join( linesArray, lines.size(), "\n" );
        
        categoryFile->writeToFile( contents );
        
        delete [] contents;

        delete [] linesArray;
        lines.deallocateStringElements();
        }    
    
        
            
    delete [] fileName;
    delete categoryFile;
    
    return;
    }
Beispiel #16
0
SimpleVector<HostAddress *> *HostCatcher::getHostList(
    int inMaxHostCount,
    HostAddress *inSkipHost ) {

    HostAddress *hostToSkip;

    if( inSkipHost != NULL ) {
        hostToSkip = inSkipHost->copy();
        }
    else {
        // don't skip any host
        // create a dummy host that won't match any other valid hosts
        // make sure dummy is in numerical form to avoid DNS lookups
        hostToSkip = new HostAddress( stringDuplicate( "1.1.1.1" ), 1 );
        }
             
    
    SimpleVector<HostAddress *> *collectedHosts =
        new SimpleVector<HostAddress *>();

    char repeat = false;
    int numCollected = 0;

    // This function assumes that getHostOrdered() draws
    // hosts in order with no repetition except when we have
    // exhausted the host supply.

    // Note that this will not be true when other threads
    // have getHostOrdered() (or getHost) calls interleaved with ours, but this
    // should be a rare case.  It will simply result
    // in a smaller host list being returned.

    HostAddress *firstHost = getHostOrdered();

    if( firstHost == NULL ) {
        // the catcher is empty

        delete hostToSkip;

        // an empty host list
        return collectedHosts;       
        }
    

    if( ! hostToSkip->equals( firstHost ) ) {
        collectedHosts->push_back( firstHost );
        numCollected++;
        }

    
    while( numCollected < inMaxHostCount && !repeat ) {

        HostAddress *nextHost = getHostOrdered();

        if( nextHost->equals( firstHost ) ) {
            delete nextHost;
            repeat = true;
            }
        else {
            if( ! hostToSkip->equals( nextHost ) ) {
                collectedHosts->push_back( nextHost );
                numCollected++;
                }
            else {
                delete nextHost;
                }
            }
        
        }


    if( hostToSkip->equals( firstHost ) ) {
        // we didn't include firstHost in our collectedHosts, so
        // we must delete it.
        delete firstHost;
        }

    
    delete hostToSkip;

    return collectedHosts;
    }
Beispiel #17
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;
        }
    }
Beispiel #18
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;
    
    }