Code cleanup

This commit is contained in:
Matthias Portzel 2024-02-23 21:43:21 -05:00
parent 80b7e884cd
commit af3308cfc5
6 changed files with 50 additions and 99 deletions

8
README
View File

@ -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

View File

@ -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));
}
}

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}