public Bot(Maze maze, EngineSettings engineSettings, WallGrid walls, BrainFactory brainFactory, EyeFactory eyeFactory) { _maze = maze; _engineSettings = engineSettings; _walls = walls; _numEyes = engineSettings.BotEyes; _energyStep = 1.0; var neurons = _numEyes + (engineSettings.ThinkDistance ? 1 : 0) + (engineSettings.ThinkPath ? 5 : 0) + (engineSettings.ThinkVelocity ? 3 : 0); Brain = brainFactory.Create(neurons, 2); _eyes = new Eye[_numEyes]; Velocity = new Ray(new CoordD(0.5, 0.5), 0.0, engineSettings.BotSpeed); for (var i = 0; i < _numEyes; ++i) { var theta = i / (double)_numEyes * Consts.HalfTurn - Consts.QuarterTurn; _eyes[i] = eyeFactory.Create(Velocity.Origin, 2, 0, theta, 100); } Init(new CoordD(.5,.5)); }
/// <summary> /// Draws with a given pen and differed length. /// </summary> /// <param name="e">Event data.</param> /// <param name="ray"></param> /// <param name="p">The <c>Pen</c> to use.</param> /// <param name="val">Length.</param> public void Draw(PaintEventArgs e, Ray ray, Pen p, double val) { var cellScaling = new CoordD(_settings.WinWidth / (double)_engineSettings.MazeWidth, _settings.WinHeight / (double)_engineSettings.MazeHeight); var end = ray.Origin.ByAngle(ray.Angle, val); if (ray.Origin.X * cellScaling.X >= e.ClipRectangle.X && ray.Origin.X * cellScaling.X < e.ClipRectangle.Width && ray.Origin.Y * cellScaling.Y >= e.ClipRectangle.Y && ray.Origin.Y * cellScaling.Y < e.ClipRectangle.Height) e.Graphics.DrawLine(p, new PointF((float)ray.Origin.X * (float)cellScaling.X, (float)ray.Origin.Y * (float)cellScaling.Y), new PointF((float)end.X * (float)cellScaling.X, (float)end.Y * (float)cellScaling.Y)); }
/// <summary> /// Draws with the alpha channel of a given pen modified by <c>v</c>. /// </summary> /// <param name="e">Event data.</param> /// <param name="ray"></param> /// <param name="p">The <c>Pen</c> to use.</param> public void Draw(PaintEventArgs e, Ray ray, Pen p) { var cellScaling = new CoordD(_settings.WinWidth / (double)_engineSettings.MazeWidth, _settings.WinHeight / (double)_engineSettings.MazeHeight); var p1 = new Pen(Color.FromArgb((int)((1.0 - Math.Max(0.0, ray.Velocity)) * 240) + 15, p.Color.R, p.Color.G, p.Color.B)); var end = ray.CastPoint(); if (ray.Origin.X * cellScaling.X >= e.ClipRectangle.X && ray.Origin.X * cellScaling.X < e.ClipRectangle.Width && ray.Origin.Y * cellScaling.Y >= e.ClipRectangle.Y && ray.Origin.Y * cellScaling.Y < e.ClipRectangle.Height) e.Graphics.DrawLine(p1, new PointF((float)ray.Origin.X * (float)cellScaling.X, (float)ray.Origin.Y * (float)cellScaling.Y), new PointF((float)end.X * (float)cellScaling.X, (float)end.Y * (float)cellScaling.Y)); }
/// <summary> /// Raycasts a given <c>Ray</c> in this maze. /// </summary> /// <param name="ray">The <c>Ray</c> to cast.</param> /// <param name="radius">The radius of the thing casting the ray.</param> public void Raycast(ref Ray ray, double radius) { if (Math.Abs(ray.Magnitude) < Double.Epsilon) { ray.Velocity = 0; return; } var gridCoords = new CoordI(ray.Origin); double len = 0; double ax; double ay; var walled = false; var south = ray.GoingSouth(); var east = ray.GoingEast(); if ((south && !east) || (!south && east)) { ax = 1.0 / Math.Cos(Consts.QuarterTurn - ray.Angle % Consts.QuarterTurn); ay = 1.0 / Math.Cos(ray.Angle % Consts.QuarterTurn); } else { ax = 1.0 / Math.Cos(ray.Angle % Consts.QuarterTurn); ay = 1.0 / Math.Cos(Consts.QuarterTurn - ray.Angle % Consts.QuarterTurn); } var testCoord = ray.Origin - gridCoords; var testSpace = new CoordD(1,1) - testCoord; if (_walls.test_wall(gridCoords, 2) && testSpace.X < radius) ray.Origin.X -= radius - testSpace.X; else if (_walls.test_wall(gridCoords, 3) && testSpace.Y < radius) ray.Origin.Y -= radius - testSpace.Y; else if (_walls.test_wall(gridCoords, 0) && testCoord.X < radius) ray.Origin.X += radius - testCoord.X; else if (_walls.test_wall(gridCoords, 1) && testCoord.Y < radius) ray.Origin.Y += radius - testCoord.Y; while (len < ray.Magnitude && !walled) { var gridSpace = ray.Origin.ByAngle(ray.Angle, len) - gridCoords; var cellSpace = new CoordD(1,1) - gridSpace; gridSpace.Abs(); cellSpace.Abs(); var hx = (east ? cellSpace.X : gridSpace.X) * ax; var hy = (south ? cellSpace.Y : gridSpace.Y) * ay; if (hx < hy) len += (east ? Math.Max(0, cellSpace.X - radius) : Math.Max(0, gridSpace.X - radius)) * ax; else len += (south ? Math.Max(0, cellSpace.Y - radius) : Math.Max(0, gridSpace.Y - radius)) * ay; var dir = hx < hy ? 0 : 1; if ((hx < hy && east) || (hx >= hy && south)) dir += 2; walled = !_walls.InBounds(gridCoords, dir) || _walls.test_wall(gridCoords, dir); if (walled) continue; switch (dir) { case 0: gridCoords.X -= 1; break; case 1: gridCoords.Y -= 1; break; case 2: gridCoords.X += 1; break; case 3: gridCoords.Y += 1; break; } } ray.Velocity = Math.Min(len, ray.Magnitude) / ray.Magnitude; }
/// <summary> /// Draws with the a default colour. /// </summary> /// <param name="e">Event data.</param> /// <param name="ray"></param> public void Draw(PaintEventArgs e, Ray ray) { Draw(e, ray, new Pen(Color.FromArgb(255, 191, 255, 0))); }