Remove catch unreachable

master
Louis Pearson 2022-02-09 00:19:33 -07:00
parent 56746b0041
commit c3227bbd46
7 changed files with 101 additions and 89 deletions

View File

@ -202,15 +202,15 @@ bridges: std.BoundedArray(BridgeState, MAXBRIDGES),
sources: std.BoundedArray(Cell, MAXSOURCES),
doors: std.BoundedArray(DoorState, MAXDOORS),
pub fn init(map: []u8, levels: []u8, map_size: Vec2) @This() {
pub fn init(map: []u8, levels: []u8, map_size: Vec2) !@This() {
std.debug.assert(map.len == levels.len);
var this = @This(){
.map = map,
.levels = levels,
.map_size = map_size,
.bridges = std.BoundedArray(BridgeState, MAXBRIDGES).init(0) catch unreachable,
.sources = std.BoundedArray(Cell, MAXSOURCES).init(0) catch unreachable,
.doors = std.BoundedArray(DoorState, MAXDOORS).init(0) catch unreachable,
.bridges = try std.BoundedArray(BridgeState, MAXBRIDGES).init(0),
.sources = try std.BoundedArray(Cell, MAXSOURCES).init(0),
.doors = try std.BoundedArray(DoorState, MAXDOORS).init(0),
};
return this;
}
@ -225,38 +225,38 @@ pub fn enable(this: *@This(), cell: Cell) void {
this.levels[i] += 1;
}
pub fn bridge(this: *@This(), cells: [2]Cell, bridgeID: usize) void {
pub fn bridge(this: *@This(), cells: [2]Cell, bridgeID: usize) !void {
if (this.indexOf(cells[0])) |_| {
if (this.indexOf(cells[1])) |_| {
this.bridges.append(.{ .cells = cells, .id = bridgeID, .enabled = false }) catch unreachable;
try this.bridges.append(.{ .cells = cells, .id = bridgeID, .enabled = false });
}
}
}
pub fn addSource(this: *@This(), cell: Cell) void {
pub fn addSource(this: *@This(), cell: Cell) !void {
if (this.indexOf(cell)) |_| {
this.sources.append(cell) catch unreachable;
try this.sources.append(cell);
}
}
pub fn addDoor(this: *@This(), cell: Cell) void {
pub fn addDoor(this: *@This(), cell: Cell) !void {
if (this.indexOf(cell)) |_| {
this.doors.append(.{ .cell = cell, .enabled = false }) catch unreachable;
try this.doors.append(.{ .cell = cell, .enabled = false });
}
}
pub fn enabledBridges(this: @This()) std.BoundedArray(usize, MAXBRIDGES) {
var items = std.BoundedArray(usize, MAXBRIDGES).init(0) catch unreachable;
pub fn enabledBridges(this: @This()) !std.BoundedArray(usize, MAXBRIDGES) {
var items = try std.BoundedArray(usize, MAXBRIDGES).init(0);
for (this.bridges.constSlice()) |b| {
if (b.enabled) items.append(b.id) catch unreachable;
if (b.enabled) try items.append(b.id);
}
return items;
}
pub fn enabledDoors(this: @This()) std.BoundedArray(Cell, MAXDOORS) {
var items = std.BoundedArray(Cell, MAXDOORS).init(0) catch unreachable;
pub fn enabledDoors(this: @This()) !std.BoundedArray(Cell, MAXDOORS) {
var items = try std.BoundedArray(Cell, MAXDOORS).init(0);
for (this.doors.constSlice()) |d| {
if (d.enabled) items.append(d.cell) catch unreachable;
if (d.enabled) try items.append(d.cell);
}
return items;
}
@ -281,23 +281,25 @@ pub fn clear(this: *@This()) void {
for (this.doors.slice()) |*door| {
door.enabled = false;
}
// Resizing to zero should always work
this.bridges.resize(0) catch unreachable;
}
pub fn reset(this: *@This()) void {
this.clear();
// Resizing to zero should always work
this.sources.resize(0) catch unreachable;
}
const w4 = @import("wasm4.zig");
const Queue = util.Queue(Cell, MAXCELLS);
// Returns number of cells filled
pub fn fill(this: *@This()) usize {
pub fn fill(this: *@This()) !usize {
var count: usize = 0;
var visited = std.BoundedArray(usize, MAXCELLS).init(0) catch unreachable;
var q = Queue.init();
var visited = try std.BoundedArray(usize, MAXCELLS).init(0);
var q = try Queue.init();
for (this.sources.slice()) |source| {
q.insert(source);
try q.insert(source);
}
while (q.remove()) |cell| {
const tile = this.get_cell(cell) orelse {
@ -312,13 +314,13 @@ pub fn fill(this: *@This()) usize {
this.enable(cell);
const hasVisited = std.mem.containsAtLeast(usize, visited.slice(), 1, &.{index});
if (hasVisited and !is_logic(tile)) continue;
visited.append(index) catch unreachable;
try visited.append(index);
count += 1;
if (get_logic(tile)) |logic| {
// TODO: implement other logic (though I'm pretty sure that requires a graph...)
if (logic != .And) continue;
if (this.levels[index] < 2) continue;
q.insert(cell + util.Dir.up);
try q.insert(cell + util.Dir.up);
}
for (get_outputs(tile)) |conductor, i| {
if (!conductor) continue;
@ -339,15 +341,15 @@ pub fn fill(this: *@This()) usize {
break :here 0;
};
if (get_inputs(nextTile)[@enumToInt(s.opposite())])
q.insert(nextCell);
try q.insert(nextCell);
}
if (is_plug(tile)) {
for (this.bridges.slice()) |*b| {
if (@reduce(.And, b.cells[0] == cell)) {
q.insert(b.cells[1]);
try q.insert(b.cells[1]);
b.enabled = true;
} else if (@reduce(.And, b.cells[1] == cell)) {
q.insert(b.cells[0]);
try q.insert(b.cells[0]);
b.enabled = true;
}
}

View File

@ -58,7 +58,7 @@ pub fn reset() void {
// so a player can see how well they've done with the game in the past.
}
pub fn load() bool {
pub fn load() !bool {
var load_buf: [1024]u8 = undefined;
const read = w4.diskr(&load_buf, 1024);
w4.tracef("%d bytes read", read);
@ -96,12 +96,12 @@ pub fn load() bool {
// player.pos.pos += Vec2f{ 4, 6 };
},
.Coin => {
game.coins.append(.{
try game.coins.append(.{
.pos = pos,
.sprite = .{ .offset = .{ 0, 0 }, .size = .{ 8, 8 }, .index = 4, .flags = .{ .bpp = .b2 } },
.anim = Anim{ .anim = &game.anim_store.coin },
.area = .{ .pos = .{ 0, 0 }, .size = .{ 8, 8 } },
}) catch unreachable;
});
},
.WireBeginPinned => {
var begin = game.wires.slice()[id].begin();

View File

@ -71,24 +71,24 @@ const Particle = struct {
const ParticleSystem = struct {
const MAXPARTICLES = 32;
particles: std.BoundedArray(Particle, MAXPARTICLES),
pub fn init() @This() {
pub fn init() !@This() {
return @This(){
.particles = std.BoundedArray(Particle, MAXPARTICLES).init(0) catch unreachable,
.particles = try std.BoundedArray(Particle, MAXPARTICLES).init(0),
};
}
pub fn update(this: *@This()) void {
pub fn update(this: *@This()) !void {
var physics = .{ .gravity = Vec2f{ 0, 0.1 }, .friction = Vec2f{ 0.1, 0.1 } };
var remove = std.BoundedArray(usize, MAXPARTICLES).init(0) catch unreachable;
var remove = try std.BoundedArray(usize, MAXPARTICLES).init(0);
for (this.particles.slice()) |*part, i| {
if (!inView(part.pos.pos)) {
remove.append(i) catch unreachable;
try remove.append(i);
continue;
}
velocityProcess(1, &part.pos);
physicsProcess(1, &part.pos, &physics);
part.life -= 1;
if (part.life == 0) remove.append(i) catch unreachable;
if (part.life == 0) try remove.append(i);
}
while (remove.popOrNull()) |i| {
_ = this.particles.swapRemove(i);
@ -108,7 +108,9 @@ const ParticleSystem = struct {
const posComp = Pos.initVel(pos, vel);
const life = randRange(10, 50);
const part = Particle.init(posComp, life);
this.particles.append(part) catch unreachable;
// Do nothing on error, we don't care if a particle
// is dropped
this.particles.append(part) catch {};
}
pub fn createNRandom(this: *@This(), pos: Vec2f, n: usize) void {
@ -182,11 +184,11 @@ fn showErr(msg: []const u8) noreturn {
unreachable;
}
pub fn start() void {
particles = ParticleSystem.init();
pub fn start() !void {
particles = try ParticleSystem.init();
std.mem.set(u8, &conduitLevels_mutable, 0);
circuit = Circuit.init(&conduit_mutable, &conduitLevels_mutable, assets.conduit_size);
circuit = try Circuit.init(&conduit_mutable, &conduitLevels_mutable, assets.conduit_size);
map = Map.init(&solids_mutable, assets.solid_size);
camera = @divTrunc(assets.spawn, @splat(2, @as(i32, 20))) * @splat(2, @as(i32, 20));
@ -223,15 +225,15 @@ pub fn start() void {
}
for (assets.sources) |source| {
circuit.addSource(source);
try circuit.addSource(source);
}
for (assets.doors) |door| {
circuit.addDoor(door);
try circuit.addDoor(door);
}
// _ = w4.diskw("", 0);
if (!Disk.load()) {
if (!try Disk.load()) {
for (assets.coins) |coin| {
coins.append(.{
.pos = Pos.init(util.vec2ToVec2f(coin * tile_size)),
@ -242,14 +244,14 @@ pub fn start() void {
}
}
updateCircuit();
try updateCircuit();
}
var indicator: ?Interaction = null;
pub fn update(time: usize) State {
pub fn update(time: usize) !State {
for (wires.slice()) |*wire| {
wirePhysicsProcess(1, wire);
try wirePhysicsProcess(1, wire);
if (wire.enabled) {
if (music.isDrumBeat()) {
if (!wire.begin().pinned) particles.createNRandom(wire.begin().pos, 8);
@ -260,11 +262,11 @@ pub fn update(time: usize) State {
velocityProcess(1, &player.pos);
physicsProcess(1, &player.pos, &player.physics);
manipulationProcess(&player.pos, &player.control);
try manipulationProcess(&player.pos, &player.control);
controlProcess(1, &player.pos, &player.control, &player.physics, &player.kinematic);
kinematicProcess(1, &player.pos, &player.kinematic);
try kinematicProcess(1, &player.pos, &player.kinematic);
controlAnimProcess(1, &player.sprite, &player.controlAnim, &player.control);
particles.update();
try particles.update();
// Drawing
w4.DRAW_COLORS.* = 0x0004;
@ -273,13 +275,13 @@ pub fn update(time: usize) State {
{
var shouldSave = false;
var remove = std.BoundedArray(usize, 10).init(0) catch unreachable;
var remove = try std.BoundedArray(usize, 10).init(0);
for (coins.slice()) |*coin, i| {
staticAnimProcess(1, &coin.sprite, &coin.anim);
drawProcess(1, &coin.pos, &coin.sprite);
if (coin.area.addv(coin.pos.pos).overlaps(player.kinematic.col.addv(player.pos.pos))) {
score += 1;
remove.append(i) catch unreachable;
try remove.append(i);
music.playCollect(score);
shouldSave = true;
}
@ -370,7 +372,7 @@ pub fn update(time: usize) State {
}
// Music
const musicCommand = music.getNext(1);
const musicCommand = try music.getNext(1);
for (musicCommand.constSlice()) |sfx| {
w4.tone(sfx.freq, sfx.duration, sfx.volume, sfx.flags);
}
@ -442,7 +444,7 @@ fn getNearestWireInteraction(pos: Vec2f, range: f32) ?Interaction {
return newIndicator;
}
fn manipulationProcess(pos: *Pos, control: *Control) void {
fn manipulationProcess(pos: *Pos, control: *Control) !void {
var offset = switch (control.facing) {
.left => Vec2f{ -6, 0 },
.right => Vec2f{ 6, 0 },
@ -495,25 +497,25 @@ fn manipulationProcess(pos: *Pos, control: *Control) void {
control.grabbing = .{ .id = wire.id, .which = wire.which };
wires.slice()[wire.id].nodes.slice()[wire.which].pos = pos.pos + Vec2f{ 0, -4 };
wires.slice()[wire.id].nodes.slice()[wire.which].pinned = false;
updateCircuit();
try updateCircuit();
},
.plug => |plug| {
wires.slice()[plug.wireID].nodes.slice()[plug.which].pos = vec2tovec2f(indicator.?.pos);
wires.slice()[plug.wireID].nodes.slice()[plug.which].pinned = true;
control.grabbing = null;
updateCircuit();
try updateCircuit();
},
.lever => {
const cell = @divTrunc(i.pos, Map.tile_size);
circuit.toggle(cell);
updateCircuit();
try updateCircuit();
},
}
}
}
}
fn updateCircuit() void {
fn updateCircuit() !void {
circuit.clear();
for (wires.slice()) |*wire, wireID| {
wire.enabled = false;
@ -522,9 +524,9 @@ fn updateCircuit() void {
const cellBegin = util.world2cell(nodes[0].pos);
const cellEnd = util.world2cell(nodes[nodes.len - 1].pos);
circuit.bridge(.{ cellBegin, cellEnd }, wireID);
try circuit.bridge(.{ cellBegin, cellEnd }, wireID);
}
_ = circuit.fill();
_ = try circuit.fill();
for (wires.slice()) |*wire| {
const begin = wire.begin();
const end = wire.end();
@ -534,13 +536,13 @@ fn updateCircuit() void {
(circuit.isEnabled(cellEnd) and end.pinned)) wire.enabled = true;
}
map.reset(&assets.solid);
const enabledDoors = circuit.enabledDoors();
const enabledDoors = try circuit.enabledDoors();
for (enabledDoors.constSlice()) |door| {
map.set_cell(door, 0);
try map.set_cell(door, 0);
}
}
fn wirePhysicsProcess(dt: f32, wire: *Wire) void {
fn wirePhysicsProcess(dt: f32, wire: *Wire) !void {
var nodes = wire.nodes.slice();
if (nodes.len == 0) return;
if (!inView(wire.begin().pos) and !inView(wire.end().pos)) return;
@ -550,7 +552,7 @@ fn wirePhysicsProcess(dt: f32, wire: *Wire) void {
for (nodes) |*node| {
velocityProcess(dt, node);
physicsProcess(dt, node, &physics);
kinematicProcess(dt, node, &kinematic);
try kinematicProcess(dt, node, &kinematic);
}
var iterations: usize = 0;
@ -559,8 +561,8 @@ fn wirePhysicsProcess(dt: f32, wire: *Wire) void {
while (left < nodes.len) : (left += 1) {
// Left side
constrainNodes(&nodes[left - 1], &nodes[left]);
kinematicProcess(dt, &nodes[left - 1], &kinematic);
kinematicProcess(dt, &nodes[left], &kinematic);
try kinematicProcess(dt, &nodes[left - 1], &kinematic);
try kinematicProcess(dt, &nodes[left], &kinematic);
}
}
}
@ -678,10 +680,10 @@ fn controlProcess(_: f32, pos: *Pos, control: *Control, physics: *Physics, kinem
pos.pos += move;
}
fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) void {
fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) !void {
var next = pos.last;
next[0] = pos.pos[0];
var hcol = map.collide(kinematic.col.addv(next));
var hcol = try map.collide(kinematic.col.addv(next));
if (hcol.len > 0) {
kinematic.lastCol[0] = next[0] - pos.last[0];
next[0] = pos.last[0];
@ -690,7 +692,7 @@ fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) void {
}
next[1] = pos.pos[1];
var vcol = map.collide(kinematic.col.addv(next));
var vcol = try map.collide(kinematic.col.addv(next));
if (vcol.len > 0) {
kinematic.lastCol[1] = next[1] - pos.last[1];
next[1] = pos.last[1];
@ -699,7 +701,7 @@ fn kinematicProcess(_: f32, pos: *Pos, kinematic: *Kinematic) void {
}
var colPosAbs = next + kinematic.lastCol;
var lastCol = map.collide(kinematic.col.addv(colPosAbs));
var lastCol = try map.collide(kinematic.col.addv(colPosAbs));
if (lastCol.len == 0) {
kinematic.lastCol = Vec2f{ 0, 0 };
}

View File

@ -27,13 +27,21 @@ export fn start() void {
export fn update() void {
const newState = switch (state) {
.Menu => menu.update(),
.Game => game.update(time),
.Game => game.update(time) catch |e| switch (e) {
error.Overflow => showErr(@errorName(e)),
error.OutOfBounds => showErr(@errorName(e)),
error.IndexOutOfBounds => showErr(@errorName(e)),
},
};
if (state != newState) {
state = newState;
switch (newState) {
.Menu => menu.start(),
.Game => game.start(),
.Game => game.start() catch |e| switch (e) {
error.Overflow => showErr(@errorName(e)),
error.OutOfBounds => showErr(@errorName(e)),
error.IndexOutOfBounds => showErr(@errorName(e)),
},
}
}
input.update();

View File

@ -59,10 +59,10 @@ pub fn load_diff(this: *@This(), diff: []const u8) void {
}
}
pub fn set_cell(this: *@This(), cell: Cell, tile: u8) void {
pub fn set_cell(this: *@This(), cell: Cell, tile: u8) !void {
const x = cell[0];
const y = cell[1];
if (x < 0 or x > this.map_size[0] or y < 0 or y > this.map_size[1]) unreachable;
if (x < 0 or x > this.map_size[0] or y < 0 or y > this.map_size[1]) return error.OutOfBounds;
const i = x + y * this.map_size[0];
this.tiles[@intCast(usize, i)] = tile;
}
@ -109,23 +109,23 @@ fn getTile(this: @This(), x: i32, y: i32) ?u8 {
return this.tiles[@intCast(u32, i)];
}
pub fn collide(this: @This(), rect: util.AABB) std.BoundedArray(util.AABB, 9) {
pub fn collide(this: @This(), rect: util.AABB) !std.BoundedArray(util.AABB, 9) {
const top_left = rect.pos / tile_sizef;
const bot_right = (rect.pos + rect.size) / tile_sizef;
var collisions = std.BoundedArray(util.AABB, 9).init(0) catch unreachable;
var collisions = try std.BoundedArray(util.AABB, 9).init(0);
var i: isize = @floatToInt(i32, top_left[0]);
while (i <= @floatToInt(i32, bot_right[0])) : (i += 1) {
var a: isize = @floatToInt(i32, top_left[1]);
while (a <= @floatToInt(i32, bot_right[1])) : (a += 1) {
if (this.isSolid(Cell{ i, a })) {
collisions.append(util.AABB{
try collisions.append(util.AABB{
.pos = Vec2f{
@intToFloat(f32, i * tile_width),
@intToFloat(f32, a * tile_height),
},
.size = tile_sizef,
}) catch unreachable;
});
}
}
}

View File

@ -91,8 +91,8 @@ pub const Procedural = struct {
this.collect = .{ .score = score, .start = beatTotal + 1, .end = beatTotal + (this.beatsPerBar * length) + 1 };
}
pub fn getNext(this: *@This(), dt: u32) MusicCommand {
var cmd = MusicCommand.init(0) catch unreachable;
pub fn getNext(this: *@This(), dt: u32) !MusicCommand {
var cmd = try MusicCommand.init(0);
const beatProgress = this.tick % this.beat;
const beatTotal = @divTrunc(this.tick, this.beat);
const beat = beatTotal % this.beatsPerBar;
@ -103,12 +103,12 @@ pub const Procedural = struct {
const playNote = if (collect.score < 6) beat % 2 == 0 else beat % 4 != 3;
if (beatTotal >= collect.start and beatTotal < collect.end and playNote and beatProgress == 0) {
// const notelen = @intCast(u8, this.beat * this.beatsPerBar);
cmd.append(Sfx{
try cmd.append(Sfx{
.freq = .{ .start = this.nextNote(this.note) },
.duration = .{ .sustain = 5, .release = 5 },
.volume = 25,
.flags = .{ .channel = .pulse2, .mode = .p25 },
}) catch unreachable;
});
this.note += 1;
}
if (bar > collect.end) {
@ -116,24 +116,24 @@ pub const Procedural = struct {
this.collect = null;
}
}
if (this.intensity.atLeast(.calm) and beat == 0 and beatProgress == 0) cmd.append(.{
if (this.intensity.atLeast(.calm) and beat == 0 and beatProgress == 0) try cmd.append(.{
.freq = .{ .start = 220, .end = 110 },
.duration = .{ .release = 3 },
.volume = 100,
.flags = .{ .channel = .triangle },
}) catch unreachable;
if (this.intensity.atLeast(.active) and beat == this.beatsPerBar / 2 and beatProgress == 0) cmd.append(.{
});
if (this.intensity.atLeast(.active) and beat == this.beatsPerBar / 2 and beatProgress == 0) try cmd.append(.{
.freq = .{ .start = 110, .end = 55 },
.duration = .{ .release = 3 },
.volume = 100,
.flags = .{ .channel = .triangle },
}) catch unreachable;
if (this.walking and beat % 3 == 1 and beatProgress == 7) cmd.append(.{
});
if (this.walking and beat % 3 == 1 and beatProgress == 7) try cmd.append(.{
.freq = .{ .start = 1761, .end = 1 },
.duration = .{ .release = 5 },
.volume = 25,
.flags = .{ .channel = .noise },
}) catch unreachable;
});
return cmd;
}
};

View File

@ -67,13 +67,13 @@ pub const AABB = struct {
pub fn Queue(comptime T: type, len: usize) type {
return struct {
data: std.BoundedArray(T, len),
pub fn init() @This() {
pub fn init() !@This() {
return @This(){
.data = std.BoundedArray(T, len).init(0) catch unreachable,
.data = try std.BoundedArray(T, len).init(0),
};
}
pub fn insert(this: *@This(), t: T) void {
this.data.insert(0, t) catch unreachable;
pub fn insert(this: *@This(), t: T) !void {
try this.data.insert(0, t);
}
pub fn remove(this: *@This()) ?Cell {
return this.data.popOrNull();