int main() { char c; int max_num = MAX; init_hanoi(max_num); printf("\n\n\n\n\n\n"); printf("\t\t\t\tHanoi Game\n\t\t\t\t"); printf("Enter '<' to quit!\n\t\t\t\tEnter '>' to show cheats!\n\n"); show_hanoi(); while(!is_complete(c_top)){ while(catch_status == FALSE) { c = getch(); if(c == 'd'){ switch(now_status) { case ON_A: now_status = ON_B; break; case ON_B: now_status = ON_C; break; case ON_C: now_status = ON_A; break; } show_hanoi(); } else if(c == 'a'){ switch(now_status) { case ON_A: now_status = ON_C; break; case ON_B: now_status = ON_A; break; case ON_C: now_status = ON_B; break; } show_hanoi(); } else if(c == 's') { catch_status = TRUE; show_hanoi(); break; } else if(c == '>') { dohanoi(max_num,65,66,67); printf("\n"); show_hanoi(); break; } else if(c == '<') { printf("Game Over! Bye!\n"); exit(0); } } while(catch_status == TRUE) { c = getch(); if(c == 'd'){ switch(now_status) { case ON_A: a_to_b(); now_status = ON_B; break; case ON_B: b_to_c(); now_status = ON_C; break; case ON_C: c_to_a(); now_status = ON_A; break; } show_hanoi(); } else if(c == 'a'){ switch(now_status) { case ON_A: a_to_c(); now_status = ON_C; break; case ON_B: b_to_a(); now_status = ON_A; break; case ON_C: c_to_b(); now_status = ON_B; break; } show_hanoi(); } else if(c == 's') { catch_status = FALSE; show_hanoi(); break; } else if(c == '>') { dohanoi(max_num,65,66,67); printf("\n"); show_hanoi(); break; } else if(c == '<') { printf("Game Over! Bye!\n"); exit(0); } } } printf("Good Game! Bye!\n"); return 0; }
void GardenerAI::passTime( double inTimeDeltaInSeconds ) { // before doing anything else, check if we are still following parent Gardener *parent = mGardener->getParentToFollow(); if( parent != NULL && ! parent->isDead() ) { // follow it if we get too far away Vector3D *destination; if( mWorld->getGardenerDistance( mGardener, parent ) > 10 ) { // move closer destination = mWorld->getGardenerPosition( parent ); } else { // stay where we are destination = mWorld->getGardenerPosition( mGardener ); } mGardener->setDesiredPosition( destination ); delete destination; return; } mSecondsSinceLastGift += inTimeDeltaInSeconds; mSecondsSinceLastRevenge += inTimeDeltaInSeconds; // first check if hungry int lowIndex = -1; for( int i=0; i<3; i++ ) { if( mGardener->getNutrientLevel(i) == 0 ) { lowIndex = i; } } if( lowIndex != -1 ) { // low in at least one nutrient // try to find a fruit high in that nutrient int index = mGardener->getIndexOfFruitHighInNutrient( lowIndex ); if( index != -1 ) { mGardener->setSelectedObjectIndex( index ); // eat selected fruit mGardener->eat(); } } // next deal with creating plot Vector3D *plotCenter = mWorld->getPlotCenter( mGardener ); if( plotCenter == NULL ) { // need to pick a new plot // walk toward water until we hit it, or until we get // too close to other gardeners Vector3D *waterPoint = mWorld->getClosestWater( mGardener ); double minPleasantDistance = 10; char tooCloseToOtherGardeners = false; Gardener *closestGardener = mWorld->getClosestGardener( mGardener ); if( closestGardener != NULL ) { Vector3D *ourPosition = mWorld->getGardenerPosition( mGardener ); Vector3D *closestGardenerPosition = mWorld->getGardenerPosition( closestGardener ); double distance = ourPosition->getDistance( closestGardenerPosition ); if( distance < minPleasantDistance ) { tooCloseToOtherGardeners = true; } delete ourPosition; delete closestGardenerPosition; } if( ! tooCloseToOtherGardeners && ! mWorld->isInWater( mGardener ) ) { mGardener->setDesiredPosition( waterPoint ); } else { // we just hit the water, or we came too close to other // gardeners // create our plot Vector3D *position = mWorld->getGardenerPosition( mGardener ); Vector3D a( position ); // vector pointing away from water center Vector3D rayFromWaterPoint( position ); rayFromWaterPoint.subtract( waterPoint ); rayFromWaterPoint.normalize(); // plot diagonal of 20 world units rayFromWaterPoint.scale( 20 ); // add this ray to our position position->add( &rayFromWaterPoint ); Vector3D b( position ); delete position; // thus, we pick a plot bordering the water that has a diagonal // length roughly equal to the water's radius // this can be a "skinny" rectangle, though, so widen it if // needed double diffX = fabs( a.mX - b.mX ); double diffY = fabs( a.mY - b.mY ); if( diffX < diffY ) { // taller than wide double increase = diffY - diffX; if( a.mX < b.mX ) { b.mX += increase; } else { a.mX += increase; } } if( diffY < diffX ) { // wider than tall double increase = diffX - diffY; if( a.mY < b.mY ) { b.mY += increase; } else { a.mY += increase; } } mWorld->setGardenerPlot( mGardener, &a, &b ); } delete waterPoint; return; } // we have a plot // check that there are enough plants in it int targetPlantCount = (int)( mGardener->mGenetics.getParameter( desiredPlantCount ) ); SimpleVector<Plant*> *plants = mWorld->getPlotPlants( mGardener ); int numPlants = plants->size(); SimpleVector<Seeds*> *seedsVector = mGardener->getAllSeeds(); int numSeeds = seedsVector->size(); delete seedsVector; if( numSeeds > 0 && numPlants < targetPlantCount ) { // plant more if( mNextPlantingLocation == NULL ) { // haven't picked a spot yet char foundPlantable = false; int numTries = 0; int maxNumTries = 10; while( !foundPlantable && numTries < maxNumTries ) { Vector3D *cornerA, *cornerB; mWorld->getGardenerPlot( mGardener, &cornerA, &cornerB ); double x = globalRandomSource.getRandomBoundedDouble( cornerA->mX, cornerB->mX ); double y = globalRandomSource.getRandomBoundedDouble( cornerA->mY, cornerB->mY ); mNextPlantingLocation = new Vector3D( x, y, 0 ); delete cornerA; delete cornerB; if( mWorld->canPlant( mNextPlantingLocation ) ) { foundPlantable = true; } else { // try again delete mNextPlantingLocation; mNextPlantingLocation = NULL; } numTries++; } } if( mNextPlantingLocation != NULL ) { Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( mNextPlantingLocation ) ) { // move to next plant location mGardener->setDesiredPosition( mNextPlantingLocation ); } else { // at next location: // make sure we can still plant // else pick another location at next time step if( mWorld->canPlant( mNextPlantingLocation ) ) { // plant here double soilCondition = mWorld->getSoilCondition( mNextPlantingLocation ); SimpleVector<Seeds*> *seedsVector = mGardener->getAllSeeds(); // find best for this soil Seeds *best = NULL; double minSoilDistance = 2; for( int i=0; i<seedsVector->size(); i++ ) { Seeds *seeds = *( seedsVector->getElement( i ) ); double distance = fabs( seeds->mIdealSoilType - soilCondition ); if( distance < minSoilDistance ) { minSoilDistance = distance; best = seeds; } } delete seedsVector; if( best != NULL ) { mWorld->addPlant( mGardener, new Plant( soilCondition, best ), mNextPlantingLocation ); mGardener->removeSeeds( best ); } } delete mNextPlantingLocation; mNextPlantingLocation = NULL; } delete gardenerPosition; } else { // tried to pick a plantable location, but failed // expand plot Vector3D *a, *b; mWorld->getGardenerPlot( mGardener, &a, &b ); // compute a vector stretching from b to a Vector3D b_to_a( a ); b_to_a.subtract( b ); // expand plot by 10% in each direction b_to_a.scale( 0.10 ); // push a away from b a->add( &b_to_a ); // also push b away from a // opposite direction b_to_a.scale( -1 ); b->add( &b_to_a ); mWorld->setGardenerPlot( mGardener, a, b ); delete a; delete b; } delete plants; delete plotCenter; return; } // else we have enough plants (or no seeds left) // if any are ripe, harvest them Plant *ripePlant = NULL; int i; for( i=0; i<numPlants && ripePlant == NULL; i++ ) { Plant *thisPlant = *( plants->getElement( i ) ); if( thisPlant->isRipe() ) { ripePlant = thisPlant; } } if( ripePlant != NULL ) { // move toward it Vector3D *plantPosition = mWorld->getPlantPosition( ripePlant ); Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( plantPosition ) ) { // move to plant mGardener->setDesiredPosition( plantPosition ); } else { // already at plant // harvest it mWorld->harvestPlant( mGardener, ripePlant ); } delete gardenerPosition; delete plantPosition; delete plants; delete plotCenter; return; } // else no ripe plants // water plants Plant *driestPlant = NULL; // ignore plants that have at least 1/4 water double driestWaterStatus = 0.25; for( int i=0; i<numPlants; i++ ) { Plant *thisPlant = *( plants->getElement( i ) ); double waterStatus = thisPlant->getWaterStatus(); if( waterStatus < driestWaterStatus ) { driestPlant = thisPlant; driestWaterStatus = waterStatus; } } if( mGardener->getCarryingWater() ) { // already carrying water // move to the driest plant if( driestPlant != NULL ) { // found driest // walk to it Vector3D *plantPosition = mWorld->getPlantPosition( driestPlant ); Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( plantPosition ) ) { // move to plant mGardener->setDesiredPosition( plantPosition ); } else { // already at plant // dump water mGardener->setCarryingWater( false ); mWorld->dumpWater( mGardener ); } delete gardenerPosition; delete plantPosition; } else { // else no dry plant found // wait and do nothing // head to plot center and wait mGardener->setDesiredPosition( plotCenter ); } } else if( driestPlant != NULL ) { // there is a dry plant, and we're not carrying water // fetch water if( ! mWorld->isInWater( mGardener ) ) { Vector3D *waterPoint = mWorld->getClosestWater( mGardener ); mGardener->setDesiredPosition( waterPoint ); delete waterPoint; } else { // grab water mGardener->setCarryingWater( true ); } } else { // no dry plant, and not carrying water char tryingToMate = false; // if not pregnant // and not target of another pregancy // hand have enough fruit to feel secure if( ! mGardener->isPregnant() && ! mWorld->isTargetOfPregnancy( mGardener ) && mGardener->getStoredFruitCount() >= mGardener->mGenetics.getParameter( storedFruitsBeforeMating ) ) { // we are not pregnant already // we have enough fruit stored // consider mating double ourThreshold = mGardener->mGenetics.getParameter( matingThreshold ); Gardener *mostLiked = mGardener->getMostLikedGardener(); if( mostLiked != NULL ) { double mostLikedMatingThreshold = mostLiked->mGenetics.getParameter( matingThreshold ); if( mGardener->getLikeMetric( mostLiked ) >= ourThreshold && mostLiked->getLikeMetric( mGardener ) >= mostLikedMatingThreshold && ! mostLiked->isPregnant() && ! mWorld->isTargetOfPregnancy( mostLiked ) ) { // we like them enough to mate // and // they like us enough to mate // and // they are not already pregnant // and // they are not already target of another pregnancy tryingToMate = true; Vector3D *ourPosition = mWorld->getGardenerPosition( mGardener ); Vector3D *otherPosition = mWorld->getGardenerPosition( mostLiked ); double distance = ourPosition->getDistance( otherPosition ); if( distance < getMaxDistanceForTransactions() ) { mWorld->mateGardeners( mGardener, mostLiked ); } else { // move toward friend mGardener->setDesiredPosition( otherPosition ); } delete ourPosition; delete otherPosition; } } } // check if we should give fruit to a neighbor char tryingToGiveFruit = false; // wait five seconds between gifts to give them // time to arrive before we reasses the situation if( !tryingToMate && mSecondsSinceLastGift > 5 ) { Gardener *mostLiked = mGardener->getMostLikedGardener(); if( mostLiked != NULL ) { // only give if we have 2+ more fruits than them // (to avoid back and forth giving when there is an // odd number of fruits between the two of us) if( mGardener->getStoredFruitCount() > mostLiked->getStoredFruitCount() + 1 ) { // we have fruit to spare compared to our best friend tryingToGiveFruit = true; Vector3D *ourPosition = mWorld->getGardenerPosition( mGardener ); Vector3D *otherPosition = mWorld->getGardenerPosition( mostLiked ); double distance = ourPosition->getDistance( otherPosition ); if( distance < getMaxDistanceForTransactions() ) { // close enough to give // find out which nutrient they are low in int lowIndex = -1; double lowValue = 2; for( int i=0; i<3; i++ ) { double value = mostLiked->getNutrientLevel(i); if( value < lowValue ) { lowIndex = i; lowValue = value; } } // try to find a fruit high in that nutrient int index = mGardener->getIndexOfFruitHighInNutrient( lowIndex ); // we will always get a valid index here, because // we have checked that we have stored fruit above mGardener->setSelectedObjectIndex( index ); mWorld->giveFruit( mGardener, mostLiked, // don't save seeds, but get any fruit, even // if fruit not selected mGardener->getSelectedFruit( false, true ) ); // reset timer mSecondsSinceLastGift = 0; // every time we give a gift, // our friendliness toward this gardener is depleted // a bit // Actually, don't do this for now, since for mating // purposes, we want to retain our friendliness // mGardener->getAngry( mostLiked ); } else { // move toward friend mGardener->setDesiredPosition( otherPosition ); } delete ourPosition; delete otherPosition; } } } char gettingRevenge = false; if( !tryingToMate && !tryingToGiveFruit ) { // consider getting revenge if( mSecondsSinceLastRevenge > 5 ) { Gardener *leastLiked = mGardener->getLeastLikedGardener(); if( leastLiked != NULL ) { Plant *plantToTake = getClosestPlantInGardenerPlot( leastLiked ); if( plantToTake != NULL ) { expandOurPlotToContainPlant( plantToTake ); gettingRevenge = true; // reset timer mSecondsSinceLastRevenge = 0; // every time we take revenge, our anger // toward this gardener lessens a bit mGardener->getFriendly( leastLiked ); } else { // none to take (our plots overlap perfectly) // try looking for a plant to poison Plant *plantToPoison = mWorld->getTendedPlant( leastLiked ); if( plantToPoison != NULL ) { // found candidate gettingRevenge = true; // walk to it Vector3D *plantPosition = mWorld->getPlantPosition( plantToPoison ); Vector3D *gardenerPosition = mWorld->getGardenerPosition( mGardener ); if( ! gardenerPosition->equals( plantPosition ) ) { // move to plant mGardener->setDesiredPosition( plantPosition ); } else { // already at plant mWorld->dumpPoison( mGardener ); // reset timer mSecondsSinceLastRevenge = 0; // every time we take revenge, our anger // toward this gardener lessens a bit mGardener->getFriendly( leastLiked ); } delete gardenerPosition; delete plantPosition; } } } } } if( !tryingToMate && !tryingToGiveFruit && !gettingRevenge ) { // head to plot center and wait mGardener->setDesiredPosition( plotCenter ); } } if( plotCenter != NULL ) { delete plotCenter; } delete plants; }