GBRobot::GBRobot(GBRobotType * rtype, const GBPosition & where, const GBVelocity & vel, long parentID) : GBObject(where, 0.5, vel, rtype->Mass()), type(rtype), brain(rtype->MakeBrain()), id(rtype->Side()->GetNewRobotNumber()), parent(parentID), lastHit(nil), friendlyCollisions(0), enemyCollisions(0), foodCollisions(0), shotCollisions(0), wallCollisions(0), hardware(&rtype->Hardware()), dead(false), flag(0) { if ( ! rtype ) throw GBNilPointerError(); hardware.radio.Reset(Owner()); Recalculate(); }
void GBWorld::PickSeedPositions(GBPosition * positions, long numSeeds) { if ( ! positions) throw GBNilPointerError(); if ( numSeeds < 1 ) return; try { GBDistance wallDist = kSeedRadius + min(size.x, size.y) / 20; GBDistance separation = sqrt((size.x - wallDist * 2) * (size.y - wallDist * 2) / numSeeds); int iterations = 0; int iterLimit = 100 + 30 * numSeeds + numSeeds * numSeeds; bool inRange; // pick positions for ( int i = 0; i < numSeeds; i++ ) { do { inRange = false; positions[i] = RandomLocation(wallDist); //TODO in small worlds, this leaves too much space in center if ( positions[i].InRange(Size() / 2, separation - separation * iterations * 2 / iterLimit) ) inRange = true; else for ( int j = 0; j < i; j++ ) if ( positions[i].InRange(positions[j], separation - separation * iterations / iterLimit) ) { inRange = true; break; } if ( ++ iterations > iterLimit ) throw GBTooManyIterationsError(); } while ( inRange ) ; } if ( reportErrors && iterations > iterLimit / 2 ) NonfatalError("Warning: seed placement took " + ToString(iterations) + " iterations"); // shuffle positions //the above algorithm is not uniform, in that the first element may have different typical location than the last //to fix this, permute randomly (Knuth Vol 2 page 125) for ( long j = numSeeds - 1; j > 0; j-- ) { //iteration with j==0 is nop, so skip it long i = Randoms().LongInRange(0, j); GBPosition temp = positions[i]; positions[i] = positions[j]; positions[j] = temp; } } catch ( GBTooManyIterationsError & ) { if ( reportErrors ) NonfatalError("Warning: GBWorld::PickSeedPositions failsafe used."); for ( int i = 0; i < numSeeds; ++ i ) positions[i] = RandomLocation(); } }