public static void Repel(Robot rob1, Robot rob2) { double fixedSep; DoubleVector fixedSepVector; var e = SimOpt.SimOpts.CoefficientElasticity; var normal = rob2.Position - rob1.Position; var currDist = normal.Magnitude(); //If both bots are fixed or not moving and they overlap, move their positions directly. Fixed bots can overlap when shapes sweep them together //or when they teleport or materialize on top of each other. We move them directly apart as they are assumed to have no velocity //by scaling the normal vector by the amount they need to be separated. Each bot is moved half of the needed distance without taking into consideration //mass or size. if (rob1.IsFixed && rob2.IsFixed || rob1.Velocity.Magnitude() < 0.0001 && rob2.Velocity.Magnitude() < 0.0001) { fixedSep = (rob1.GetRadius(SimOpt.SimOpts.FixedBotRadii) + rob2.GetRadius(SimOpt.SimOpts.FixedBotRadii) - currDist) / 2; fixedSepVector = normal.Unit() * fixedSep; rob1.Position -= fixedSepVector; rob2.Position += fixedSepVector; } else { var totalMass = rob1.Mass + rob2.Mass; fixedSep = rob1.GetRadius(SimOpt.SimOpts.FixedBotRadii) + rob2.GetRadius(SimOpt.SimOpts.FixedBotRadii) - currDist; fixedSepVector = normal.Unit() * (fixedSep / (1 + Math.Pow(55, 0.3 - e))); rob1.Position -= fixedSepVector * (rob2.Mass / totalMass); rob2.Position += fixedSepVector * (rob1.Mass / totalMass); } if (!double.IsFinite(1.0 / normal.Magnitude())) { return; } var m1 = rob1.Mass; var m2 = rob2.Mass; //If a bot is fixed, all the collision energy should be translated to the non-fixed bot so for //the purposes of calculating the force applied to the non-fixed bot, treat the fixed one as if it is very massive if (rob1.IsFixed) { m1 = 32000; } if (rob2.IsFixed) { m2 = 32000; } var unit = normal.Unit(); var vel1 = rob1.Velocity; var vel2 = rob2.Velocity; //Project the bot's direction vector onto the unit vector and scale by velocity //These represent vectors we subtract from the bot's velocity to push the bot in a direction //appropriate to the collision. This would be all we needed if the bots all massed the same. //It's possible the bots are already moving away from each other having "collided" last cycle. If so, //we don't want to reverse them again and we don't want to add too much more further acceleration var projection = DoubleVector.Dot(vel1, unit) * 0.99; if (projection <= 0) { // bots are already moving away from one another projection = 0.000001; } var v1 = unit * projection; projection = DoubleVector.Dot(vel2, unit) * 0.99; // try damping things down a little if (projection >= 0) { // bots are already moving away from one another projection = -0.000001; } var v2 = unit * projection; //Now we need to factor in the mass of the bots. These vectors represent the resistance to movement due //to the bot's mass var v1F = (v2 * (e + 1) * m2 + v1 * (m1 - e * m2)) * (1 / (m1 + m2)); var v2F = (v1 * (e + 1) * m1 + v2 * (m2 - e * m1)) * (1 / (m1 + m2)); //No reason to try to try to accelerate fixed bots if (!rob1.IsFixed) { rob1.Velocity -= v1 + v1F; } if (!rob2.IsFixed) { rob2.Velocity -= v2 + v2F; } //Update the touch senses Senses.Touch(rob1, rob2.Position.X, rob2.Position.Y); Senses.Touch(rob2, rob1.Position.X, rob1.Position.Y); //Update last touch variables rob1.LastTouched = rob2; rob2.LastTouched = rob1; //Update the refvars to reflect touching bots. Senses.LookOccurr(rob1, rob2); Senses.LookOccurr(rob2, rob1); }
private static void aggiungirob(IRobotManager robotManager, IBucketManager bucketManager) { if (!SimOpt.SimOpts.Specie.Any(s => CheckVegStatus(robotManager, s))) { return; } int r; do { r = ThreadSafeRandom.Local.Next(0, SimOpt.SimOpts.Specie.Count); // start randomly in the list of species } while (!CheckVegStatus(robotManager, SimOpt.SimOpts.Specie[r])); var x = ThreadSafeRandom.Local.Next(Robot.RobSize / 2, SimOpt.SimOpts.FieldWidth - Robot.RobSize / 2); var y = ThreadSafeRandom.Local.Next(Robot.RobSize / 2, SimOpt.SimOpts.FieldHeight - Robot.RobSize / 2); if (SimOpt.SimOpts.Specie[r].Name == "" || SimOpt.SimOpts.Specie[r].Path == "Invalid Path") { return; } var a = DnaManipulations.RobScriptLoad(robotManager, bucketManager, System.IO.Path.Join(SimOpt.SimOpts.Specie[r].Path, SimOpt.SimOpts.Specie[r].Name)); if (a == null) { SimOpt.SimOpts.Specie[r].Native = false; return; } //Check to see if we were able to load the bot. If we can't, the path may be wrong, the sim may have //come from another machine with a different install path. Set the species path to an empty string to //prevent endless looping of error dialogs. if (!a.Exists) { SimOpt.SimOpts.Specie[r].Path = "Invalid Path"; return; } a.IsVegetable = SimOpt.SimOpts.Specie[r].Veg; if (a.IsVegetable) { a.Chloroplasts = SimOptions.StartChlr; } a.IsFixed = SimOpt.SimOpts.Specie[r].Fixed; a.CantSee = SimOpt.SimOpts.Specie[r].CantSee; a.DnaDisabled = SimOpt.SimOpts.Specie[r].DisableDna; a.MovementSysvarsDisabled = SimOpt.SimOpts.Specie[r].DisableMovementSysvars; a.CantReproduce = SimOpt.SimOpts.Specie[r].CantReproduce; a.IsVirusImmune = SimOpt.SimOpts.Specie[r].VirusImmune; a.IsCorpse = false; a.IsDead = false; a.Body = 1000; a.Mutations = 0; a.OldMutations = 0; a.LastMutation = 0; a.SonNumber = 0; a.Parent = null; Array.Clear(a.Memory, 0, a.Memory.Length); if (a.IsFixed) { a.Memory[216] = 1; } a.Position = new DoubleVector(x, y); a.Aim = ThreadSafeRandom.Local.NextDouble() * Math.PI * 2; a.Memory[MemoryAddresses.SetAim] = (int)a.Aim * 200; //Bot is already in a bucket due to the prepare routine bucketManager.UpdateBotBucket(a); a.Energy = SimOpt.SimOpts.Specie[r].Stnrg; a.MutationProbabilities = SimOpt.SimOpts.Specie[r].Mutables; a.VirusTimer = 0; a.VirusShot = null; a.NumberOfGenes = DnaManipulations.CountGenes(a.Dna); a.GenMut = (double)a.Dna.Count / RobotsManager.GeneticSensitivity; a.Memory[MemoryAddresses.DnaLenSys] = a.Dna.Count; a.Memory[MemoryAddresses.GenesSys] = a.NumberOfGenes; a.ChloroplastsDisabled = SimOpt.SimOpts.Specie[r].NoChlr; for (var i = 0; i < 7; i++) { a.Skin[i] = SimOpt.SimOpts.Specie[r].Skin[i]; } a.Color = SimOpt.SimOpts.Specie[r].Color; Senses.MakeOccurrList(a); }