/// <summary> /// Get the next sample value from the gaussian distribution. /// </summary> public double NextSample() { for (; ;) { // Select box at random. byte u = _rng.NextByte(); int i = u & 0x7F; double sign = ((u & 0x80) == 0) ? -1.0 : 1.0; // Generate uniform random value with range [0,0xffffffff]. uint u2 = _rng.NextUInt(); // Special case for the base segment. if (0 == i) { if (u2 < _xComp[0]) { // Generated x is within R0. return(u2 * __UIntToU * _A_Div_Y0 * sign); } // Generated x is in the tail of the distribution. return(SampleTail() * sign); } // All other segments. if (u2 < _xComp[i]) { // Generated x is within the rectangle. return(u2 * __UIntToU * _x[i] * sign); } // Generated x is outside of the rectangle. // Generate a random y coordinate and test if our (x,y) is within the distribution curve. // This execution path is relatively slow/expensive (makes a call to Math.Exp()) but relatively rarely executed, // although more often than the 'tail' path (above). double x = u2 * __UIntToU * _x[i]; if (_y[i - 1] + ((_y[i] - _y[i - 1]) * _rng.NextDouble()) < GaussianPdfDenorm(x)) { return(x * sign); } } }
private void SpawnPlants() { var plantAmount = _plantInfos.CountPlants(); var plantsInCube = 0; foreach (var kvp in plantAmount) { var currentPlantType = kvp.Key; var currentAmount = kvp.Value; var rule = _zone.Configuration.PlantRules.GetPlantRule(currentPlantType); if (rule.HasBlockingState) { plantsInCube += currentAmount; } } var tilesInCube = _area.Ground; var fertilityFactor = _zone.Configuration.Fertility / 100.0; var availablePlaces = (int)(tilesInCube * fertilityFactor); availablePlaces -= plantsInCube; var cubeFertilityState = plantsInCube / (double)tilesInCube; //zone fertility check if (cubeFertilityState > fertilityFactor) { //ok, cube is fulfilling the fertility condition return; } for (var i = 0; i < tilesInCube; i++) { var x = FastRandom.NextInt(_area.Width - 1); var y = FastRandom.NextInt(_area.Height - 1); var globalX = x + _area.X1; var globalY = y + _area.Y1; var plantInfo = GetPlantInfo(x, y); var blockInfo = GetBlockInfo(x, y); var plantType = plantInfo.type; if (plantType != 0 || blockInfo.Flags != BlockingFlags.Undefined) { continue; } //per tile random chance if (FastRandom.NextByte() >= plantInfo.spawn) { continue; } var newPlantRule = GetNewPlantRule(globalX, globalY); if (newPlantRule == null) { plantInfo.Clear(); blockInfo.Height = 0; blockInfo.Plant = false; SetPlantInfo(x, y, plantInfo); SetBlockInfo(x, y, blockInfo); continue; } //is there a max amount defined for the current type? if (newPlantRule.MaxAmount > 0) { //have we planted enough? var amount = plantAmount.GetOrDefault(newPlantRule.Type); if (amount > newPlantRule.MaxAmount) { continue; } } if (!CheckKillDistance(newPlantRule, x, y, this)) { plantInfo.Clear(); blockInfo.Plant = false; blockInfo.Height = 0; SetPlantInfo(x, y, plantInfo); SetBlockInfo(x, y, blockInfo); continue; } plantInfo.type = newPlantRule.Type; plantInfo.state = 0; plantInfo.material = 0; //no material at state0 plantInfo.health = newPlantRule.Health[plantInfo.state]; //set health blockInfo.Height = newPlantRule.GetBlockingHeight(plantInfo.state); if (blockInfo.Height > 0) { blockInfo.Plant = true; } SetPlantInfo(x, y, plantInfo); SetBlockInfo(x, y, blockInfo); if (--availablePlaces <= 0) { return; } } }