/// <summary> /// Move forward based on a raycast to detect collisions. /// </summary> /// <param name="s">The speed to move at.</param> public void forward(double s) { m.raycast(ref velocity, radius); CoordD to = velocity.O + ((velocity.cast_point() - velocity.O) * s); move(to); }
public Ray(CoordD origin, double θ, double r) { O = origin; this.r = r; v = 1.0; this.θ = bound_angle(θ); }
public void move(CoordD pos) { velocity.O.x = pos.x; velocity.O.y = pos.y; grid_pos = new CoordI(velocity.O / m.cell_size); for (int i = 0; i < num_eyes; ++i) { eyes[i].move(velocity.O); } }
/// <summary> /// Draws with a given pen and differed length. /// </summary> /// <param name="e">Event data.</param> /// <param name="p">The <c>Pen</c> to use.</param> /// <param name="val">Length.</param> public void draw(PaintEventArgs e, Pen p, double val) { CoordD end = O.by_angle(θ, val); if (O.x >= e.ClipRectangle.X && O.x < e.ClipRectangle.Width && O.y >= e.ClipRectangle.Y && O.y < e.ClipRectangle.Height) { e.Graphics.DrawLine(p, new PointF((float)O.x, (float)O.y), new PointF((float)end.x, (float)end.y)); } }
public Maze(int width, int height, int window_w, int window_h) { walls = new Wall_grid(width, height); draw_rect = new Rectangle(0, 0, window_w, window_h); cell_size = new CoordD((double)window_w / (double)width, (double)window_h / (double)height); font_format = new StringFormat(); font_format.Alignment = StringAlignment.Center; font_format.LineAlignment = StringAlignment.Center; generate(); }
/// <summary> /// Draws with the alpha channel of a given pen modified by <c>v</c>. /// </summary> /// <param name="e">Event data.</param> /// <param name="p">The <c>Pen</c> to use.</param> public void draw(PaintEventArgs e, Pen p) { Pen p1 = new Pen(Color.FromArgb((int)((1.0 - Math.Max(0.0, v)) * 240) + 15, p.Color.R, p.Color.G, p.Color.B)); CoordD end = cast_point(); if (O.x >= e.ClipRectangle.X && O.x < e.ClipRectangle.Width && O.y >= e.ClipRectangle.Y && O.y < e.ClipRectangle.Height) { e.Graphics.DrawLine(p1, new PointF((float)O.x, (float)O.y), new PointF((float)end.x, (float)end.y)); } }
/// <summary> /// Initialise in a given position. /// </summary> /// <param name="pos">The position to move to.</param> public void init(CoordD pos) { max_energy = Program.settings.maze_time; num_eyes = Program.settings.bot_eyes; radius = Program.settings.bot_radius; alive = true; goal = false; energy = max_energy; grid_pos = new CoordI(pos / m.cell_size); move(pos); turn_to(0.0); }
public Eye(CoordD origin, double radius, double theta, double offset, double magnitude) { this.radius = radius; ray = new Ray(origin.by_angle(theta + offset, radius), theta, magnitude); this.offset = offset; while (this.offset < 0) { this.offset += Consts.τ; } while (this.offset >= Consts.τ) { this.offset -= Consts.τ; } }
public void move(CoordD pos) { ray.O = pos.by_angle(ray.θ, radius); }
/// <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 (ray.r == 0) { ray.v = 0; return; } CoordI grid_coords = new CoordI(ray.O / cell_size); int dir = -1; double len = 0; double Ax; double Ay; bool walled = false; bool south = ray.going_south(); bool east = ray.going_east(); if ((south && !east) || (!south && east)) { Ax = 1.0 / Math.Cos(Consts.η - ray.θ % Consts.η); Ay = 1.0 / Math.Cos(ray.θ % Consts.η); } else { Ax = 1.0 / Math.Cos(ray.θ % Consts.η); Ay = 1.0 / Math.Cos(Consts.η - ray.θ % Consts.η); } CoordD test_coord = ray.O - grid_coords * cell_size; CoordD test_space = cell_size - test_coord; if (walls.test_wall(grid_coords, 2) && test_space.x < radius) { ray.O.x -= radius - test_space.x; } else if (walls.test_wall(grid_coords, 3) && test_space.y < radius) { ray.O.y -= radius - test_space.y; } else if (walls.test_wall(grid_coords, 0) && test_coord.x < radius) { ray.O.x += radius - test_coord.x; } else if (walls.test_wall(grid_coords, 1) && test_coord.y < radius) { ray.O.y += radius - test_coord.y; } while (len < ray.r && !walled) { CoordD grid_space = ray.O.by_angle(ray.θ, len) - grid_coords * cell_size; CoordD cell_space = cell_size - grid_space; grid_space.abs(); cell_space.abs(); double hx = (east ? cell_space.x : grid_space.x) * Ax; double hy = (south ? cell_space.y : grid_space.y) * Ay; if (hx < hy) { len += (east ? Math.Max(0, cell_space.x - radius) : Math.Max(0, grid_space.x - radius)) * Ax; } else { len += (south ? Math.Max(0, cell_space.y - radius) : Math.Max(0, grid_space.y - radius)) * Ay; } dir = hx < hy ? 0 : 1; if ((hx < hy && east) || (hx >= hy && south)) { dir += 2; } walled = !walls.in_bounds(grid_coords, dir) || walls.test_wall(grid_coords, dir); if (!walled) { if (dir == 0) { grid_coords.x -= 1; } else if (dir == 1) { grid_coords.y -= 1; } else if (dir == 2) { grid_coords.x += 1; } else if (dir == 3) { grid_coords.y += 1; } } } ray.v = Math.Min(len, ray.r) / ray.r; }
public void scale(int width, int height) { draw_rect = new Rectangle(0, 0, width, height); cell_size = new CoordD((double)width / (double)walls.size.x, (double)height / (double)walls.size.y); }
public void copy(CoordD other) { this.x = (int)other.x; this.y = (int)other.y; }
public CoordI(CoordD other) { this.x = (int)other.x; this.y = (int)other.y; }
public void copy(CoordD other) { this.x = other.x; this.y = other.y; }
public CoordD(CoordD other) { this.x = other.x; this.y = other.y; }
/// <summary> /// Use the <c>Brain</c> with variable inputs based on <c>Program.settings</c>. /// </summary> public void think() { if (!alive) { return; } for (int i = 0; i < num_eyes; ++i) { brain.set_input(i, (float)eyes[i].ray.v); } int extra = 0; if (Program.settings.think_distance) { brain.set_input(num_eyes + extra++, (float)(((m.goal * m.cell_size - velocity.O) / ((m.walls.size + 1) * m.cell_size)).length())); } if (Program.settings.think_path) { int this_pos = m.walls.get_path_value(m.start) + 1; if (m.walls.in_bounds(grid_pos)) { this_pos = m.walls.get_path_value(grid_pos); } brain.set_input(num_eyes + extra++, (float)this_pos / (float)m.walls.get_path_value(m.start)); int dir = 0; if (velocity.north_quad()) { dir = 1; } else if (velocity.east_quad()) { dir = 2; } else if (velocity.south_quad()) { dir = 3; } for (int i = 0; i < 4; ++i) { int index = (i + dir) % 4; if (m.walls.test_wall(grid_pos, index) || this_pos < m.walls.get_path_value(grid_pos + Wall_grid.order[index])) { brain.set_input(num_eyes + extra++, 0); } else { brain.set_input(num_eyes + extra++, 1); } } } if (Program.settings.think_velocity) { CoordD magnitude = new CoordD(0, 0).by_angle(velocity.θ, 1.0); brain.set_input(num_eyes + extra++, (float)magnitude.x); brain.set_input(num_eyes + extra++, (float)magnitude.y); brain.set_input(num_eyes + extra++, (float)speed); } brain.think(); act(brain.get_output(0), brain.get_output(1)); }