Read and write circuit nodes
parent
c086c6d9de
commit
020e6f3615
176
src/world.zig
176
src/world.zig
|
@ -151,6 +151,18 @@ pub const Coordinate = struct {
|
|||
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 {
|
||||
return .{ .val = .{ coord.val[0] + val[0], coord.val[1] + val[1] } };
|
||||
}
|
||||
|
@ -463,8 +475,7 @@ pub const Entity = struct {
|
|||
};
|
||||
|
||||
// Data format:
|
||||
// | node count | level count |
|
||||
// | node headers... |
|
||||
// | level count | node count |
|
||||
// | level headers... |
|
||||
// | node 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
|
||||
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
|
||||
for (level_headers) |lvl_header| {
|
||||
try lvl_header.write(writer);
|
||||
}
|
||||
|
||||
// Write node data
|
||||
for (circuit_nodes) |node| {
|
||||
try node.write(writer);
|
||||
}
|
||||
|
||||
pub fn read(alloc: std.mem.Allocator, reader: anytype) ![]LevelHeader {
|
||||
// read number of levels
|
||||
const level_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);
|
||||
// Write levels
|
||||
for (levels) |level| {
|
||||
try level.write(writer);
|
||||
}
|
||||
|
||||
return level_headers;
|
||||
}
|
||||
|
||||
const Cursor = std.io.FixedBufferStream([]const u8);
|
||||
pub const Database = struct {
|
||||
cursor: Cursor,
|
||||
level_info: []LevelHeader,
|
||||
circuit_info: []CircuitNode,
|
||||
level_data_begin: usize,
|
||||
// circuit_data_begin: usize,
|
||||
|
||||
const world_data = @embedFile(@import("world_data").path);
|
||||
|
||||
|
@ -528,12 +545,31 @@ pub const Database = struct {
|
|||
|
||||
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());
|
||||
|
||||
return Database{
|
||||
.cursor = cursor,
|
||||
.level_info = levels,
|
||||
.level_info = level_headers,
|
||||
.circuit_info = circuit_nodes,
|
||||
.level_data_begin = level_data_begin,
|
||||
};
|
||||
}
|
||||
|
@ -586,13 +622,25 @@ pub const Database = struct {
|
|||
// An abstract representation of all circuits in game.
|
||||
// abstract_circuit: []CircuitNode,
|
||||
|
||||
const NodeID = u16;
|
||||
pub const NodeID = u8;
|
||||
|
||||
pub const CircuitNode = struct {
|
||||
energized: bool = false,
|
||||
kind: NodeKind,
|
||||
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 {
|
||||
_ = options;
|
||||
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
|
||||
And: [2]NodeID,
|
||||
/// A Xor logic gate
|
||||
|
@ -621,10 +680,91 @@ pub const NodeKind = union(enum) {
|
|||
/// 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: enum { Off, Bottom, Top, Left, Right },
|
||||
Switch: SwitchEnum,
|
||||
Join: 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 {
|
||||
_ = options;
|
||||
if (fmt.len != 0) @compileError("Unknown format character: '" ++ fmt ++ "'");
|
||||
|
|
|
@ -109,12 +109,7 @@ fn make(step: *std.build.Step) !void {
|
|||
defer data.deinit();
|
||||
const writer = data.writer();
|
||||
|
||||
try world.write(level_headers.items, writer);
|
||||
|
||||
// Write levels
|
||||
for (levels.items) |level| {
|
||||
try level.write(writer);
|
||||
}
|
||||
try world.write(writer, level_headers.items, circuit.items, levels.items);
|
||||
|
||||
// Open output file and write data into it
|
||||
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 {
|
||||
coord: Coord,
|
||||
last_coord: ?Coord = null,
|
||||
last_node: u16,
|
||||
last_node: world.NodeID,
|
||||
};
|
||||
const Queue = std.TailQueue(SearchItem);
|
||||
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 coordinate = try alloc.create(Node);
|
||||
coordinate.* = .{ .data = .{
|
||||
.last_node = @intCast(u16, nodes.items.len),
|
||||
.last_node = @intCast(world.NodeID, nodes.items.len),
|
||||
.coord = Coord.init(.{ x, y }),
|
||||
} };
|
||||
switch (tileData) {
|
||||
|
@ -324,7 +319,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
},
|
||||
.Plug => {
|
||||
// try nodes.append(.{ .kind = .{ .Plug = null } });
|
||||
coordinate.data.last_node = 20000;
|
||||
coordinate.data.last_node = std.math.maxInt(world.NodeID);
|
||||
plugs.append(coordinate);
|
||||
},
|
||||
else => {
|
||||
|
@ -370,21 +365,22 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
const flags = tile.flags;
|
||||
|
||||
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
|
||||
// TODO
|
||||
},
|
||||
.Plug => {
|
||||
// These have already been added, so just continue the
|
||||
// search
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Plug = null },
|
||||
.coord = coord,
|
||||
});
|
||||
},
|
||||
.Outlet => {
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Outlet = last_node },
|
||||
.coord = coord,
|
||||
|
@ -392,7 +388,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
},
|
||||
.Switch_Off => {
|
||||
// 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(.{
|
||||
.kind = .{ .Switch = .Off },
|
||||
.coord = coord,
|
||||
|
@ -400,7 +396,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
},
|
||||
.Switch_On => {
|
||||
// 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(.{
|
||||
.kind = .{ .Switch = .Off },
|
||||
.coord = coord,
|
||||
|
@ -412,7 +408,7 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
std.log.warn("Join first side", .{});
|
||||
} else {
|
||||
std.log.warn("Join second side", .{});
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Join = last_node },
|
||||
.coord = coord,
|
||||
|
@ -452,15 +448,15 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
// may have come from a plug
|
||||
return error.OutputToSource;
|
||||
} else if (side == .L) {
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .And = .{ last_node, 20000 } },
|
||||
.kind = .{ .And = .{ last_node, std.math.maxInt(world.NodeID) } },
|
||||
.coord = coord,
|
||||
});
|
||||
} else if (side == .R) {
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .And = .{ 20000, last_node } },
|
||||
.kind = .{ .And = .{ std.math.maxInt(world.NodeID), last_node } },
|
||||
.coord = coord,
|
||||
});
|
||||
}
|
||||
|
@ -498,15 +494,15 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
|||
// may have come from a plug
|
||||
return error.OutputToSource;
|
||||
} else if (side == .L) {
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Xor = .{ last_node, 20000 } },
|
||||
.kind = .{ .Xor = .{ last_node, std.math.maxInt(world.NodeID) } },
|
||||
.coord = coord,
|
||||
});
|
||||
} else if (side == .R) {
|
||||
next_node = @intCast(u16, nodes.items.len);
|
||||
next_node = @intCast(world.NodeID, nodes.items.len);
|
||||
try nodes.append(.{
|
||||
.kind = .{ .Xor = .{ 20000, last_node } },
|
||||
.kind = .{ .Xor = .{ std.math.maxInt(world.NodeID), last_node } },
|
||||
.coord = coord,
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue