Update state of circuit graph

master
Louis Pearson 2022-08-07 21:20:22 -06:00
parent 76d50ce508
commit 55c12f4828
2 changed files with 100 additions and 12 deletions

View File

@ -10,6 +10,7 @@ const State = @import("main.zig").State;
// const Disk = @import("disk.zig"); // const Disk = @import("disk.zig");
const extract = @import("extract.zig"); const extract = @import("extract.zig");
const world = @import("world.zig"); const world = @import("world.zig");
const Coord = world.Coordinate;
const world_data = @embedFile(@import("world_data").path); const world_data = @embedFile(@import("world_data").path);
const Vec2 = util.Vec2; const Vec2 = util.Vec2;
@ -253,6 +254,15 @@ fn loadLevel(lvl: usize) !void {
} }
} }
{
var i: usize = 0;
while (level.getJoin(i)) |join| : (i += 1) {
const globalc = Coord.fromWorld(level.world_x, level.world_y).addC(join);
if (db.isEnergized(globalc)) {
circuit.addSource(.{join.val[0], join.val[1]});
}
}
}
try coins.resize(0); try coins.resize(0);
// if (!try Disk.load()) { // if (!try Disk.load()) {
@ -268,7 +278,6 @@ fn loadLevel(lvl: usize) !void {
// } // }
try updateCircuit(); try updateCircuit();
} }
fn moveLevel(direction: enum { L, R, U, D }) !void { fn moveLevel(direction: enum { L, R, U, D }) !void {
@ -625,6 +634,10 @@ fn manipulationProcess(pos: *Pos, control: *Control) !void {
control.grabbing = .{ .id = wire.id, .which = wire.which }; 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].pos = pos.pos + Vec2f{ 0, -4 };
wires.slice()[wire.id].nodes.slice()[wire.which].pinned = false; wires.slice()[wire.id].nodes.slice()[wire.which].pinned = false;
const local32 = vec2ftovec2(wires.slice()[wire.id].nodes.slice()[wire.which].pos / @splat(2, @as(f32, 8)));
const x = level.world_x * 20 + @intCast(i16, local32[0]);
const y = level.world_y * 20 + @intCast(i16, local32[1]);
db.disconnectPlug(Coord.init(.{ x, y }));
try updateCircuit(); try updateCircuit();
}, },
.plug => |plug| { .plug => |plug| {
@ -654,7 +667,6 @@ fn updateCircuit() !void {
circuit.bridge(.{ cellBegin, cellEnd }, wireID); circuit.bridge(.{ cellBegin, cellEnd }, wireID);
const Coord = world.Coordinate;
const topleft = Coord.fromWorld(level.world_x, level.world_y); const topleft = Coord.fromWorld(level.world_x, level.world_y);
const p1 = Coord.init(.{ const p1 = Coord.init(.{
@intCast(i16, cellBegin[0]), @intCast(i16, cellBegin[0]),
@ -695,7 +707,7 @@ fn updateCircuit() !void {
try map.set_cell(door, world.Tiles.Empty); try map.set_cell(door, world.Tiles.Empty);
} }
db.updateCircuit();
} }
fn wirePhysicsProcess(dt: f32, wire: *Wire) !void { fn wirePhysicsProcess(dt: f32, wire: *Wire) !void {

View File

@ -307,6 +307,26 @@ pub const Level = struct {
return tiles[i]; return tiles[i];
} }
pub fn getJoin(level: Level, which: usize) ?Coordinate {
const tiles = level.tiles orelse return null;
var joinCount: usize = 0;
for (tiles) |tile, i| {
switch (tile) {
.flags => |flag| {
if (flag.circuit == .Join) {
if (joinCount == which) {
const x = @intCast(i16, @mod(i, 20));
const y = @intCast(i16, @divFloor(i, 20));
return Coord.init(.{ x, y });
}
}
},
else => continue,
}
}
return null;
}
pub fn getWire(level: *Level, num: usize) ?[2]Entity { pub fn getWire(level: *Level, num: usize) ?[2]Entity {
std.debug.assert(level.entities != null); std.debug.assert(level.entities != null);
var node_begin: ?Entity = null; var node_begin: ?Entity = null;
@ -622,15 +642,71 @@ pub const Database = struct {
if (!p1.eq(node.coord) or !p2.eq(node.coord)) continue; if (!p1.eq(node.coord) or !p2.eq(node.coord)) continue;
if (p1.eq(node.coord)) opt1 = i else opt2 = i; if (p1.eq(node.coord)) opt1 = i else opt2 = i;
} }
var w1 = db.circuit_info[opt1 orelse return]; var plug1 = db.circuit_info[opt1 orelse return];
var w2 = db.circuit_info[opt2 orelse return]; var plug2 = db.circuit_info[opt2 orelse return];
if (w1.energized and !w2.energized) { if (plug1.energized and !plug2.energized) {
w2.energized = true; plug2.energized = true;
w2.kind.Plug = @intCast(NodeID, opt1.?); plug2.kind.Plug = @intCast(NodeID, opt1.?);
} else if (w2.energized and !w1.energized) { } else if (plug2.energized and !plug1.energized) {
w1.energized = true; plug1.energized = true;
w1.kind.Plug = @intCast(NodeID, opt2.?); plug1.kind.Plug = @intCast(NodeID, opt2.?);
}
}
pub fn disconnectPlug(db: *Database, plug: Coord) void {
for (db.circuit_info) |node, i| {
if (!plug.eq(node.coord)) continue;
db.circuit_info[i].energized = false;
}
}
pub fn isEnergized(db: *Database, coord: Coord) bool {
for (db.circuit_info) |node, i| {
if (!coord.eq(node.coord)) continue;
return db.circuit_info[i].energized;
}
return false;
}
pub fn updateCircuit(db: *Database) void {
for (db.circuit_info) |node, i| {
switch (node.kind) {
.And => |And| {
const input1 = db.circuit_info[And[0]].energized;
const input2 = db.circuit_info[And[1]].energized;
db.circuit_info[i].energized = (input1 and input2);
},
.Xor => |Xor| {
const input1 = db.circuit_info[Xor[0]].energized;
const input2 = db.circuit_info[Xor[1]].energized;
db.circuit_info[i].energized = (input1 and !input2) or (input2 and !input1);
},
.Source => db.circuit_info[i].energized = true,
.Conduit => |Conduit| {
const input1 = db.circuit_info[Conduit[0]].energized;
const input2 = db.circuit_info[Conduit[1]].energized;
db.circuit_info[i].energized = (input1 or input2);
},
.Plug => |plug_opt| {
if (plug_opt) |input| {
db.circuit_info[i].energized = db.circuit_info[input].energized;
} else {
db.circuit_info[i].energized = false;
}
},
.Switch => |state| {
// TODO Rework switch to make sense
db.circuit_info[i].energized = false;
_ = state;
},
.Join => |Join| {
db.circuit_info[i].energized = db.circuit_info[Join].energized;
},
.Outlet => |Outlet| {
db.circuit_info[i].energized = db.circuit_info[Outlet].energized;
},
}
} }
} }
}; };