Code cleanup
This commit is contained in:
parent
80b7e884cd
commit
af3308cfc5
8
README
8
README
|
@ -7,8 +7,14 @@ This creates two main files:
|
|||
# Overview / Assumptions
|
||||
We're using the same coordinate space as the simulator (mms). This is "math coords", with 0, 0 in the lower left and positive y up. North is up
|
||||
|
||||
* Main.zig is our entry point.
|
||||
* It calls Algorithm.zig which is our floodfill implementation. It stores our current knowledge of walls and nodes.
|
||||
* rp2040-bot.zig and simulated-bot.zig implement the same interface for the robot/simulator respectively. They're used by Algorithm.zig to interface with the "world."
|
||||
* Mouse.zig is used by Algorithm.zig to keep track of information about the mouse (mainly position). It also has functions that read or write mouse position.
|
||||
* Map.zig has data types and constants related to the maze (size, goal locations). It gets imported everywhere.
|
||||
|
||||
# Code notes
|
||||
I'm using usize as my default int type so that I can index into arrays with it, I don't know if there's a better option.
|
||||
I'm using usize as my default int type so that I can index into arrays with it.
|
||||
TODO: test with non-square mazes. I did my best but I don't know
|
||||
|
||||
Use std.log.debug. microzig. yeah
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
// TODO: extract this into robot or main or something
|
||||
fn print (comptime fmt: []const u8, args: anytype) void {
|
||||
if (@import("builtin").os.tag != .freestanding) {
|
||||
std.debug.print(fmt, args);
|
||||
}
|
||||
}
|
||||
|
||||
const map = @import("map.zig");
|
||||
const Point = map.Point;
|
||||
const Cardinal = map.Cardinal;
|
||||
const Mouse = @import("mouse.zig").Mouse;
|
||||
|
||||
pub const is_robot = @import("builtin").os.tag == .freestanding;
|
||||
|
||||
// Doesn't have any state
|
||||
// It's a hardware abstraction layer
|
||||
pub const robot = if (is_robot) @import("rp2040-bot.zig") else @import("simulated-bot.zig");
|
||||
|
||||
// It's a little weird to do this as a global, but it just returns
|
||||
// an instance of Mouse with initial values
|
||||
var mouse = @import("mouse.zig").initialize();
|
||||
|
||||
pub fn setup () void {
|
||||
robot.setup();
|
||||
}
|
||||
|
||||
//// Node
|
||||
const Node = struct {
|
||||
p: Point,
|
||||
|
@ -76,16 +83,10 @@ const WallPost = struct {
|
|||
// These are nullable to represent when we haven't seen them yet
|
||||
up: ?bool,
|
||||
right: ?bool,
|
||||
|
||||
// I don't think we need this here, since we always access a Wall Post through
|
||||
// position: struct {
|
||||
// .x: usize,
|
||||
// .y: usize
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
// Might be a better way to do this, initialization
|
||||
// Might be a better way to do this initialization
|
||||
var walls = init: {
|
||||
var initialWalls: [map.height + 1][map.width + 1]WallPost = undefined;
|
||||
var row: [map.width + 1]WallPost = undefined;
|
||||
|
@ -94,24 +95,6 @@ var walls = init: {
|
|||
break :init initialWalls;
|
||||
};
|
||||
|
||||
// const walls = init: {
|
||||
// var walls: [map.width + 1][map.height + 1]Wall = undefined;
|
||||
// for (&nodes, 0..) |*row, y| {
|
||||
// for (&row, 0..) |*n, x| {
|
||||
// n.* = Node {
|
||||
// lmjklkjm
|
||||
|
||||
|
||||
|
||||
// .p = Point{ .x = x, .y = y },
|
||||
// .score = undefined
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// break :init walls;
|
||||
// };
|
||||
|
||||
fn isEdge(p: Point, direction: Cardinal) bool {
|
||||
// std.log.debug("is Edge called with point: {} direction: {}\n", .{p, direction});
|
||||
return (
|
||||
|
@ -124,7 +107,7 @@ fn isEdge(p: Point, direction: Cardinal) bool {
|
|||
|
||||
// Used by both isWall and setWall
|
||||
fn getWall(p: Point, direction: Cardinal) *?bool {
|
||||
// Should be handled by the caller, but it doesn't hurt
|
||||
// Should be handled by the caller
|
||||
assert(!isEdge(p, direction));
|
||||
|
||||
// Direction is north, west, or south we look left.
|
||||
|
@ -167,7 +150,7 @@ pub fn setWall(p: Point, direction: Cardinal, value: bool) void {
|
|||
}
|
||||
|
||||
const wall = getWall(p, direction);
|
||||
// wall.* is a ?bool and value is a bool, will this error?
|
||||
// wall.* is a ?bool and value is a bool, but we can do type coercion
|
||||
wall.* = value;
|
||||
}
|
||||
|
||||
|
@ -198,7 +181,6 @@ test {
|
|||
|
||||
|
||||
//// Algorithm
|
||||
|
||||
fn recalcScores(dest: []const Point) void {
|
||||
// Reset every node to a high score
|
||||
for (&mazeNodes) |*row| {
|
||||
|
@ -228,7 +210,12 @@ fn hasPoint(l: []const Point, needle: Point) bool {
|
|||
|
||||
// Takes a list of destination points, and a mouse
|
||||
// Blocks until the mouse is in one of the destination points
|
||||
pub fn floodFill(mouse: *Mouse, dest: []const Point) void {
|
||||
pub fn floodFill(dest: []const Point) void {
|
||||
if (dest.len == 4) {
|
||||
assert(hasPoint(dest, map.goals[0]));
|
||||
assert(hasPoint(dest, map.goals[3]));
|
||||
}
|
||||
|
||||
mouse.updateWalls();
|
||||
|
||||
// Calculate optimistic distances from the center
|
||||
|
@ -271,9 +258,9 @@ pub fn floodFill(mouse: *Mouse, dest: []const Point) void {
|
|||
mouse.updateWalls();
|
||||
}
|
||||
|
||||
// This isn't always true because sometimes dest isn't the goal
|
||||
assert(hasPoint(dest, mouse.position));
|
||||
if (dest.len == 4) {
|
||||
// This isn't always true because sometimes dest isn't the goal
|
||||
assert(hasPoint(map.goals[0..], mouse.position));
|
||||
}
|
||||
}
|
||||
|
|
19
src/main.zig
19
src/main.zig
|
@ -2,21 +2,18 @@ const std = @import("std");
|
|||
const builtin = @import("builtin");
|
||||
|
||||
const algo = @import("algorithm.zig");
|
||||
const robot = algo.robot;
|
||||
const map = @import("map.zig");
|
||||
|
||||
// TODO: Refactor, move the Mouse declaration into algorithm
|
||||
const mouse = @import("mouse.zig");
|
||||
pub fn main() !noreturn {
|
||||
algo.setup();
|
||||
|
||||
pub fn main() !void {
|
||||
var m = mouse.initialize();
|
||||
// Flood fill to the goal
|
||||
algo.floodFill(map.goals[0..]);
|
||||
|
||||
algo.floodFill(&m, map.goals[0..]);
|
||||
// Flood fill back to the start
|
||||
const starts = [_]map.Point{ map.start };
|
||||
algo.floodFill(&m, starts[0..]);
|
||||
|
||||
m.stall();
|
||||
// if (!mouse.is_robot) {
|
||||
// @import("simulator.zig").moveForward();
|
||||
// }
|
||||
algo.floodFill(starts[0..]);
|
||||
|
||||
robot.stall();
|
||||
}
|
||||
|
|
|
@ -8,29 +8,16 @@ const Cardinal = map.Cardinal;
|
|||
const Point = map.Point;
|
||||
const TurningDirection = map.TurningDirection;
|
||||
|
||||
|
||||
const algo = @import("algorithm.zig");
|
||||
const robot = algo.robot;
|
||||
const setWall = algo.setWall;
|
||||
|
||||
pub const is_robot = @import("builtin").os.tag == .freestanding;
|
||||
|
||||
// Doesn't have any state, even about hardware-related stuff
|
||||
// It's a hardware abstraction layer
|
||||
const robot = if (is_robot) @import("robot.zig") else @import("simulator.zig");
|
||||
|
||||
pub const Mouse = struct {
|
||||
position: map.Point,
|
||||
|
||||
facing: Cardinal,
|
||||
|
||||
// pub fn turn90 (direction: TurningDirection) {
|
||||
// robot.turn90(direction);
|
||||
// self.facing =
|
||||
// }
|
||||
|
||||
// pub fn turn180 (self: Mouse) {
|
||||
|
||||
// }
|
||||
|
||||
pub fn spinTo(self: *Mouse, direction: Cardinal) void {
|
||||
if (self.facing == direction) {
|
||||
// return, we're done!
|
||||
|
@ -66,8 +53,6 @@ pub const Mouse = struct {
|
|||
pub fn moveAdjacent (self: *Mouse, p: Point) void {
|
||||
// |self.position.x - p.x| + |self.position.y - p.y| == 1
|
||||
assert(intDist(self.position.x, p.x) + intDist(self.position.y, p.y) == 1);
|
||||
// assert(@max(self.position.x, p.x) - @min() ==);
|
||||
// assert(abs(@as(isize, self.position.x) - @as(isize, p.x)) + abs(@as(isize, self.position.y) - @as(isize, p.y)) == 1);
|
||||
|
||||
// The direction we need to move to get to this point
|
||||
var direction: Cardinal = undefined;
|
||||
|
@ -126,13 +111,9 @@ pub const Mouse = struct {
|
|||
}
|
||||
}
|
||||
|
||||
// Pass through; it's dumb but it has to happen
|
||||
pub fn stall(self: Mouse) noreturn {
|
||||
_ = self;
|
||||
return robot.stall();
|
||||
}
|
||||
|
||||
pub fn updateWalls(self: Mouse) void {
|
||||
// TODO: Write to the simulator for cosmetics
|
||||
|
||||
// I could probably come up with a read function that takes a direction and yada yada
|
||||
if (self.readNorth()) |isWall| {
|
||||
setWall(self.position, .north, isWall);
|
||||
|
@ -150,8 +131,6 @@ pub const Mouse = struct {
|
|||
};
|
||||
|
||||
pub fn initialize() Mouse {
|
||||
robot.setup();
|
||||
|
||||
return Mouse {
|
||||
.position = map.start,
|
||||
.facing = .north
|
||||
|
|
|
@ -6,17 +6,15 @@ const map = @import("map.zig");
|
|||
const stdin = std.io.getStdIn().reader();
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
// Since this only runs on my computer, we can do whatever we want here
|
||||
// const allocator =
|
||||
|
||||
pub fn setup () void {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Sim docs
|
||||
// https://github.com/mackorone/mms?tab=readme-ov-file#example
|
||||
|
||||
// Since this only runs on my computer, we can do whatever we want here
|
||||
|
||||
pub fn setup () void {}
|
||||
|
||||
// TODO: create a utility function that takes an allocator and reads from std in and returns a &[]u8
|
||||
|
||||
fn waitForAck () void {
|
||||
var input = std.BoundedArray(u8, 128).init(0) catch unreachable;
|
||||
_ = stdin.streamUntilDelimiter(input.writer(), '\n', input.capacity()) catch unreachable;
|
||||
|
@ -28,17 +26,6 @@ pub fn moveForward() void {
|
|||
_ = stdout.write("moveForward\n") catch unreachable;
|
||||
// wait for "ack" on std in
|
||||
waitForAck();
|
||||
|
||||
// var input = std.BoundedArray(u8, 128).init(0) catch unreachable;
|
||||
// const w = input.writer();
|
||||
// // _ = w.write("hi") catch unreachable;
|
||||
// // std.debug.print("Reading stdin {}\n", .{ input.len });
|
||||
// std.log.debug("Reading std in {}", .{input.capacity()});
|
||||
// _ = stdin.streamUntilDelimiter(w, '\n', input.capacity()) catch unreachable;
|
||||
// std.log.debug("Read {}", .{ input });
|
||||
// std.log.debug("{s}", .{ input.slice()[0..input.len] });
|
||||
// const got: []u8 = input.slice();
|
||||
// std.log.debug("{s}", .{ got });
|
||||
}
|
||||
|
||||
pub fn turn90(direction: map.TurningDirection) void {
|
||||
|
@ -66,6 +53,7 @@ pub fn stall() noreturn {
|
|||
|
||||
|
||||
// TODO: Style all of these
|
||||
// TODO: figure out what the above comment means. They're pretty stylish already
|
||||
pub fn readRight() bool {
|
||||
_ = stdout.write("wallRight\n") catch unreachable;
|
||||
|
||||
|
@ -92,11 +80,5 @@ pub fn readFront() bool {
|
|||
}
|
||||
pub fn readBack() bool {
|
||||
// What?
|
||||
// stdout.write("wallBack\n");
|
||||
|
||||
// var input = std.BoundedArray(u8, 128).init(0) catch unreachable;
|
||||
// _ = stdin.streamUntilDelimiter(input.writer(), '\n', input.capacity()) catch unreachable;
|
||||
|
||||
// return std.mem.eql(u8, input.slice(), "true");
|
||||
std.debug.panic();
|
||||
}
|
Loading…
Reference in New Issue