littlebiglogicengine/src/main.zig

222 lines
6.3 KiB
Zig
Raw Normal View History

2025-02-11 07:55:25 -07:00
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
// const allocator = gpa.allocator();
2025-02-11 11:22:34 -07:00
// 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});
2025-02-11 07:55:25 -07:00
}
2025-02-11 11:22:34 -07:00
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),
};
2025-02-11 07:55:25 -07:00
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);
}
};
2025-02-11 11:22:34 -07:00
pub const Battery = struct {
component: Component = .{},
2025-02-11 07:55:25 -07:00
output: *Wire,
2025-02-11 11:22:34 -07:00
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));
}
2025-02-11 07:55:25 -07:00
}
};
pub const Not = struct {
2025-02-11 11:22:34 -07:00
component: Component = .{},
2025-02-11 07:55:25 -07:00
input: *Wire,
output: *Wire,
2025-02-11 11:22:34 -07:00
invert_output: bool = true,
2025-02-11 08:14:55 -07:00
pub fn process(self: *Not) void {
2025-02-11 11:22:34 -07:00
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?
}
2025-02-11 08:14:55 -07:00
}
};
pub const And = struct {
2025-02-11 11:22:34 -07:00
component: Component,
inputs: []*Wire,
2025-02-11 08:14:55 -07:00
output: *Wire,
2025-02-11 11:22:34 -07:00
// if false, is in Minimum Input mode
// if true, is in Multiply Inputs mode
arithmetic_mode: bool = false,
2025-02-11 07:55:25 -07:00
// TODO check implementation
2025-02-11 08:14:55 -07:00
pub fn process(self: *And) void {
2025-02-11 11:22:34 -07:00
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;
}
};
2025-02-11 08:14:55 -07:00
2025-02-11 11:22:34 -07:00
pub const Or = struct {
component: Component,
2025-02-11 08:14:55 -07:00
2025-02-11 11:22:34 -07:00
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;
// };
2025-02-11 07:55:25 -07:00
}
};