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;
|
||||
}
|
||||
|
||||
pub fn toggle(this: *@This(), c: Cell) void {
|
||||
pub fn toggle(this: *@This(), c: Cell) ?u8 {
|
||||
const cell = c;
|
||||
if (this.get_cell(cell)) |tile| {
|
||||
if (T.is_switch(tile)) {
|
||||
const toggled = toggle_switch(tile);
|
||||
this.set_cell(cell, toggled);
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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 => {
|
||||
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();
|
||||
},
|
||||
}
|
||||
|
@ -728,7 +743,8 @@ fn updateCircuit() !void {
|
|||
w4.tracef("[%d]: Socket [%d] <%d>", n, socket, 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),
|
||||
.Outlet => |Outlet| w4.tracef("[%d]: Outlet [%d] <%d>", n, Outlet, e),
|
||||
}
|
||||
|
|
|
@ -116,6 +116,16 @@ pub const TileData = union(enum) {
|
|||
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 {
|
||||
switch (data) {
|
||||
.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 {
|
||||
for (db.circuit_info) |node, i| {
|
||||
if (!coord.eq(node.coord)) continue;
|
||||
|
@ -702,10 +718,16 @@ pub const Database = struct {
|
|||
.Plug => |Plug| {
|
||||
db.circuit_info[i].energized = db.circuit_info[Plug].energized;
|
||||
},
|
||||
.Switch => |state| {
|
||||
// TODO Rework switch to make sense
|
||||
db.circuit_info[i].energized = false;
|
||||
_ = state;
|
||||
.Switch => |_Switch| {
|
||||
db.circuit_info[i].energized = db.circuit_info[_Switch.source].energized;
|
||||
},
|
||||
.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| {
|
||||
db.circuit_info[i].energized = db.circuit_info[Join].energized;
|
||||
|
@ -772,6 +794,7 @@ const NodeEnum = enum(u4) {
|
|||
Plug,
|
||||
Socket,
|
||||
Switch,
|
||||
SwitchOutlet,
|
||||
Join,
|
||||
Outlet,
|
||||
};
|
||||
|
@ -798,11 +821,25 @@ pub const NodeKind = union(NodeEnum) {
|
|||
/// Vertical = Off or Top/Bottom, depending on flow
|
||||
/// Horizontal = Off 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,
|
||||
/// Used to identify entities that recieve power, like doors
|
||||
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 {
|
||||
var kind: NodeKind = undefined;
|
||||
|
@ -839,9 +876,16 @@ pub const NodeKind = union(NodeEnum) {
|
|||
kind = .{ .Plug = try reader.readInt(NodeID, .Little) };
|
||||
},
|
||||
.Switch => {
|
||||
kind = .{
|
||||
.Switch = @intToEnum(SwitchEnum, try reader.readInt(NodeID, .Little)),
|
||||
};
|
||||
kind = .{ .Switch = .{
|
||||
.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 => {
|
||||
kind = .{ .Join = try reader.readInt(NodeID, .Little) };
|
||||
|
@ -876,8 +920,13 @@ pub const NodeKind = union(NodeEnum) {
|
|||
const socket = Socket orelse std.math.maxInt(NodeID);
|
||||
try writer.writeInt(NodeID, socket, .Little);
|
||||
},
|
||||
.Switch => |Switch| {
|
||||
try writer.writeInt(NodeID, @enumToInt(Switch), .Little);
|
||||
.Switch => |_Switch| {
|
||||
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| {
|
||||
try writer.writeInt(NodeID, Join, .Little);
|
||||
|
@ -899,7 +948,8 @@ pub const NodeKind = union(NodeEnum) {
|
|||
.Source => std.fmt.format(writer, "{s}", .{name}),
|
||||
.Plug => |Plug| std.fmt.format(writer, "{s} [{}]", .{ name, Plug }),
|
||||
.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 }),
|
||||
.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) {
|
||||
.Source => {}, // Do nothing, but add everything around the source
|
||||
.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
|
||||
},
|
||||
.Socket => {
|
||||
|
@ -393,21 +395,139 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
.coord = coord,
|
||||
});
|
||||
},
|
||||
.Switch_Off => {
|
||||
// TODO: Find last coordinate of search and determine flow
|
||||
.Switch_Off, .Switch_On => {
|
||||
// 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);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Switch = .Off },
|
||||
.coord = coord,
|
||||
});
|
||||
},
|
||||
.Switch_On => {
|
||||
// TODO: Find last coordinate of search and determine flow
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Switch = .Off },
|
||||
.kind = .{ .Switch = .{
|
||||
.source = last_node,
|
||||
.state = state,
|
||||
} },
|
||||
.coord = coord,
|
||||
});
|
||||
// Add switch outlets
|
||||
if (input_dir != .West and west) {
|
||||
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .SwitchOutlet = .{
|
||||
.source = next_node,
|
||||
.which = .West,
|
||||
} },
|
||||
.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 => {
|
||||
const last_coord = node.data.last_coord.?;
|
||||
|
|
Loading…
Reference in New Issue