00001
00002 #include "cerberus.h"
00003 #include "landscape.h"
00004 #include "entities.h"
00005
00006
00007 #include "mt19937.hpp"
00008
00012 cWorld::cWorld( IrrlichtDevice* device, int level, int size, int energy, double scalarStart, double hScalar ) :
00013 mDevice(device), mLevel( level ), mSize( size ), mEnergy( energy ), mScalarStart( scalarStart ), mHScalar( hScalar )
00014 {
00015 mSoul=NULL;
00016
00017
00018 mName.append( L"LANDSCAPE " );
00019 char buffer[5];
00020 snprintf( buffer, 5, "%04d", mLevel );
00021 mName.append( buffer );
00022
00023
00024 mDriver = mDevice->getVideoDriver();
00025 mSmgr = mDevice->getSceneManager();
00026 mLogger = mDevice->getLogger();
00027
00028
00029 mTreeMesh = mSmgr->getMesh( "media/tree.obj" );
00030 mBoulderMesh = mSmgr->getMesh( "media/boulder.obj" );
00031 mRobotMesh = mSmgr->getMesh( "media/robot.obj" );
00032
00033
00034 rng = new mt19937( ((unsigned long)(mLevel)+8749UL)*23095UL );
00035
00036
00037 mPoints = new double*[mSize+1];
00038 for( int i=0; i<mSize+1; i++ ) {
00039 mPoints[i] = new double[mSize+1];
00040 memset( mPoints[i], 0, sizeof(double)*(mSize+1) );
00041 }
00042
00043
00044 mElements = new cElement**[mSize];
00045 for( int i=0; i<mSize; i++ ) {
00046 mElements[i] = new cElement*[mSize];
00047 for( int j=0; j<mSize; j++ )
00048 mElements[i][j] = new cElement( this, mDevice );
00049 }
00050
00051 init();
00052 }
00053
00054
00055 cWorld::~cWorld()
00056 {
00057
00058 for( int i=0; i<mSize+1; i++ )
00059 delete mPoints[i];
00060 delete mPoints;
00061
00062 for( int i=0; i<mSize; i++ ) {
00063 for( int j=0; j<mSize; j++ )
00064 delete mElements[i][j];
00065 delete mElements[i];
00066 }
00067 delete mElements;
00068
00069
00070 if( mSoul )
00071 delete mSoul;
00072
00073
00074 delete rng;
00075
00076
00077 mCamera->remove();
00078 mNode->remove();
00079 }
00080
00081
00082 double cWorld::gaussian( double x0, double sigma )
00083 {
00084 double x;
00085
00086 for(;;) {
00087 x = x0 + 4.0*sigma*(-1.0 + getRandomNumber()*2.0);
00088 if( getRandomNumber()<exp(-0.5*pow((x-x0)/sigma, 2.0)) )
00089 break;
00090 }
00091
00092 return x;
00093 }
00094
00095
00096 double cWorld::gaussian_4( double sigma, double a1, double a2, double a3, double a4 )
00097 {
00098 return gaussian( (a1+a2+a3+a4 )/4.0, sigma );
00099 }
00100
00101 double cWorld::gaussian_3( double sigma, double a1, double a2, double a3 )
00102 {
00103 return gaussian( (a1+a2+a3 )/3.0, sigma );
00104 }
00105
00106 void cWorld::init()
00107 {
00108 double delta = mScalarStart;
00109 int N = mSize;
00110 double max, min;
00111
00112 mPoints[0][0] = gaussian( 0, delta );
00113 mPoints[N][0] = gaussian( 0, delta );
00114 mPoints[0][N] = gaussian( 0, delta );
00115 mPoints[N][N] = gaussian( 0, delta );
00116
00117 int d = N / 2;
00118 int D = N;
00119
00120 while (d >= 1)
00121 {
00122 #ifdef DEBUG
00123 std::cout << "doing: d=" << d << " D=" << D << " delta=" << delta << "\n";
00124 #endif
00125 delta = delta*sqrt(0.5*mHScalar);
00126
00127 #ifdef DEBUG
00128 std::cout << "middlepoints!\n";
00129 #endif
00130
00131 for( int x=d; x<=N-d; x=x+D )
00132 for( int y=d; y<=N-d; y=y+D )
00133 mPoints[x][y] = gaussian_4( delta, mPoints[x - d][y - d], mPoints[x + d][x - d],
00134 mPoints[x - d][y + d], mPoints[x + d][y + d]);
00135
00136
00137 delta = delta * sqrt(0.5 * mHScalar);
00138 #ifdef DEBUG
00139 std::cout << "borders!\n";
00140 #endif
00141
00142 for ( int x=d; x<=N-d; x=x+D ) {
00143 mPoints[x][0] = gaussian_3(delta, mPoints[x + d][0], mPoints[x - d][0], mPoints[x][d]);
00144 mPoints[x][N] = gaussian_3(delta, mPoints[x + d][N], mPoints[x - d][N], mPoints[x][N - d]);
00145 mPoints[0][x] = gaussian_3(delta, mPoints[0][x + d], mPoints[0][x - d], mPoints[d][x]);
00146 mPoints[N][x] = gaussian_3(delta, mPoints[N][x + d], mPoints[N][x - d], mPoints[N - d][x]);
00147 }
00148
00149 #ifdef DEBUG
00150 std::cout << "interiors!\n";
00151 #endif
00152 for ( int x=d; x<=N-d; x=x+D )
00153 for (int y=D; y<=N-d; y=y+D )
00154 mPoints[x][y] = gaussian_4(delta,mPoints[x+d][y],mPoints[x-d][y],mPoints[x][y+d],mPoints[x][y-d]);
00155
00156 #ifdef DEBUG
00157 std::cout << "interiors2!\n";
00158 #endif
00159 for ( int x = D; x <= N-d; x = x + D)
00160 for (int y = d; y <= N-d; y = y + D)
00161 mPoints[x][y] = gaussian_4(delta,mPoints[x+d][y],mPoints[x-d][y],mPoints[x][y+d],mPoints[x][y-d]);
00162 if (d == 1)
00163 break;
00164 d = d / 2;
00165 D = D / 2;
00166 }
00167
00168 min=1e300; max=-1e300;
00169 for( int x=0; x<mSize+1; x++ ) {
00170 for (int y = 0; y < mSize+1; y ++) {
00171 mPoints[x][y] = round(mPoints[x][y]);
00172 if( mPoints[x][y]<min )
00173 min=mPoints[x][y];
00174 if( mPoints[x][y]>max )
00175 max=mPoints[x][y];
00176 }
00177 }
00178
00179 for( int x=0; x<mSize+1; x++ ) {
00180 for (int y = 0; y < mSize+1; y ++) {
00181 mPoints[x][y] -= min;
00182 }
00183 }
00184
00185
00186 for( int x=1; x<mSize; x++ ) {
00187 for (int y=1; y<mSize; y ++) {
00188 double k = mPoints[x][y+1];
00189 if( (mPoints[x-1][y]==k) && (mPoints[x][y-1]==k) && (mPoints[x+1][y]==k) )
00190 mPoints[x][y] = k;
00191 }
00192 }
00193 }
00194
00195
00196 void cWorld::print()
00197 {
00198
00199 for( int x = 0; x < mSize+1; x++ ) {
00200 for( int y = 0; y < mSize+1; y++ )
00201 std::cout << x << " " << y << " " << mPoints[x][y] << " " << "\n";
00202 std::cout << "\n";
00203 }
00204 }
00205
00206 void cWorld::create( void )
00207 {
00208 double y1, y2, y3;
00209
00210
00211 mNode = mSmgr->addEmptySceneNode();
00212
00213 for( int i=0; i<mSize; i++ ) {
00214 for( int j=0; j<mSize; j++ ) {
00215 video::SColor color;
00216
00217
00218 scene::SMeshBuffer* elementBuffer = new scene::SMeshBuffer();
00219 elementBuffer->Indices.set_used( 12 );
00220 elementBuffer->Vertices.set_used( 12 );
00221 for( int k=0; k<12; ++k )
00222 elementBuffer->Indices[k] = k;
00223
00224
00225 double height = mPoints[i][j];
00226 if( (mPoints[i][j+1]!=height) || (mPoints[i+1][j+1]!=height) || (mPoints[i+1][j]!=height) ) {
00227
00228
00229 if( (i+j)%2 == 0 )
00230 color.set( 255, 100, 100, 100 );
00231 else
00232 color.set( 255, 0, 0, 0 );
00233
00234
00235
00236 mElements[i][j]->setFlat( false );
00237 } else {
00238
00239
00240 if( (i+j)%2 == 0 )
00241 color.set( 255, 0, 204, 0 );
00242 else
00243 color.set( 255, 0, 128, 182 );
00244
00245
00246 mElements[i][j]->setFlat( true );
00247 }
00248
00249 y1=mPoints[i][j+1]-mPoints[i][j];
00250 y2=mPoints[i+1][j+1]-mPoints[i][j];
00251 y3=mPoints[i+1][j]-mPoints[i][j];
00252 y1*=sqrt(2); y2*=sqrt(2); y3*=sqrt(2);
00253 if( fabs(y2)>=fabs(y3-y1) ) {
00254 elementBuffer->Vertices[0] = video::S3DVertex( 0, 0,0, y1-y2,1,-y1, color, 1,0 );
00255 elementBuffer->Vertices[1] = video::S3DVertex( 0,y1,1, y1-y2,1,-y1, color, 1,0 );
00256 elementBuffer->Vertices[2] = video::S3DVertex( 1,y2,1, y1-y2,1,-y1, color, 1,0 );
00257
00258
00259
00260
00261 elementBuffer->Vertices[3] = video::S3DVertex( 0, 0,0, -y3,1,y3-y2, color, 1,0 );
00262 elementBuffer->Vertices[4] = video::S3DVertex( 1,y2,1, -y3,1,y3-y2, color, 1,0 );
00263 elementBuffer->Vertices[5] = video::S3DVertex( 1,y3,0, -y3,1,y3-y2, color, 1,0 );
00264
00265
00266
00267
00268 elementBuffer->Vertices[6] = video::S3DVertex( 0, 0,0, -y1+y2,-1,y1, video::SColor(255,0,0,0), 1,0 );
00269 elementBuffer->Vertices[7] = video::S3DVertex( 1,y2,1, -y1+y2,-1,y1, video::SColor(255,0,0,0), 1,0 );
00270 elementBuffer->Vertices[8] = video::S3DVertex( 0,y1,1, -y1+y2,-1,y1, video::SColor(255,0,0,0), 1,0 );
00271
00272
00273
00274
00275 elementBuffer->Vertices[9] = video::S3DVertex( 0, 0,0, y3,-1,-y3+y2, video::SColor(255,0,0,0), 1,0 );
00276 elementBuffer->Vertices[10] = video::S3DVertex( 1,y3,0, y3,-1,-y3+y2, video::SColor(255,0,0,0), 1,0 );
00277 elementBuffer->Vertices[11] = video::S3DVertex( 1,y2,1, y3,-1,-y3+y2, video::SColor(255,0,0,0), 1,0 );
00278
00279
00280
00281 } else {
00282 elementBuffer->Vertices[0] = video::S3DVertex( 0, 0,0, -y3,1,-y1, color, 1,0 );
00283 elementBuffer->Vertices[1] = video::S3DVertex( 0,y1,1, -y3,1,-y1, color, 1,0 );
00284 elementBuffer->Vertices[2] = video::S3DVertex( 1,y3,0, -y3,1,-y1, color, 1,0 );
00285
00286
00287
00288
00289 elementBuffer->Vertices[3] = video::S3DVertex( 1,y3,0, y1-y2,1,y3-y2, color, 1,0 );
00290 elementBuffer->Vertices[4] = video::S3DVertex( 0,y1,1, y1-y2,1,y3-y2, color, 1,0 );
00291 elementBuffer->Vertices[5] = video::S3DVertex( 1,y2,1, y1-y2,1,y3-y2, color, 1,0 );
00292
00293
00294
00295
00296 elementBuffer->Vertices[6] = video::S3DVertex( 0, 0,0, y3,-1,y1, video::SColor(255,0,0,0), 1,0 );
00297 elementBuffer->Vertices[7] = video::S3DVertex( 1,y3,0, y3,-1,y1, video::SColor(255,0,0,0), 1,0 );
00298 elementBuffer->Vertices[8] = video::S3DVertex( 0,y1,1, y3,-1,y1, video::SColor(255,0,0,0), 1,0 );
00299
00300
00301
00302
00303 elementBuffer->Vertices[9] = video::S3DVertex( 1,y3,0, -y1+y2,-1,-y3+y2, video::SColor(255,0,0,0), 1,0 );
00304 elementBuffer->Vertices[10] = video::S3DVertex( 1,y2,1, -y1+y2,-1,-y3+y2, video::SColor(255,0,0,0), 1,0 );
00305 elementBuffer->Vertices[11] = video::S3DVertex( 0,y1,1, -y1+y2,-1,-y3+y2, video::SColor(255,0,0,0), 1,0 );
00306
00307
00308
00309 }
00310 elementBuffer->recalculateBoundingBox();
00311
00312 scene::SMesh* elementMesh = new scene::SMesh();
00313 elementMesh->addMeshBuffer( elementBuffer );
00314 elementBuffer->drop();
00315
00316 scene::IMeshSceneNode* elementNode = mSmgr->addMeshSceneNode( elementMesh, mNode );
00317 if( !elementNode ) {
00318 mLogger->log( "Couldn't create element node!", ELL_ERROR );
00319 exit( -1 );
00320 }
00321 elementMesh->drop();
00322
00323 elementNode->setPosition( core::vector3df(i, mPoints[i][j]*sqrt(2), j) );
00324
00325 elementNode->setMaterialFlag( video::EMF_LIGHTING, false );
00326 elementNode->setMaterialType( video::EMT_SOLID );
00327 elementNode->getMaterial(0).AmbientColor = color;
00328 elementNode->getMaterial(0).DiffuseColor = color;
00329 elementNode->getMaterial(0).EmissiveColor = color;
00330
00331 scene::ITriangleSelector* elementSelector = mSmgr->createTriangleSelector( elementMesh,
00332 elementNode );
00333 elementNode->setTriangleSelector( elementSelector );
00334 elementSelector->drop();
00335
00336 mElements[i][j]->setNode( elementNode );
00337 mElements[i][j]->setIndex( i, j );
00338 mElements[i][j]->setLevel( (int)(mPoints[i][j]) );
00339 }
00340 }
00341
00342 int curr_energy=0;
00343 while( curr_energy<=mEnergy ) {
00344 int i, j;
00345
00346 i=(int)(getRandomNumber()*mSize);
00347 j=(int)(getRandomNumber()*mSize);
00348
00349 if( !(mElements[i][j]->createEntity(eTree)) )
00350 continue;
00351
00352 curr_energy+=1;
00353 }
00354
00355
00356
00357
00358 mCamera = mSmgr->addCameraSceneNode( mNode );
00359 mSoul = new cSoul( mCamera );
00360
00361
00362 bool found=false;
00363 while( !found ) {
00364 int i, j;
00365
00366 i=(int)(getRandomNumber()*mSize);
00367 j=(int)(getRandomNumber()*mSize);
00368
00369 if( !mElements[i][j]->createEntity( eRobot ) )
00370 continue;
00371 else
00372 found=true;
00373
00374 mElements[i][j]->getNextEntity()->getNode()->setVisible( false );
00375 mSoul->setRobot( mElements[i][j]->getNextEntity() );
00376 mSoul->setIndex( i, j );
00377 mSoul->setGroundLevel( mElements[i][j]->getGroundLevel() );
00378 }
00379 }
00380
00387 cEntityBase* cWorld::findEntity()
00388 {
00389 core::line3d<f32> line;
00390 line.start = mCamera->getPosition();
00391 line.end = line.start + (mCamera->getTarget() - line.start).normalize() * 1000.0f;
00392
00393 cEntityBase* entity;
00394 cEntityBase* entitySave=NULL;
00395 core::vector3df intersection;
00396 core::triangle3df tri;
00397 f32 shortestDistance=1.0e30;
00398
00399 for( int i=0; i<mSize; i++ )
00400 for( int j=0; j<mSize; j++ ) {
00401 entity = mElements[i][j];
00402 while(entity) {
00403 scene::ITriangleSelector* selector=entity->getNode()->getTriangleSelector();
00404 if( mSmgr->getSceneCollisionManager()->getCollisionPoint(line, selector, intersection, tri) ) {
00405 if( mCamera->getPosition().getDistanceFrom(intersection)<shortestDistance ) {
00406 entitySave = entity;
00407 shortestDistance=mCamera->getPosition().getDistanceFrom(intersection);
00408 }
00409 }
00410 entity = entity->getNextEntity();
00411 }
00412 }
00413
00414 return entitySave;
00415 }
00416
00417
00418 bool cWorld::createEntity( eEntity entityType, cEntityBase* entityBelow )
00419 {
00420 assert(entityBelow);
00421
00422 bool status=entityBelow->createEntity( entityType );
00423
00424 if( status ) {
00425 switch( entityType ) {
00426 case eTree:
00427 mSoul->substractFromEnergy( 1 );
00428 break;
00429 case eBoulder:
00430 mSoul->substractFromEnergy( 2 );
00431 break;
00432 case eRobot:
00433 mSoul->substractFromEnergy( 3 );
00434 break;
00435 default:
00436 break;
00437 }
00438 }
00439
00440 return status;
00441 }
00442
00443
00456 int cWorld::absorbEntity( cEntityBase* entityBelow )
00457 {
00458 assert(entityBelow);
00459
00460
00461 if( (entityBelow->getType() != eElement) && (entityBelow->getType() != eBoulder) )
00462 return 0;
00463
00464
00465 int energy=0;
00466 if( entityBelow->getNextEntity() ) {
00467
00468 if( entityBelow->getNextEntity()->getNextEntity() )
00469 return 0;
00470
00471
00472 energy = entityBelow->getNextEntity()->getEnergy();
00473 delete entityBelow->getNextEntity();
00474 entityBelow->setNextEntity( NULL );
00475 } else {
00476
00477
00478 if( entityBelow->getType() == eBoulder ) {
00479 energy = entityBelow->getEnergy();
00480 entityBelow->getPreviousEntity()->setNextEntity( NULL );
00481 delete entityBelow;
00482 }
00483 }
00484
00485 mSoul->addToEnergy( energy );
00486
00487 return energy;
00488 }
00489
00490
00498 bool cWorld::transferSoul( cEntityBase* entityBelow )
00499 {
00500 assert(entityBelow);
00501
00502
00503 cEntityBase* robot = entityBelow->getNextEntity();
00504 if( !robot )
00505 return false;
00506 else {
00507 if( robot->getType() != eRobot )
00508 return false;
00509 }
00510
00511 doTransferSoul( robot );
00512 return true;
00513 }
00514
00515
00520 void cWorld::doTransferSoul( cEntityBase* robot )
00521 {
00522 int oldI=mSoul->getIndexI();
00523 int oldJ=mSoul->getIndexJ();
00524 f32 oldGroundLevel=mSoul->getGroundLevel();
00525
00526
00527 mSoul->getRobot()->getNode()->setVisible( true );
00528 robot->getNode()->setVisible( false );
00529 mSoul->setRobot( robot );
00530
00531
00532 mSoul->setIndex( robot->getIndexI(), robot->getIndexJ() );
00533 mSoul->setGroundLevel( robot->getGroundLevel() );
00534 mSoul->setTarget( core::vector3df(oldI+0.5, oldGroundLevel+1.1, oldJ+0.5) );
00535 mSoul->updateView();
00536
00537
00538
00539
00540 }
00541
00542
00543 void cWorld::hyperjump( void )
00544 {
00545 int i, j;
00546 bool transferred=false;
00547 int level=mSoul->getGroundLevel()/sqrt(2);
00548
00549 while( !transferred ) {
00550 i=(int)(getRandomNumber()*mSize);
00551 j=(int)(getRandomNumber()*mSize);
00552
00553 if( (mElements[i][j]->getLevel()<=level) && (mElements[i][j]->getNextEntity()==NULL) ) {
00554 mElements[i][j]->createEntity( eRobot );
00555 mSoul->substractFromEnergy( eRobotNrg );
00556
00557 doTransferSoul( mElements[i][j]->getNextEntity() );
00558
00559 printf( "hyperjump to: %i %i %i\n", i, j, mElements[i][j]->getLevel() );
00560 transferred=true;
00561 }
00562 }
00563 }
00564
00565
00566 void cWorld::showStartScreen()
00567 {
00568 mCamera->setPosition( core::vector3df(16,12,-15) );
00569 mCamera->setTarget( core::vector3df(16,0,16) );
00570 }
00571
00572
00573 bool cWorld::checkLandscapeCode( unsigned int level, unsigned int code )
00574 {
00575 mt19937* rng = new mt19937( ((unsigned long)(level)+8749UL)*23095UL );
00576 unsigned int mCode=(unsigned int)(rng->genrand_real1()*100000000.0);
00577
00578 fprintf( stdout, "level: %04d\ncorrect code: %08d\nyour code: %08d\n", level, mCode, code );
00579
00580
00581 delete rng;
00582
00583 return code==mCode;
00584 }