littlebiglogicengine/src/main.zig

222 lines
6.8 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 16:28:27 -07:00
var input = Signal{ .digital = 1, .analog = 0.5 };
var battery1 = Battery{ .value = -0.5 };
var battery2 = Battery{ .value = 0.5 };
var battery3 = Battery{ .value = -1.0 };
var or1_inputs = [_]*Signal{ &input, &input, undefined };
var or1 = Or{ .inputs = &or1_inputs, .arithmetic_mode = true };
var or2_inputs = [_]*Signal{ &or1.output, &or1.output, undefined };
var or2 = Or{ .inputs = &or2_inputs, .arithmetic_mode = true };
var or3_inputs = [_]*Signal{ &input, &battery1.output };
var or3 = Or{ .inputs = &or3_inputs };
var or4_inputs = [_]*Signal{ &or1.output, &battery1.output };
var or4 = Or{ .inputs = &or4_inputs };
var or5_inputs = [_]*Signal{ &or2.output, &battery1.output };
var or5 = Or{ .inputs = &or5_inputs };
var or6_inputs = [_]*Signal{ &battery2.output, &or3.output };
var or6 = Or{ .inputs = &or6_inputs, .arithmetic_mode = true };
var and1_inputs = [_]*Signal{ &battery3.output, &or6.output };
var and1 = And{ .inputs = &and1_inputs };
var or7_inputs = [_]*Signal{ &battery2.output, &or4.output };
var or7 = Or{ .inputs = &or7_inputs, .arithmetic_mode = true };
var and2_inputs = [_]*Signal{ &battery3.output, &or7.output };
var and2 = And{ .inputs = &and2_inputs };
var or8_inputs = [_]*Signal{ &battery2.output, &or5.output };
var or8 = Or{ .inputs = &or8_inputs, .arithmetic_mode = true };
or1_inputs[2] = &and1.output;
or2_inputs[2] = &and2.output;
battery1.process();
battery2.process();
battery3.process();
or3.process();
or6.process();
and1.process();
or1.process();
or4.process();
or7.process();
and2.process();
or2.process();
or5.process();
or8.process();
std.debug.print("{}\n{}\n{}\n{}\n", .{ input, or6.output, or7.output, or8.output });
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,
2025-02-11 13:46:37 -07:00
processFn: *const fn (*Component, []*Signal) []Signal,
};
pub const Signal = struct {
digital: i2 = 0,
analog: f32 = 0.0,
color: u24 = 0,
pub fn format(
self: Signal,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = .{ fmt, options };
try writer.writeAll("Signal(");
if (self.digital < 0) try writer.writeByte('-') else try writer.writeByte('+');
try writer.print("{d} / {d:0>1.4})", .{
@abs(self.digital),
self.analog,
});
}
2025-02-11 11:22:34 -07:00
};
pub const Circuit = struct {
width: u16 = 8,
height: u16 = 8,
components: std.ArrayList(Component),
2025-02-11 13:46:37 -07:00
pub fn init(allocator: std.mem.Allocator) Circuit {
return .{
.components = std.ArrayList(Component).init(allocator),
};
}
pub fn deinit(self: *Circuit) void {
self.components.deinit();
}
2025-02-11 11:22:34 -07:00
};
pub const Battery = struct {
2025-02-11 16:28:27 -07:00
// component: Component = .{ .processFn = process },
2025-02-11 13:07:08 -07:00
value: f32,
2025-02-11 16:28:27 -07:00
output: Signal = .{},
pub fn process(self: *Battery) void {
// const self: *Battery = @fieldParentPtr("component", component);
// return &[_]Signal{.{
// .digital = std.math.sign(self.value),
// .analog = self.value,
// }};
self.output.digital = @intFromFloat(std.math.sign(self.value));
self.output.analog = self.value;
2025-02-11 13:07:08 -07:00
}
2025-02-11 08:14:55 -07:00
};
2025-02-11 11:43:39 -07:00
// 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));
// }
// }
// };
2025-02-11 13:46:37 -07:00
pub const Not = struct {
// component: Component = .{},
2025-02-11 11:43:39 -07:00
2025-02-11 13:46:37 -07:00
input: *Signal,
output: Signal = .{},
2025-02-11 11:43:39 -07:00
2025-02-11 13:46:37 -07:00
invert_output: bool = true,
2025-02-11 11:43:39 -07:00
2025-02-11 13:46:37 -07:00
pub fn process(self: *Not) void {
if (self.invert_output) {
2025-02-11 16:28:27 -07:00
self.output.digital = 1 - @as(i2, @intCast(@abs(self.input.digital)));
2025-02-11 13:46:37 -07:00
self.output.analog = 1.0 - @abs(self.input.analog);
} else {
self.output.digital = self.input.digital;
self.output.analog = self.input.analog;
}
self.output.analog = std.math.clamp(self.output.analog, 0.0, 1.0);
}
};
2025-02-11 11:43:39 -07:00
2025-02-11 16:28:27 -07:00
pub const And = struct {
// component: Component,
2025-02-11 11:43:39 -07:00
2025-02-11 16:28:27 -07:00
inputs: []*Signal,
output: Signal = .{},
2025-02-11 11:43:39 -07:00
2025-02-11 16:28:27 -07:00
// 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.digital = 0;
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.digital = 0;
self.output.analog = @min(self.output.analog, input.analog);
}
}
self.output.analog = std.math.clamp(self.output.analog, 0.0, 1.0);
}
};
2025-02-11 11:43:39 -07:00
2025-02-11 16:28:27 -07:00
pub const Or = struct {
// component: Component,
2025-02-11 11:43:39 -07:00
2025-02-11 16:28:27 -07:00
inputs: []*Signal,
output: Signal = .{},
2025-02-11 11:43:39 -07:00
2025-02-11 16:28:27 -07:00
// 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.digital = 0;
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.digital = 0;
self.output.analog = @max(self.output.analog, input.analog);
}
}
self.output.analog = std.math.clamp(self.output.analog, 0.0, 1.0);
}
};