Read and write circuit nodes

master
Louis Pearson 2022-08-07 15:56:26 -06:00
parent c086c6d9de
commit 020e6f3615
2 changed files with 177 additions and 41 deletions

View File

@ -151,6 +151,18 @@ pub const Coordinate = struct {
return Coordinate{ .val = val }; return Coordinate{ .val = val };
} }
pub fn read(reader: anytype) !Coordinate {
return Coordinate{ .val = .{
try reader.readInt(i16, .Little),
try reader.readInt(i16, .Little),
} };
}
pub fn write(coord: Coordinate, writer: anytype) !void {
try writer.writeInt(i16, coord.val[0], .Little);
try writer.writeInt(i16, coord.val[1], .Little);
}
pub fn add(coord: Coordinate, val: [2]i16) Coordinate { pub fn add(coord: Coordinate, val: [2]i16) Coordinate {
return .{ .val = .{ coord.val[0] + val[0], coord.val[1] + val[1] } }; return .{ .val = .{ coord.val[0] + val[0], coord.val[1] + val[1] } };
} }
@ -463,8 +475,7 @@ pub const Entity = struct {
}; };
// Data format: // Data format:
// | node count | level count | // | level count | node count |
// | node headers... |
// | level headers... | // | level headers... |
// | node data... | // | node data... |
// | level data... | // | level data... |
@ -489,34 +500,40 @@ pub const LevelHeader = struct {
} }
}; };
pub fn write(level_headers: []LevelHeader, writer: anytype) !void { pub fn write(
writer: anytype,
level_headers: []LevelHeader,
circuit_nodes: []CircuitNode,
levels: []Level,
) !void {
// Write number of levels // Write number of levels
try writer.writeInt(u16, @intCast(u16, level_headers.len), .Little); try writer.writeInt(u16, @intCast(u16, level_headers.len), .Little);
// Write number of circuit nodes
try writer.writeInt(u16, @intCast(u16, circuit_nodes.len), .Little);
// Write headers // Write headers
for (level_headers) |lvl_header| { for (level_headers) |lvl_header| {
try lvl_header.write(writer); try lvl_header.write(writer);
} }
}
pub fn read(alloc: std.mem.Allocator, reader: anytype) ![]LevelHeader { // Write node data
// read number of levels for (circuit_nodes) |node| {
const level_count = try reader.readInt(u16, .Little); try node.write(writer);
var level_headers = try alloc.alloc(LevelHeader, level_count);
// read headers
for (level_headers) |_, i| {
level_headers[i] = try LevelHeader.read(reader);
} }
return level_headers; // Write levels
for (levels) |level| {
try level.write(writer);
}
} }
const Cursor = std.io.FixedBufferStream([]const u8); const Cursor = std.io.FixedBufferStream([]const u8);
pub const Database = struct { pub const Database = struct {
cursor: Cursor, cursor: Cursor,
level_info: []LevelHeader, level_info: []LevelHeader,
circuit_info: []CircuitNode,
level_data_begin: usize, level_data_begin: usize,
// circuit_data_begin: usize,
const world_data = @embedFile(@import("world_data").path); const world_data = @embedFile(@import("world_data").path);
@ -528,12 +545,31 @@ pub const Database = struct {
var reader = cursor.reader(); var reader = cursor.reader();
var levels = try read(alloc, reader); // read number of levels
const level_count = try reader.readInt(u16, .Little);
// read number of nodes
const node_count = try reader.readInt(u16, .Little);
var level_headers = try alloc.alloc(LevelHeader, level_count);
// read headers
for (level_headers) |_, i| {
level_headers[i] = try LevelHeader.read(reader);
}
var circuit_nodes = try alloc.alloc(CircuitNode, node_count);
// read headers
for (circuit_nodes) |_, i| {
circuit_nodes[i] = try CircuitNode.read(reader);
}
var level_data_begin = @intCast(usize, try cursor.getPos()); var level_data_begin = @intCast(usize, try cursor.getPos());
return Database{ return Database{
.cursor = cursor, .cursor = cursor,
.level_info = levels, .level_info = level_headers,
.circuit_info = circuit_nodes,
.level_data_begin = level_data_begin, .level_data_begin = level_data_begin,
}; };
} }
@ -586,13 +622,25 @@ pub const Database = struct {
// An abstract representation of all circuits in game. // An abstract representation of all circuits in game.
// abstract_circuit: []CircuitNode, // abstract_circuit: []CircuitNode,
const NodeID = u16; pub const NodeID = u8;
pub const CircuitNode = struct { pub const CircuitNode = struct {
energized: bool = false, energized: bool = false,
kind: NodeKind, kind: NodeKind,
coord: Coordinate, coord: Coordinate,
pub fn read(reader: anytype) !CircuitNode {
return CircuitNode{
.coord = try Coordinate.read(reader),
.kind = try NodeKind.read(reader),
};
}
pub fn write(node: CircuitNode, writer: anytype) !void {
try node.coord.write(writer);
try node.kind.write(writer);
}
pub fn format(node: CircuitNode, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { pub fn format(node: CircuitNode, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
_ = options; _ = options;
if (fmt.len != 0) @compileError("Unknown format character: '" ++ fmt ++ "'"); if (fmt.len != 0) @compileError("Unknown format character: '" ++ fmt ++ "'");
@ -604,7 +652,18 @@ pub const CircuitNode = struct {
} }
}; };
pub const NodeKind = union(enum) { const NodeEnum = enum(u4) {
And,
Xor,
Source,
Conduit,
Plug,
Switch,
Join,
Outlet,
};
pub const NodeKind = union(NodeEnum) {
/// An And logic gate /// An And logic gate
And: [2]NodeID, And: [2]NodeID,
/// A Xor logic gate /// A Xor logic gate
@ -621,10 +680,91 @@ pub const NodeKind = union(enum) {
/// 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: enum { Off, Bottom, Top, Left, Right }, Switch: SwitchEnum,
Join: NodeID, Join: NodeID,
Outlet: NodeID, Outlet: NodeID,
const SwitchEnum = enum { Off, Bottom, Top, Left, Right };
pub fn read(reader: anytype) !NodeKind {
var kind: NodeKind = undefined;
const nodeEnum = @intToEnum(NodeEnum, try reader.readInt(u8, .Little));
switch (nodeEnum) {
.And => {
kind = .{ .And = .{
try reader.readInt(NodeID, .Little),
try reader.readInt(NodeID, .Little),
} };
},
.Xor => {
kind = .{ .Xor = .{
try reader.readInt(NodeID, .Little),
try reader.readInt(NodeID, .Little),
} };
},
.Source => kind = .Source,
.Conduit => {
kind = .{ .Conduit = .{
try reader.readInt(NodeID, .Little),
try reader.readInt(NodeID, .Little),
} };
},
.Plug => {
const plug =
try reader.readInt(NodeID, .Little);
if (plug == std.math.maxInt(NodeID)) {
kind = .{ .Plug = null };
} else {
kind = .{ .Plug = plug };
}
},
.Switch => {
kind = .{
.Switch = @intToEnum(SwitchEnum, try reader.readInt(NodeID, .Little)),
};
},
.Join => {
kind = .{ .Join = try reader.readInt(NodeID, .Little) };
},
.Outlet => {
kind = .{ .Outlet = try reader.readInt(NodeID, .Little) };
},
}
return kind;
}
pub fn write(kind: NodeKind, writer: anytype) !void {
try writer.writeInt(u8, @enumToInt(kind), .Little);
switch (kind) {
.And => |And| {
try writer.writeInt(NodeID, And[0], .Little);
try writer.writeInt(NodeID, And[1], .Little);
},
.Xor => |Xor| {
try writer.writeInt(NodeID, Xor[0], .Little);
try writer.writeInt(NodeID, Xor[1], .Little);
},
.Source => {},
.Conduit => |Conduit| {
try writer.writeInt(NodeID, Conduit[0], .Little);
try writer.writeInt(NodeID, Conduit[1], .Little);
},
.Plug => |Plug| {
const plug = Plug orelse std.math.maxInt(NodeID);
try writer.writeInt(NodeID, plug, .Little);
},
.Switch => |Switch| {
try writer.writeInt(NodeID, @enumToInt(Switch), .Little);
},
.Join => |Join| {
try writer.writeInt(NodeID, Join, .Little);
},
.Outlet => |Outlet| {
try writer.writeInt(NodeID, Outlet, .Little);
},
}
}
pub fn format(kind: NodeKind, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { pub fn format(kind: NodeKind, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
_ = options; _ = options;
if (fmt.len != 0) @compileError("Unknown format character: '" ++ fmt ++ "'"); if (fmt.len != 0) @compileError("Unknown format character: '" ++ fmt ++ "'");

View File

@ -109,12 +109,7 @@ fn make(step: *std.build.Step) !void {
defer data.deinit(); defer data.deinit();
const writer = data.writer(); const writer = data.writer();
try world.write(level_headers.items, writer); try world.write(writer, level_headers.items, circuit.items, levels.items);
// Write levels
for (levels.items) |level| {
try level.write(writer);
}
// Open output file and write data into it // Open output file and write data into it
cwd.makePath(this.builder.getInstallPath(.lib, "")) catch |e| switch (e) { cwd.makePath(this.builder.getInstallPath(.lib, "")) catch |e| switch (e) {
@ -283,7 +278,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
const SearchItem = struct { const SearchItem = struct {
coord: Coord, coord: Coord,
last_coord: ?Coord = null, last_coord: ?Coord = null,
last_node: u16, last_node: world.NodeID,
}; };
const Queue = std.TailQueue(SearchItem); const Queue = std.TailQueue(SearchItem);
const Node = Queue.Node; const Node = Queue.Node;
@ -309,7 +304,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
const y = global_y + @intCast(i16, @divTrunc(i, level.width)); const y = global_y + @intCast(i16, @divTrunc(i, level.width));
const coordinate = try alloc.create(Node); const coordinate = try alloc.create(Node);
coordinate.* = .{ .data = .{ coordinate.* = .{ .data = .{
.last_node = @intCast(u16, nodes.items.len), .last_node = @intCast(world.NodeID, nodes.items.len),
.coord = Coord.init(.{ x, y }), .coord = Coord.init(.{ x, y }),
} }; } };
switch (tileData) { switch (tileData) {
@ -324,7 +319,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
}, },
.Plug => { .Plug => {
// try nodes.append(.{ .kind = .{ .Plug = null } }); // try nodes.append(.{ .kind = .{ .Plug = null } });
coordinate.data.last_node = 20000; coordinate.data.last_node = std.math.maxInt(world.NodeID);
plugs.append(coordinate); plugs.append(coordinate);
}, },
else => { else => {
@ -370,21 +365,22 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
const flags = tile.flags; const flags = tile.flags;
switch (flags.circuit) { switch (flags.circuit) {
.Source, .Conduit => { .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. Needs to store more info in coordinate queue
// TODO // TODO
}, },
.Plug => { .Plug => {
// These have already been added, so just continue the // These have already been added, so just continue the
// search // search
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Plug = null }, .kind = .{ .Plug = null },
.coord = coord, .coord = coord,
}); });
}, },
.Outlet => { .Outlet => {
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Outlet = last_node }, .kind = .{ .Outlet = last_node },
.coord = coord, .coord = coord,
@ -392,7 +388,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
}, },
.Switch_Off => { .Switch_Off => {
// TODO: Find last coordinate of search and determine flow // TODO: Find last coordinate of search and determine flow
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Switch = .Off }, .kind = .{ .Switch = .Off },
.coord = coord, .coord = coord,
@ -400,7 +396,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
}, },
.Switch_On => { .Switch_On => {
// TODO: Find last coordinate of search and determine flow // TODO: Find last coordinate of search and determine flow
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Switch = .Off }, .kind = .{ .Switch = .Off },
.coord = coord, .coord = coord,
@ -412,7 +408,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
std.log.warn("Join first side", .{}); std.log.warn("Join first side", .{});
} else { } else {
std.log.warn("Join second side", .{}); std.log.warn("Join second side", .{});
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Join = last_node }, .kind = .{ .Join = last_node },
.coord = coord, .coord = coord,
@ -452,15 +448,15 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
// may have come from a plug // may have come from a plug
return error.OutputToSource; return error.OutputToSource;
} else if (side == .L) { } else if (side == .L) {
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .And = .{ last_node, 20000 } }, .kind = .{ .And = .{ last_node, std.math.maxInt(world.NodeID) } },
.coord = coord, .coord = coord,
}); });
} else if (side == .R) { } else if (side == .R) {
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .And = .{ 20000, last_node } }, .kind = .{ .And = .{ std.math.maxInt(world.NodeID), last_node } },
.coord = coord, .coord = coord,
}); });
} }
@ -498,15 +494,15 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
// may have come from a plug // may have come from a plug
return error.OutputToSource; return error.OutputToSource;
} else if (side == .L) { } else if (side == .L) {
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Xor = .{ last_node, 20000 } }, .kind = .{ .Xor = .{ last_node, std.math.maxInt(world.NodeID) } },
.coord = coord, .coord = coord,
}); });
} else if (side == .R) { } else if (side == .R) {
next_node = @intCast(u16, nodes.items.len); next_node = @intCast(world.NodeID, nodes.items.len);
try nodes.append(.{ try nodes.append(.{
.kind = .{ .Xor = .{ 20000, last_node } }, .kind = .{ .Xor = .{ std.math.maxInt(world.NodeID), last_node } },
.coord = coord, .coord = coord,
}); });
} }