Prototype switch circuitnode implementation
parent
b4cc068efa
commit
c179f234dd
|
@ -230,14 +230,16 @@ pub fn isEnabled(this: @This(), cell: Cell) bool {
|
||||||
return this.levels[i] >= 1;
|
return this.levels[i] >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle(this: *@This(), c: Cell) void {
|
pub fn toggle(this: *@This(), c: Cell) ?u8 {
|
||||||
const cell = c;
|
const cell = c;
|
||||||
if (this.get_cell(cell)) |tile| {
|
if (this.get_cell(cell)) |tile| {
|
||||||
if (T.is_switch(tile)) {
|
if (T.is_switch(tile)) {
|
||||||
const toggled = toggle_switch(tile);
|
const toggled = toggle_switch(tile);
|
||||||
this.set_cell(cell, toggled);
|
this.set_cell(cell, toggled);
|
||||||
|
return tile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clearMap(this: *@This()) void {
|
pub fn clearMap(this: *@This()) void {
|
||||||
|
|
20
src/game.zig
20
src/game.zig
|
@ -651,7 +651,22 @@ fn manipulationProcess(pos: *Pos, control: *Control) !void {
|
||||||
},
|
},
|
||||||
.lever => {
|
.lever => {
|
||||||
const cell = @divTrunc(i.pos, Map.tile_size);
|
const cell = @divTrunc(i.pos, Map.tile_size);
|
||||||
circuit.toggle(cell);
|
const new_switch = circuit.toggle(cell);
|
||||||
|
if (new_switch) |tile| {
|
||||||
|
const T = world.Tiles;
|
||||||
|
// TODO: make switch system better
|
||||||
|
const new_state: world.NodeKind.SwitchEnum = switch(tile) {
|
||||||
|
T.SwitchTeeWestOn => .North,
|
||||||
|
T.SwitchTeeWestOff => .West,
|
||||||
|
T.SwitchTeeEastOn => .North,
|
||||||
|
T.SwitchTeeEastOff => .East,
|
||||||
|
T.SwitchVerticalOn => .South,
|
||||||
|
else => .Off,
|
||||||
|
};
|
||||||
|
const x = level.world_x * 20 + @intCast(i16, cell[0]);
|
||||||
|
const y = level.world_y * 20 + @intCast(i16, cell[1]);
|
||||||
|
db.setSwitch(Coord.init(.{ x, y }), new_state);
|
||||||
|
}
|
||||||
try updateCircuit();
|
try updateCircuit();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -728,7 +743,8 @@ fn updateCircuit() !void {
|
||||||
w4.tracef("[%d]: Socket [%d] <%d>", n, socket, e);
|
w4.tracef("[%d]: Socket [%d] <%d>", n, socket, e);
|
||||||
},
|
},
|
||||||
.Plug => |Plug| w4.tracef("[%d]: Plug [%d] <%d>", n, Plug, e),
|
.Plug => |Plug| w4.tracef("[%d]: Plug [%d] <%d>", n, Plug, e),
|
||||||
.Switch => |Switch| w4.tracef("[%d]: Switch [%s] <%d>", n, &@tagName(Switch), e),
|
.Switch => |Switch| w4.tracef("[%d]: Switch %d [%d] <%d>", n, Switch.state, Switch.source, e),
|
||||||
|
.SwitchOutlet => |Switch| w4.tracef("[%d]: SwitchOutlet %d [%d] <%d>", n, Switch.which, Switch.source, e),
|
||||||
.Join => |Join| w4.tracef("[%d]: Join [%d] <%d>", n, Join, e),
|
.Join => |Join| w4.tracef("[%d]: Join [%d] <%d>", n, Join, e),
|
||||||
.Outlet => |Outlet| w4.tracef("[%d]: Outlet [%d] <%d>", n, Outlet, e),
|
.Outlet => |Outlet| w4.tracef("[%d]: Outlet [%d] <%d>", n, Outlet, e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,16 @@ pub const TileData = union(enum) {
|
||||||
circuit: CircuitType,
|
circuit: CircuitType,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
pub fn getCircuit(data: TileData) ?CircuitType {
|
||||||
|
switch (data) {
|
||||||
|
.tile => |_| return null,
|
||||||
|
.flags => |flags| {
|
||||||
|
if (flags.circuit == .None) return null;
|
||||||
|
return flags.circuit;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toByte(data: TileData) u8 {
|
pub fn toByte(data: TileData) u8 {
|
||||||
switch (data) {
|
switch (data) {
|
||||||
.tile => |int| return 0b1000_0000 | @intCast(u8, int),
|
.tile => |int| return 0b1000_0000 | @intCast(u8, int),
|
||||||
|
@ -665,6 +675,12 @@ pub const Database = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn setSwitch(db: *Database, coord: Coord, new_state: NodeKind.SwitchEnum) void {
|
||||||
|
const _switch = db.getNodeID(coord) orelse return;
|
||||||
|
db.circuit_info[_switch].kind.Switch.state = new_state;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn isEnergized(db: *Database, coord: Coord) bool {
|
pub fn isEnergized(db: *Database, coord: Coord) bool {
|
||||||
for (db.circuit_info) |node, i| {
|
for (db.circuit_info) |node, i| {
|
||||||
if (!coord.eq(node.coord)) continue;
|
if (!coord.eq(node.coord)) continue;
|
||||||
|
@ -702,10 +718,16 @@ pub const Database = struct {
|
||||||
.Plug => |Plug| {
|
.Plug => |Plug| {
|
||||||
db.circuit_info[i].energized = db.circuit_info[Plug].energized;
|
db.circuit_info[i].energized = db.circuit_info[Plug].energized;
|
||||||
},
|
},
|
||||||
.Switch => |state| {
|
.Switch => |_Switch| {
|
||||||
// TODO Rework switch to make sense
|
db.circuit_info[i].energized = db.circuit_info[_Switch.source].energized;
|
||||||
db.circuit_info[i].energized = false;
|
},
|
||||||
_ = state;
|
.SwitchOutlet => |_Switch| {
|
||||||
|
const _switch = db.circuit_info[_Switch.source];
|
||||||
|
const _outlet = db.circuit_info[i].kind.SwitchOutlet;
|
||||||
|
// If the switch isn't energized, this outlet is not energized
|
||||||
|
if (!_switch.energized) db.circuit_info[i].energized = false;
|
||||||
|
// If the switch is energized, check that it is outputting to this outlet
|
||||||
|
db.circuit_info[i].energized = _outlet.which == _switch.kind.Switch.state;
|
||||||
},
|
},
|
||||||
.Join => |Join| {
|
.Join => |Join| {
|
||||||
db.circuit_info[i].energized = db.circuit_info[Join].energized;
|
db.circuit_info[i].energized = db.circuit_info[Join].energized;
|
||||||
|
@ -772,6 +794,7 @@ const NodeEnum = enum(u4) {
|
||||||
Plug,
|
Plug,
|
||||||
Socket,
|
Socket,
|
||||||
Switch,
|
Switch,
|
||||||
|
SwitchOutlet,
|
||||||
Join,
|
Join,
|
||||||
Outlet,
|
Outlet,
|
||||||
};
|
};
|
||||||
|
@ -798,11 +821,25 @@ pub const NodeKind = union(NodeEnum) {
|
||||||
/// Vertical = Off or Top/Bottom, depending on flow
|
/// Vertical = Off or Top/Bottom, depending on flow
|
||||||
/// Horizontal = Off or Left/Right, depending on flow
|
/// Horizontal = Off or Left/Right, depending on flow
|
||||||
/// Tee = Top/Bottom or Left/Right, depending on flow
|
/// Tee = Top/Bottom or Left/Right, depending on flow
|
||||||
Switch: SwitchEnum,
|
Switch: Switch,
|
||||||
|
/// Interface between a switch and other components. Each one
|
||||||
|
/// of these represents a possible outlet on a switch, and reads
|
||||||
|
/// the state of the switch to determine if it is powered or not
|
||||||
|
SwitchOutlet: SwitchOutlet,
|
||||||
|
/// Connection between levels
|
||||||
Join: NodeID,
|
Join: NodeID,
|
||||||
|
/// Used to identify entities that recieve power, like doors
|
||||||
Outlet: NodeID,
|
Outlet: NodeID,
|
||||||
|
|
||||||
const SwitchEnum = enum { Off, Bottom, Top, Left, Right };
|
pub const Switch = struct {
|
||||||
|
source: NodeID,
|
||||||
|
state: SwitchEnum,
|
||||||
|
};
|
||||||
|
pub const SwitchOutlet = struct {
|
||||||
|
source: NodeID,
|
||||||
|
which: SwitchEnum,
|
||||||
|
};
|
||||||
|
pub const SwitchEnum = enum { Off, North, West, East, South };
|
||||||
|
|
||||||
pub fn read(reader: anytype) !NodeKind {
|
pub fn read(reader: anytype) !NodeKind {
|
||||||
var kind: NodeKind = undefined;
|
var kind: NodeKind = undefined;
|
||||||
|
@ -839,9 +876,16 @@ pub const NodeKind = union(NodeEnum) {
|
||||||
kind = .{ .Plug = try reader.readInt(NodeID, .Little) };
|
kind = .{ .Plug = try reader.readInt(NodeID, .Little) };
|
||||||
},
|
},
|
||||||
.Switch => {
|
.Switch => {
|
||||||
kind = .{
|
kind = .{ .Switch = .{
|
||||||
.Switch = @intToEnum(SwitchEnum, try reader.readInt(NodeID, .Little)),
|
.source = try reader.readInt(NodeID, .Little),
|
||||||
};
|
.state = @intToEnum(SwitchEnum, try reader.readInt(u8, .Little)),
|
||||||
|
} };
|
||||||
|
},
|
||||||
|
.SwitchOutlet => {
|
||||||
|
kind = .{ .SwitchOutlet = .{
|
||||||
|
.source = try reader.readInt(NodeID, .Little),
|
||||||
|
.which = @intToEnum(SwitchEnum, try reader.readInt(u8, .Little)),
|
||||||
|
} };
|
||||||
},
|
},
|
||||||
.Join => {
|
.Join => {
|
||||||
kind = .{ .Join = try reader.readInt(NodeID, .Little) };
|
kind = .{ .Join = try reader.readInt(NodeID, .Little) };
|
||||||
|
@ -876,8 +920,13 @@ pub const NodeKind = union(NodeEnum) {
|
||||||
const socket = Socket orelse std.math.maxInt(NodeID);
|
const socket = Socket orelse std.math.maxInt(NodeID);
|
||||||
try writer.writeInt(NodeID, socket, .Little);
|
try writer.writeInt(NodeID, socket, .Little);
|
||||||
},
|
},
|
||||||
.Switch => |Switch| {
|
.Switch => |_Switch| {
|
||||||
try writer.writeInt(NodeID, @enumToInt(Switch), .Little);
|
try writer.writeInt(NodeID, _Switch.source, .Little);
|
||||||
|
try writer.writeInt(u8, @enumToInt(_Switch.state), .Little);
|
||||||
|
},
|
||||||
|
.SwitchOutlet => |_Switch| {
|
||||||
|
try writer.writeInt(NodeID, _Switch.source, .Little);
|
||||||
|
try writer.writeInt(u8, @enumToInt(_Switch.which), .Little);
|
||||||
},
|
},
|
||||||
.Join => |Join| {
|
.Join => |Join| {
|
||||||
try writer.writeInt(NodeID, Join, .Little);
|
try writer.writeInt(NodeID, Join, .Little);
|
||||||
|
@ -899,7 +948,8 @@ pub const NodeKind = union(NodeEnum) {
|
||||||
.Source => std.fmt.format(writer, "{s}", .{name}),
|
.Source => std.fmt.format(writer, "{s}", .{name}),
|
||||||
.Plug => |Plug| std.fmt.format(writer, "{s} [{}]", .{ name, Plug }),
|
.Plug => |Plug| std.fmt.format(writer, "{s} [{}]", .{ name, Plug }),
|
||||||
.Socket => |Socket| std.fmt.format(writer, "{s} [{?}]", .{ name, Socket }),
|
.Socket => |Socket| std.fmt.format(writer, "{s} [{?}]", .{ name, Socket }),
|
||||||
.Switch => |Switch| std.fmt.format(writer, "{s} [{s}]", .{ name, @tagName(Switch) }),
|
.Switch => |_Switch| std.fmt.format(writer, "{s} <{s}> [{}]", .{ name, @tagName(_Switch.state), _Switch.source }),
|
||||||
|
.SwitchOutlet => |_Switch| std.fmt.format(writer, "{s} <{s}> [{}]", .{ name, @tagName(_Switch.which), _Switch.source }),
|
||||||
.Join => |Join| std.fmt.format(writer, "{s} [{}]", .{ name, Join }),
|
.Join => |Join| std.fmt.format(writer, "{s} [{}]", .{ name, Join }),
|
||||||
.Outlet => |Outlet| std.fmt.format(writer, "{s} [{}]", .{ name, Outlet }),
|
.Outlet => |Outlet| std.fmt.format(writer, "{s} [{}]", .{ name, Outlet }),
|
||||||
};
|
};
|
||||||
|
|
|
@ -367,7 +367,9 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
switch (flags.circuit) {
|
switch (flags.circuit) {
|
||||||
.Source => {}, // Do nothing, but add everything around the source
|
.Source => {}, // Do nothing, but add everything around the source
|
||||||
.Conduit => {
|
.Conduit => {
|
||||||
// Collects from two other nodes. Needs to store more info in coordinate queue
|
// Collects from two other nodes. Intersections will need to be stored so when
|
||||||
|
// we find out we have to outputs, we can add the conduit and possible rewrite
|
||||||
|
// previous nodes to point to the conduit
|
||||||
// TODO
|
// TODO
|
||||||
},
|
},
|
||||||
.Socket => {
|
.Socket => {
|
||||||
|
@ -393,21 +395,139 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
.coord = coord,
|
.coord = coord,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.Switch_Off => {
|
.Switch_Off, .Switch_On => {
|
||||||
// TODO: Find last coordinate of search and determine flow
|
// Identify input side
|
||||||
|
const last_coord = node.data.last_coord.?;
|
||||||
|
const Dir = enum { North, West, East, South };
|
||||||
|
const input_dir: Dir = dir: {
|
||||||
|
if (last_coord.eq(coord.add(.{ 0, -1 }))) {
|
||||||
|
break :dir .North;
|
||||||
|
} else if (last_coord.eq(coord.add(.{ -1, 0 }))) {
|
||||||
|
break :dir .West;
|
||||||
|
} else if (last_coord.eq(coord.add(.{ 1, 0 }))) {
|
||||||
|
break :dir .East;
|
||||||
|
} else {
|
||||||
|
break :dir .South;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Find outlets
|
||||||
|
const north_opt = level.?.getTile(coord.add(.{ 0, -1 })).?.getCircuit();
|
||||||
|
const west_opt = level.?.getTile(coord.add(.{ -1, 0 })).?.getCircuit();
|
||||||
|
const east_opt = level.?.getTile(coord.add(.{ 1, 0 })).?.getCircuit();
|
||||||
|
const south_opt = level.?.getTile(coord.add(.{ 0, 1 })).?.getCircuit();
|
||||||
|
|
||||||
|
const north = (north_opt orelse world.CircuitType.None) != .None;
|
||||||
|
const west = (west_opt orelse world.CircuitType.None) != .None;
|
||||||
|
const east = (east_opt orelse world.CircuitType.None) != .None;
|
||||||
|
const south = (south_opt orelse world.CircuitType.None) != .None;
|
||||||
|
|
||||||
|
// We don't have four way switches, don't allow them
|
||||||
|
std.debug.assert(west != true or east != true);
|
||||||
|
// We only have vertically oriented switches ATM
|
||||||
|
std.debug.assert(north == true and south == true);
|
||||||
|
|
||||||
|
// Determine initial state of switch
|
||||||
|
const state: world.NodeKind.SwitchEnum = state: {
|
||||||
|
// Vertical switch
|
||||||
|
if (!west and !east) {
|
||||||
|
if (flags.circuit == .Switch_Off) break :state .Off;
|
||||||
|
if (input_dir == .North) break :state .South;
|
||||||
|
break :state .North;
|
||||||
|
}
|
||||||
|
if (east and !west) {
|
||||||
|
if (flags.circuit == .Switch_Off) break :state .East;
|
||||||
|
if (input_dir == .North) break :state .South;
|
||||||
|
break :state .North;
|
||||||
|
}
|
||||||
|
if (west and !east) {
|
||||||
|
if (flags.circuit == .Switch_Off) break :state .West;
|
||||||
|
if (input_dir == .North) break :state .South;
|
||||||
|
break :state .North;
|
||||||
|
}
|
||||||
|
return error.ImpossibleSwitchState;
|
||||||
|
};
|
||||||
|
// Add switch
|
||||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
try nodes.append(.{
|
try nodes.append(.{
|
||||||
.kind = .{ .Switch = .Off },
|
.kind = .{ .Switch = .{
|
||||||
|
.source = last_node,
|
||||||
|
.state = state,
|
||||||
|
} },
|
||||||
.coord = coord,
|
.coord = coord,
|
||||||
});
|
});
|
||||||
},
|
// Add switch outlets
|
||||||
.Switch_On => {
|
if (input_dir != .West and west) {
|
||||||
// TODO: Find last coordinate of search and determine flow
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
|
||||||
try nodes.append(.{
|
try nodes.append(.{
|
||||||
.kind = .{ .Switch = .Off },
|
.kind = .{ .SwitchOutlet = .{
|
||||||
|
.source = next_node,
|
||||||
|
.which = .West,
|
||||||
|
} },
|
||||||
.coord = coord,
|
.coord = coord,
|
||||||
});
|
});
|
||||||
|
const right = try alloc.create(Node);
|
||||||
|
right.* = Node{ .data = .{
|
||||||
|
.last_node = out_node,
|
||||||
|
.coord = coord.add(.{ 1, 0 }),
|
||||||
|
.last_coord = coord,
|
||||||
|
} };
|
||||||
|
bfs_queue.append(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_dir != .East and east) {
|
||||||
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
try nodes.append(.{
|
||||||
|
.kind = .{ .SwitchOutlet = .{
|
||||||
|
.source = next_node,
|
||||||
|
.which = .East,
|
||||||
|
} },
|
||||||
|
.coord = coord,
|
||||||
|
});
|
||||||
|
const left = try alloc.create(Node);
|
||||||
|
left.* = Node{ .data = .{
|
||||||
|
.last_node = out_node,
|
||||||
|
.coord = coord.add(.{ -1, 0 }),
|
||||||
|
.last_coord = coord,
|
||||||
|
} };
|
||||||
|
bfs_queue.append(left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_dir != .South and south) {
|
||||||
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
try nodes.append(.{
|
||||||
|
.kind = .{ .SwitchOutlet = .{
|
||||||
|
.source = next_node,
|
||||||
|
.which = .South,
|
||||||
|
} },
|
||||||
|
.coord = coord,
|
||||||
|
});
|
||||||
|
const down = try alloc.create(Node);
|
||||||
|
down.* = Node{ .data = .{
|
||||||
|
.last_node = out_node,
|
||||||
|
.coord = coord.add(.{ 0, 1 }),
|
||||||
|
.last_coord = coord,
|
||||||
|
} };
|
||||||
|
bfs_queue.append(down);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_dir != .North and north) {
|
||||||
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
try nodes.append(.{
|
||||||
|
.kind = .{ .SwitchOutlet = .{
|
||||||
|
.source = next_node,
|
||||||
|
.which = .North,
|
||||||
|
} },
|
||||||
|
.coord = coord,
|
||||||
|
});
|
||||||
|
const up = try alloc.create(Node);
|
||||||
|
up.* = Node{ .data = .{
|
||||||
|
.last_node = out_node,
|
||||||
|
.coord = coord.add(.{ 0, -1 }),
|
||||||
|
.last_coord = coord,
|
||||||
|
} };
|
||||||
|
bfs_queue.append(up);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
},
|
},
|
||||||
.Join => {
|
.Join => {
|
||||||
const last_coord = node.data.last_coord.?;
|
const last_coord = node.data.last_coord.?;
|
||||||
|
|
Loading…
Reference in New Issue