several large improvements
This commit is contained in:
parent
24479e0fe7
commit
9836866ec5
1 changed files with 185 additions and 86 deletions
271
src/main.zig
271
src/main.zig
|
@ -43,34 +43,34 @@ pub fn main() !void {
|
|||
and1.arithmetic_mode = true;
|
||||
and2.arithmetic_mode = true;
|
||||
|
||||
battery1.component.connect(0, &or3.component, 1);
|
||||
battery1.component.connect(0, &or4.component, 1);
|
||||
battery1.component.connect(0, &or5.component, 1);
|
||||
try circuit.connectComponents(&battery1.component, 0, &or3.component, 1);
|
||||
try circuit.connectComponents(&battery1.component, 0, &or4.component, 1);
|
||||
try circuit.connectComponents(&battery1.component, 0, &or5.component, 1);
|
||||
|
||||
battery2.component.connect(0, &or6.component, 0);
|
||||
battery2.component.connect(0, &or7.component, 0);
|
||||
battery2.component.connect(0, &or8.component, 0);
|
||||
try circuit.connectComponents(&battery2.component, 0, &or6.component, 0);
|
||||
try circuit.connectComponents(&battery2.component, 0, &or7.component, 0);
|
||||
try circuit.connectComponents(&battery2.component, 0, &or8.component, 0);
|
||||
|
||||
battery3.component.connect(0, &and1.component, 0);
|
||||
battery3.component.connect(0, &and2.component, 0);
|
||||
try circuit.connectComponents(&battery3.component, 0, &and1.component, 0);
|
||||
try circuit.connectComponents(&battery3.component, 0, &and2.component, 0);
|
||||
|
||||
not1.component.connect(0, &or3.component, 0);
|
||||
not1.component.connect(0, &or1.component, 0);
|
||||
not1.component.connect(0, &or1.component, 1);
|
||||
try circuit.connectComponents(¬1.component, 0, &or3.component, 0);
|
||||
try circuit.connectComponents(¬1.component, 0, &or1.component, 0);
|
||||
try circuit.connectComponents(¬1.component, 0, &or1.component, 1);
|
||||
|
||||
or1.component.connect(0, &or4.component, 0);
|
||||
or1.component.connect(0, &or2.component, 0);
|
||||
or1.component.connect(0, &or2.component, 1);
|
||||
or2.component.connect(0, &or5.component, 0);
|
||||
try circuit.connectComponents(&or1.component, 0, &or4.component, 0);
|
||||
try circuit.connectComponents(&or1.component, 0, &or2.component, 0);
|
||||
try circuit.connectComponents(&or1.component, 0, &or2.component, 1);
|
||||
try circuit.connectComponents(&or2.component, 0, &or5.component, 0);
|
||||
|
||||
or3.component.connect(0, &or6.component, 1);
|
||||
or4.component.connect(0, &or7.component, 1);
|
||||
or5.component.connect(0, &or8.component, 1);
|
||||
try circuit.connectComponents(&or3.component, 0, &or6.component, 1);
|
||||
try circuit.connectComponents(&or4.component, 0, &or7.component, 1);
|
||||
try circuit.connectComponents(&or5.component, 0, &or8.component, 1);
|
||||
|
||||
or6.component.connect(0, &and1.component, 1);
|
||||
and1.component.connect(0, &or1.component, 2);
|
||||
or7.component.connect(0, &and2.component, 1);
|
||||
and2.component.connect(0, &or2.component, 2);
|
||||
try circuit.connectComponents(&or6.component, 0, &and1.component, 1);
|
||||
try circuit.connectComponents(&and1.component, 0, &or1.component, 2);
|
||||
try circuit.connectComponents(&or7.component, 0, &and2.component, 1);
|
||||
try circuit.connectComponents(&and2.component, 0, &or2.component, 2);
|
||||
|
||||
try circuit.tick();
|
||||
|
||||
|
@ -111,20 +111,21 @@ pub fn main() !void {
|
|||
pub const Circuit = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
components: Components,
|
||||
source_components: Components,
|
||||
|
||||
process_order: ?ProcessOrder = null,
|
||||
|
||||
const Components = std.ArrayListUnmanaged(*Component);
|
||||
const ComponentIndex = u32;
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) Circuit {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.components = Components.empty,
|
||||
.source_components = Components.empty,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Circuit) void {
|
||||
self.source_components.deinit(self.allocator);
|
||||
if (self.process_order) |p| self.allocator.free(p);
|
||||
for (0..self.components.items.len) |i| self.components.items[i].deinit(self.allocator);
|
||||
self.components.deinit(self.allocator);
|
||||
}
|
||||
|
@ -133,68 +134,154 @@ pub const Circuit = struct {
|
|||
var c = try T.init(self.allocator);
|
||||
errdefer c.component.deinit(self.allocator);
|
||||
try self.components.append(self.allocator, &c.component);
|
||||
if (T == Battery) try self.source_components.append(self.allocator, &c.component);
|
||||
return c;
|
||||
}
|
||||
|
||||
pub fn connectComponents(self: *Circuit, from: *Component, from_idx: usize, to: *Component, to_idx: usize) !void {
|
||||
try from.connect(self.allocator, from_idx, to, to_idx);
|
||||
}
|
||||
|
||||
pub fn tick(self: *Circuit) !void {
|
||||
var process_order_solver = try ProcessOrderSolver.init(self);
|
||||
defer process_order_solver.deinit();
|
||||
const process_order = process_order_solver.solve();
|
||||
_ = process_order;
|
||||
if (self.process_order == null) try self.updateProcessOrder();
|
||||
for (self.process_order.?) |component| {
|
||||
std.log.debug("processing component: {}", .{component});
|
||||
component.process();
|
||||
}
|
||||
}
|
||||
|
||||
fn updateProcessOrder(self: *Circuit) !void {
|
||||
var process_order = std.ArrayList(*Component).init(self.allocator);
|
||||
errdefer process_order.deinit();
|
||||
|
||||
const visited = try self.allocator.alloc(bool, self.components.items.len);
|
||||
defer self.allocator.free(visited);
|
||||
|
||||
// find components with nonexistant or disconnected inputs
|
||||
var source_components = std.ArrayList(ComponentIndex).init(self.allocator);
|
||||
defer source_components.deinit();
|
||||
source: for (self.components.items) |component| {
|
||||
for (component.inputs.items) |input|
|
||||
if (input.connection != null)
|
||||
continue :source;
|
||||
|
||||
const idx = self.componentIndex(component).?;
|
||||
try process_order.append(component);
|
||||
visited[idx] = true;
|
||||
try source_components.append(idx);
|
||||
}
|
||||
|
||||
// do multiple Depth First Searches (with extra steps) once per source component
|
||||
for (source_components.items) |source_component_idx| {
|
||||
var stack = std.ArrayList(ComponentIndex).init(self.allocator);
|
||||
defer stack.deinit();
|
||||
|
||||
var component_idx = source_component_idx;
|
||||
|
||||
dfs: while (true) {
|
||||
visited[component_idx] = true;
|
||||
|
||||
// check each output of the current component
|
||||
for (self.components.items[component_idx].outputs.items) |output| {
|
||||
// check each connection of the current output
|
||||
for (output.connections.items) |connection| {
|
||||
std.debug.print("{}\n", .{connection});
|
||||
}
|
||||
}
|
||||
|
||||
// for (self.components.items[source_component_idx].outputs.items) |output| {
|
||||
// if (output.connection) |output_to| {
|
||||
// std.debug.print("checking output {?d}\n", .{self.componentIndex(output_to)});
|
||||
// for (output_to.inputs.items) |other_input| {
|
||||
// const other_idx = self.componentIndex(other_input.connection.?).?;
|
||||
// std.debug.print("other_idx is visited: {}\n", .{visited[other_idx]});
|
||||
// if (!visited[other_idx]) {
|
||||
// try process_order.append(self.components.items[other_idx]);
|
||||
// try stack.append(other_idx);
|
||||
// component_idx = other_idx;
|
||||
// std.debug.print("continue with {}\n", .{component_idx});
|
||||
// continue :dfs;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
component_idx = stack.pop() orelse break :dfs;
|
||||
std.debug.print("backtracking to {}\n", .{component_idx});
|
||||
}
|
||||
}
|
||||
|
||||
std.debug.print("{any}\n", .{visited});
|
||||
|
||||
if (self.process_order) |p| self.allocator.free(p);
|
||||
self.process_order = try process_order.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn componentIndex(self: *Circuit, component: *Component) ?ComponentIndex {
|
||||
const idx = std.mem.indexOfScalar(*Component, self.components.items, component);
|
||||
if (idx) |i|
|
||||
return @intCast(i)
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
const ProcessOrder = []*Component;
|
||||
const ProcessOrderSolver = struct {
|
||||
circuit: *Circuit,
|
||||
solved: []bool,
|
||||
// pub fn solve(self: *ProcessOrderSolver) ProcessOrder {
|
||||
// for (self.solved) |*s| s.* = false;
|
||||
// for (self.circuit.source_components.items) |source_component| {
|
||||
// var component = source_component;
|
||||
// while (true) {
|
||||
// // component.process();
|
||||
// // std.debug.print("source component {any}\n\n", .{source_component});
|
||||
// const idx = self.componentIndex(component);
|
||||
// self.solved[idx.?] = true;
|
||||
// std.debug.print("{}\n", .{component});
|
||||
// // std.debug.print("{any}\n", .{component.outputs.items});
|
||||
// _ = &component;
|
||||
// // component = component.outputs.items[0].connection.?;
|
||||
// next: for (component.outputs.items) |output| {
|
||||
// if (output.connection) |connection|
|
||||
// if (self.solved[self.componentIndex(connection).?] == false)
|
||||
// if (self.componentReady(connection)) {
|
||||
// component = connection;
|
||||
// } else {
|
||||
// continue :next;
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return &[_]*Component{};
|
||||
// }
|
||||
|
||||
pub fn init(circuit: *Circuit) !ProcessOrderSolver {
|
||||
return .{
|
||||
.circuit = circuit,
|
||||
.solved = try circuit.allocator.alloc(bool, circuit.components.items.len),
|
||||
};
|
||||
}
|
||||
// /// whether a component is ready to be solved
|
||||
// fn componentReady(self: ProcessOrderSolver, component: *Component) bool {
|
||||
// for (component.inputs.items) |input| {
|
||||
// if (input.connection) |c| {
|
||||
// if (self.solved[self.componentIndex(c).?])
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
pub fn deinit(self: *ProcessOrderSolver) void {
|
||||
self.circuit.allocator.free(self.solved);
|
||||
}
|
||||
|
||||
pub fn solve(self: *ProcessOrderSolver) ProcessOrder {
|
||||
for (self.circuit.source_components.items) |source_component| {
|
||||
var component = source_component;
|
||||
// while (true) blk: {
|
||||
// component.process();
|
||||
// std.debug.print("source component {any}\n\n", .{source_component});
|
||||
const idx = self.componentIndex(component);
|
||||
self.solved[idx.?] = true;
|
||||
std.debug.print("{}\n", .{component});
|
||||
std.debug.print("{any}\n", .{component.outputs.items});
|
||||
_ = &component;
|
||||
// component = component.outputs.items[0].connection.?;
|
||||
// }
|
||||
}
|
||||
return &[_]*Component{};
|
||||
}
|
||||
|
||||
fn componentIndex(self: ProcessOrderSolver, component: *Component) ?usize {
|
||||
// for (self.circuit.components.items, 0..) |c, i| {
|
||||
// // std.debug.print("{any} == {any}\n", .{ component, &c });
|
||||
// std.debug.print("{*} == {*}\n", .{ component, &c });
|
||||
// // std.debug.print("{s}\n{s}\n{any}\n\n", .{
|
||||
// // std.fmt.fmtSliceHexLower(std.mem.asBytes(component)),
|
||||
// // std.fmt.fmtSliceHexLower(std.mem.asBytes(&c)),
|
||||
// // std.mem.eql(u8, std.mem.asBytes(component), std.mem.asBytes(&c)),
|
||||
// // });
|
||||
// // if (std.mem.eql(u8, std.mem.asBytes(component), std.mem.asBytes(&c))) {
|
||||
// if (component == c) {
|
||||
// return i;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
return std.mem.indexOfScalar(*Component, self.circuit.components.items, component);
|
||||
}
|
||||
};
|
||||
// // TODO this is probably broken
|
||||
// fn componentIndex(self: ProcessOrderSolver, component: *Component) ?usize {
|
||||
// // for (self.circuit.components.items, 0..) |c, i| {
|
||||
// // // std.debug.print("{any} == {any}\n", .{ component, &c });
|
||||
// // std.debug.print("{*} == {*}\n", .{ component, &c });
|
||||
// // // std.debug.print("{s}\n{s}\n{any}\n\n", .{
|
||||
// // // std.fmt.fmtSliceHexLower(std.mem.asBytes(component)),
|
||||
// // // std.fmt.fmtSliceHexLower(std.mem.asBytes(&c)),
|
||||
// // // std.mem.eql(u8, std.mem.asBytes(component), std.mem.asBytes(&c)),
|
||||
// // // });
|
||||
// // // if (std.mem.eql(u8, std.mem.asBytes(component), std.mem.asBytes(&c))) {
|
||||
// // if (component == c) {
|
||||
// // return i;
|
||||
// // }
|
||||
// // }
|
||||
// // return null;
|
||||
// return std.mem.indexOfScalar(*Component, self.circuit.components.items, component);
|
||||
// }
|
||||
// };
|
||||
};
|
||||
|
||||
var null_signal = Signal{};
|
||||
|
@ -215,8 +302,13 @@ pub const Component = struct {
|
|||
};
|
||||
pub const Output = struct {
|
||||
signal: Signal = .{},
|
||||
connection: ?*Component = null,
|
||||
idx: usize = 0,
|
||||
connections: Connections = .empty,
|
||||
|
||||
pub const Connections = std.ArrayListUnmanaged(Connection);
|
||||
pub const Connection = struct {
|
||||
component: *Component,
|
||||
idx: usize,
|
||||
};
|
||||
};
|
||||
const Inputs = std.ArrayListUnmanaged(Input);
|
||||
const Outputs = std.ArrayListUnmanaged(Output);
|
||||
|
@ -249,6 +341,8 @@ pub const Component = struct {
|
|||
|
||||
pub fn deinit(self: *Component, allocator: std.mem.Allocator) void {
|
||||
self.inputs.deinit(allocator);
|
||||
for (self.outputs.items) |*output|
|
||||
output.connections.deinit(allocator);
|
||||
self.outputs.deinit(allocator);
|
||||
self.deinitFn(self, allocator);
|
||||
}
|
||||
|
@ -277,12 +371,17 @@ pub const Component = struct {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn connect(self: *Component, self_idx: usize, to: *Component, to_idx: usize) void {
|
||||
to.inputs.items[to_idx] = .{
|
||||
.signal = &self.outputs.items[self_idx].signal,
|
||||
.connection = self,
|
||||
.idx = self_idx,
|
||||
};
|
||||
fn connect(self: *Component, allocator: std.mem.Allocator, self_idx: usize, to: *Component, to_idx: usize) !void {
|
||||
const input = &to.inputs.items[to_idx];
|
||||
input.signal = &self.outputs.items[self_idx].signal;
|
||||
input.connection = self;
|
||||
input.idx = self_idx;
|
||||
|
||||
const output = &self.outputs.items[self_idx];
|
||||
try output.connections.append(allocator, .{
|
||||
.component = to,
|
||||
.idx = to_idx,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue