const std = @import("std"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); // const allocator = gpa.allocator(); // var input = Wire{ .digital = false, .analog = 1.0 }; // var input_buffer = Not{ .invert_output = false, .input = &input }; // // analog in // var wire1 = Wire{}; // var wire2 = Wire{}; // var wire3 = Wire{}; // // orange battery // var wire4 = Wire{}; // var wire5 = Wire{}; // var wire6 = Wire{}; // // cblueorange battery // var wire7 = Wire{}; // var wire8 = Wire{}; // var wire9 = Wire{}; // // red battery // var wire10 = Wire{}; // var wire11 = Wire{}; // // grey OR gates // var wire12 = Wire{}; // var wire13 = Wire{}; // var wire14 = Wire{}; // var wire15 = Wire{}; // // pink OR gates // var wire16 = Wire{}; // var wire17 = Wire{}; // var wire18 = Wire{}; // // right side flippity floppities // var wire19 = Wire{}; // var wire20 = Wire{}; // var wire21 = Wire{}; // var wire22 = Wire{}; // var wire23 = Wire{}; // var battery1 = Battery{ .value = -0.5 }; // var battery2 = Battery{ .value = 0.5 }; // var battery3 = Battery{ .value = -1.0 }; // var or1_inputs = [_]*Wire{ &wire1, &wire2, &wire3 }; // var or1 = Or{ .inputs = &or1_inputs }; // var or2_inputs = [_]*Wire{ &}; // var or2 = Or{ .inputs = &or2_inputs }; // var or3_inputs = [_]*Wire{}; // var or3 = Or{ .inputs = &or3_inputs }; // var or4_inputs = [_]*Wire{}; // var or4 = Or{ .inputs = &or4_inputs }; // var or5_inputs = [_]*Wire{}; // var or5 = Or{ .inputs = &or5_inputs }; // var or6_inputs = [_]*Wire{}; // var or6 = Or{ .inputs = &or6_inputs }; // var and1 = And{}; // var or7_inputs = [_]*Wire{}; // var or7 = Or{ .inputs = &or7_inputs }; // var and2 = And{}; // var or8_inputs = [_]*Wire{}; // var or8 = Or{ .inputs = &or8_inputs }; // std.debug.print("{}\n", .{wire3}); } pub const Component = struct { x: u16 = 0, y: u16 = 0, state: *anyopaque, processFn: *const fn (*Component) void, }; pub const Circuit = struct { width: u16 = 8, height: u16 = 8, components: std.ArrayList(Component), }; pub const Wire = struct { digital: bool = false, analog: f32 = 0.0, pub fn format(self: Wire, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { _ = .{ fmt, options }; try writer.print("Wire({s} | {d:0>1.4})", .{ if (self.digital) "1" else "0", self.analog, }); } fn analogSet(self: *Wire, value: f32) void { self.analog = std.math.clamp(value, 0.0, 1.0); } }; pub const Battery = struct { component: Component = .{}, output: *Wire, value: f32, invert_output: bool = false, pub fn process(self: *Battery) void { if (self.invert_output) { self.output.digital = self.value != 0.0; self.output.analogSet(self.value); } else { self.output.digital = self.value == 0.0; self.output.analogSet(1.0 - @abs(self.value)); } } }; pub const Not = struct { component: Component = .{}, input: *Wire, output: *Wire, invert_output: bool = true, pub fn process(self: *Not) void { if (self.invert_output) { self.output.digital = !self.input.digital; self.output.analogSet(1.0 - @abs(self.input.analog)); } else { self.output.digital = self.input.digital; self.output.analogSet(self.input.analog); // TODO does the output get clamped here? } } }; pub const And = struct { component: Component, inputs: []*Wire, output: *Wire, // if false, is in Minimum Input mode // if true, is in Multiply Inputs mode arithmetic_mode: bool = false, // TODO check implementation pub fn process(self: *And) void { if (self.arithmetic_mode) { self.output.digital = self.inputs[0].digital; self.output.analog = self.inputs[0].analog; for (self.inputs[1..]) |input| { self.output.digital = self.output.digital and input.digital; self.output.analog *= input.analog; } } else { self.output.digital = self.inputs[0].digital; self.output.analog = self.inputs[0].analog; for (self.inputs[1..]) |input| { self.output.digital = self.output.digital and input.digital; self.output.analog = @min(self.output.analog, input.analog); } } self.output.analog = std.math.clamp(self.output.analog, 0.0, 1.0); // var digital = self.inputs[0].digital; // if (digital) for (1..self.inputs.len - 1) |i| if (!self.inputs[i].digital) { // digital = false; // break; // }; // self.output.digital = digital; // var best = self.inputs[0].analog; // for (self.inputs[1..]) |input| best = @min(best, input.analog); // self.output.analog = best; } }; pub const Or = struct { component: Component, inputs: []*Wire, output: *Wire, // if false, is in Maximum Input mode // if true, is in Add Inputs mode arithmetic_mode: bool = false, // TODO check implementation pub fn process(self: *Or) void { if (self.arithmetic_mode) { self.output.digital = self.inputs[0].digital; self.output.analog = self.inputs[0].analog; for (self.inputs[1..]) |input| { self.output.digital = self.output.digital and input.digital; self.output.analog += input.analog; } } else { self.output.digital = self.inputs[0].digital; self.output.analog = self.inputs[0].analog; for (self.inputs[1..]) |input| { self.output.digital = self.output.digital and input.digital; self.output.analog = @max(self.output.analog, input.analog); } } self.output.analog = std.math.clamp(self.output.analog, 0.0, 1.0); // self.output.digital = 1; // for (self.inputs) |input| if (input.digital) { // self.output.digital = true; // break; // }; } };