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; }
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; }
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; } }
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 {
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; }
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 ); } }
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; }
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; } }
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; } }
void Plant::draw( Vector3D *inPosition, double inScale, double inMaxZ, double inMinZ ) { if( mPoisoned && mPoisonStatus >= 1) { // draw nothing return; } double drawScale = inScale; if( mPoisoned ) { // shrink with poisoning drawScale *= ( 1 - mPoisonStatus ); } double radius = drawScale * ( mGrowth * 0.8 + 0.2 ); // leaves become black with poisoning // (shades of white to allow texture color to dominate) Color leafColor( 1 - mPoisonStatus, 1 - mPoisonStatus, 1 - mPoisonStatus, 1 ); if( ! Features::drawNicePlantLeaves ) { // set color to shades of green green for leaves if we're drawing // simple boxes, since there's no texture color leafColor.setValues( 0, 1 - mPoisonStatus, 0, 1 ); } Angle3D zeroAngle( 0, 0, 0 ); PlantGenetics *genetics = &( mSeeds.mGenetics ); int maxNumJoints = (int)( genetics->getParameter( jointCount ) ); double growthFactor = mGrowth * 0.8 + 0.2; int numFullJoints = (int)( growthFactor * maxNumJoints ); double partialJoint = growthFactor * maxNumJoints - numFullJoints; int numLeavesPerJoint = (int)( genetics->getParameter( leavesPerJoint ) ); Angle3D angleIncrement( 0, 0, 2 * M_PI / numLeavesPerJoint ); Angle3D startAngle( 0, 0, mStartZAngle ); double currentScale = 1; double scaleDecrement = currentScale / ( maxNumJoints + 1 ); Vector3D leafPosition( inPosition ); Vector3D positionIncrement( 0, 0, -0.5 ); Vector3D leafWalkerTerminus; SimpleVector<Vector3D *> thisLayerLeafTerminii; for( int j=0; j<numFullJoints; j++ ) { // lower leaves are darker double colorScaleFactor = (double)(j+1) / (double)maxNumJoints; // min scaling of 0.5 colorScaleFactor = colorScaleFactor * 0.5 + 0.5; Color thisLevelColor; thisLevelColor.setValues( &leafColor ); thisLevelColor.weightColor( colorScaleFactor ); Angle3D currentAngle( &startAngle ); double zValue = leafPosition.mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { // draw this joint for( int g=0; g<numLeavesPerJoint; g++ ) { if( Features::drawShadows ) { // draw shadow glColor4f( 0, 0, 0, 0.5 ); mLeaf.draw( &leafPosition, ¤tAngle, currentScale * radius * 1.05 ); } // draw leaf setGLColor( &thisLevelColor ); mLeaf.draw( &leafPosition, ¤tAngle, currentScale * radius, &leafWalkerTerminus ); thisLayerLeafTerminii.push_back( new Vector3D( &leafWalkerTerminus ) ); currentAngle.add( &angleIncrement ); } // finally cap this joint setGLColor( &thisLevelColor ); mJointCapTexture->enable(); glBegin( GL_QUADS ); { double capRadius = currentScale * radius * 0.1; double capZ = leafPosition.mZ; glTexCoord2f( 0, 0 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 0 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 1 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY + capRadius, capZ ); glTexCoord2f( 0, 1 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY + capRadius, capZ ); } glEnd(); mJointCapTexture->disable(); } Angle3D angleToNextJoint( &angleIncrement ); angleToNextJoint.scale( 0.5 ); currentAngle.add( &angleToNextJoint ); // start next joint at our current angle startAngle.setComponents( ¤tAngle ); currentScale -= scaleDecrement; leafPosition.add( &positionIncrement ); } if( partialJoint > 0 ) { Angle3D currentAngle( &startAngle ); // darker as growing completes // lower leaves are darker double colorScaleFactor = (double)(numFullJoints+1) / (double)maxNumJoints; // min scaling of 0.5 colorScaleFactor = colorScaleFactor * 0.5 + 0.5; // scale factor comes into effect as partial joint reaches 1 colorScaleFactor = (1 - partialJoint) + colorScaleFactor * partialJoint; Color thisLevelColor; thisLevelColor.setValues( &leafColor ); thisLevelColor.weightColor( colorScaleFactor ); double zValue = leafPosition.mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { // draw this joint for( int g=0; g<numLeavesPerJoint; g++ ) { if( Features::drawShadows ) { // draw shadow glColor4f( 0, 0, 0, 0.5 ); mLeaf.draw( &leafPosition, ¤tAngle, partialJoint * currentScale * radius * 1.05 ); } setGLColor( &thisLevelColor ); mLeaf.draw( &leafPosition, ¤tAngle, // scale down further by partial fraction partialJoint * currentScale * radius ); currentAngle.add( &angleIncrement ); } // finally cap this joint setGLColor( &thisLevelColor ); mJointCapTexture->enable(); glBegin( GL_QUADS ); { double capRadius = currentScale * radius * 0.1; double capZ = leafPosition.mZ; glTexCoord2f( 0, 0 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 0 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY - capRadius, capZ ); glTexCoord2f( 1, 1 ); glVertex3d( leafPosition.mX + capRadius, leafPosition.mY + capRadius, capZ ); glTexCoord2f( 0, 1 ); glVertex3d( leafPosition.mX - capRadius, leafPosition.mY + capRadius, capZ ); } glEnd(); mJointCapTexture->disable(); } } int numTerminii = thisLayerLeafTerminii.size(); int t; if( mGrowth >= 1 ) { // NOTE: // This method of collecting all leaf terminii for the plant ASSUMES // that each terminus is at a unique location // This seems like a safe assumption, given the way leaves are // arranged now, but it is not safe in the general case. // If two terminii are at the same location, the terminus collection // would finish before collecting all terminii if( !mLeafTerminiiSet ) { // not done collecting leaf terminii for full-growth plant int numExisting = mLeafTerminii.size(); char collision = false; for( int t=0; t<numTerminii && !collision; t++ ) { Vector3D *newTerminus = *( thisLayerLeafTerminii.getElement( t ) ); // make sure not the same as existing char same = false; for( int e=0; e<numExisting && !same; e++ ) { Vector3D *existing = *( mLeafTerminii.getElement( e ) ); if( existing->equals( newTerminus ) ) { same = true; collision = true; } } if( !same ) { // add to list of all terminii mLeafTerminii.push_back( new Vector3D( newTerminus ) ); } } if( collision ) { // we are back to drawing a layer that we've already drawn // before // so we're not gathering new leaf terminii anymore mLeafTerminiiSet = true; } } else { // don't try adding flowers if we already have more than // numTerminii // flowers int numTotalTerminii = mLeafTerminii.size(); int numFlowers = mFlowerTerminusIndicies.size(); int numFruit = mFruitTerminusIndices.size(); if( numFlowers < numTotalTerminii && mTimeSinceLastFlower >= genetics->getParameter( timeBetweenFlowers ) ) { // new flower // pick random, unflowered, unfruited terminus int numTries = 0; char found = false; int foundIndex = -1; while( ! found && numTries < 100 ) { foundIndex = globalRandomSource.getRandomBoundedInt( 0, numTotalTerminii - 1 ); found = true; int f; for( f=0; f<numFlowers && found; f++ ) { if( *( mFlowerTerminusIndicies.getElement( f ) ) == foundIndex ) { // collision with existing flower location found = false; } } for( f=0; f<numFruit && found; f++ ) { if( *( mFruitTerminusIndices.getElement( f ) ) == foundIndex ) { // collision with existing fruit location found = false; } } numTries++; } if( found ) { mFlowerTerminusIndicies.push_back( foundIndex ); mFlowerStages.push_back( 0 ); mFlowerAngles.push_back( new Angle3D( 0, 0, globalRandomSource.getRandomBoundedDouble( 0, 2 * M_PI ) ) ); } mTimeSinceLastFlower = 0; } // recount, since we may have added some numFlowers = mFlowerTerminusIndicies.size(); for( int f=0; f<numFlowers; f++ ) { int terminusIndex = *( mFlowerTerminusIndicies.getElement( f ) ); Vector3D *terminus = *( mLeafTerminii.getElement( terminusIndex ) ); double zValue = terminus->mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { Angle3D *flowerAngle = *( mFlowerAngles.getElement( f ) ); double flowerStage = *( mFlowerStages.getElement( f ) ); mFlower.draw( terminus, flowerAngle, drawScale, flowerStage ); } } } // draw fruit int numFruit = mFruit.size(); for( int f=0; f<numFruit; f++ ) { int terminusIndex = *( mFruitTerminusIndices.getElement( f ) ); Vector3D *terminus = *( mLeafTerminii.getElement( terminusIndex ) ); double zValue = terminus->mZ; if( zValue <= inMaxZ && zValue >= inMaxZ ) { Angle3D *fruitAngle = *( mFruitAngles.getElement( f ) ); Fruit *thisFruit = *( mFruit.getElement( f ) ); double fruitScale = drawScale * 0.2; thisFruit->draw( terminus, fruitAngle, fruitScale ); if( mHighlightRipeFruit && thisFruit->isRipe() ) { // make sure this is the fruit that we will harvest // next // (the z-range drawing can screw us // up here, since we might draw fruits out-of-order) // thus, the first-drawn ripe fruit is not necessarily // the fruit that will be next harvested Fruit *fruitNextHarvested = peekAtRipeFruit(); if( thisFruit == fruitNextHarvested ) { // this fruit will be harvested next glColor4f( 1, 1, 1, 0.25 ); // highlight brightens only glBlendFunc( GL_SRC_ALPHA, GL_ONE ); drawBlurCircle( terminus, fruitScale ); // back to normal blend function glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // only highlight one mHighlightRipeFruit = false; } } } } } // delete this layer's terminus points for( t=0; t<numTerminii; t++ ) { delete *( thisLayerLeafTerminii.getElement( t ) ); } }
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 ); }
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; }
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; }
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; } }
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; }