Make circuit rely on database
parent
3036ccd1e8
commit
d3450e4323
|
@ -4246,9 +4246,9 @@
|
||||||
"defUid": 93,
|
"defUid": 93,
|
||||||
"px": [84,124],
|
"px": [84,124],
|
||||||
"fieldInstances": [
|
"fieldInstances": [
|
||||||
{ "__identifier": "Point", "__value": [{ "cx": 15, "cy": 15 }], "__type": "Array<Point>", "__tile": null, "defUid": 94, "realEditorValues": [{
|
{ "__identifier": "Point", "__value": [{ "cx": 14, "cy": 15 }], "__type": "Array<Point>", "__tile": null, "defUid": 94, "realEditorValues": [{
|
||||||
"id": "V_String",
|
"id": "V_String",
|
||||||
"params": ["15,15"]
|
"params": ["14,15"]
|
||||||
}] },
|
}] },
|
||||||
{ "__identifier": "Anchor", "__value": [ true, true ], "__type": "Array<Bool>", "__tile": null, "defUid": 98, "realEditorValues": [ {
|
{ "__identifier": "Anchor", "__value": [ true, true ], "__type": "Array<Bool>", "__tile": null, "defUid": 98, "realEditorValues": [ {
|
||||||
"id": "V_Bool",
|
"id": "V_Bool",
|
||||||
|
@ -4330,12 +4330,13 @@
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,0,
|
0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,0,
|
||||||
0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,
|
0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,
|
||||||
0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,1,1,1,7,10,0,1,0,0,
|
0,0,0,1,0,0,1,0,0,1,0,0,1,0,9,0,1,0,0,0,0,0,0,1,0,0,1,1,1,7,10,0,1,0,2,
|
||||||
2,1,0,0,0,0,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,
|
0,1,0,0,0,0,0,0,1,0,0,4,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,1,1,
|
||||||
1,1,1,0,0,0,1,0,0,0,0,0,0,8,0,0,9,0,8,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,
|
1,1,1,0,0,0,1,0,0,0,0,0,0,8,0,0,9,0,8,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,
|
||||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
],
|
],
|
||||||
"autoLayerTiles": [
|
"autoLayerTiles": [
|
||||||
|
{ "px": [112,112], "src": [64,48], "f": 0, "t": 104, "d": [106,294] },
|
||||||
{ "px": [48,144], "src": [8,48], "f": 0, "t": 97, "d": [104,366] },
|
{ "px": [48,144], "src": [8,48], "f": 0, "t": 97, "d": [104,366] },
|
||||||
{ "px": [24,88], "src": [96,48], "f": 0, "t": 108, "d": [35,223] },
|
{ "px": [24,88], "src": [96,48], "f": 0, "t": 108, "d": [35,223] },
|
||||||
{ "px": [72,104], "src": [96,48], "f": 0, "t": 108, "d": [35,269] },
|
{ "px": [72,104], "src": [96,48], "f": 0, "t": 108, "d": [35,269] },
|
||||||
|
@ -4345,7 +4346,6 @@
|
||||||
{ "px": [96,136], "src": [24,48], "f": 0, "t": 99, "d": [37,352] },
|
{ "px": [96,136], "src": [24,48], "f": 0, "t": 99, "d": [37,352] },
|
||||||
{ "px": [48,120], "src": [104,48], "f": 0, "t": 109, "d": [40,306] },
|
{ "px": [48,120], "src": [104,48], "f": 0, "t": 109, "d": [40,306] },
|
||||||
{ "px": [48,88], "src": [112,48], "f": 0, "t": 110, "d": [41,226] },
|
{ "px": [48,88], "src": [112,48], "f": 0, "t": 110, "d": [41,226] },
|
||||||
{ "px": [128,120], "src": [88,48], "f": 0, "t": 107, "d": [43,316] },
|
|
||||||
{ "px": [32,88], "src": [48,48], "f": 0, "t": 102, "d": [44,224] },
|
{ "px": [32,88], "src": [48,48], "f": 0, "t": 102, "d": [44,224] },
|
||||||
{ "px": [40,88], "src": [48,48], "f": 0, "t": 102, "d": [44,225] },
|
{ "px": [40,88], "src": [48,48], "f": 0, "t": 102, "d": [44,225] },
|
||||||
{ "px": [56,88], "src": [48,48], "f": 0, "t": 102, "d": [44,227] },
|
{ "px": [56,88], "src": [48,48], "f": 0, "t": 102, "d": [44,227] },
|
||||||
|
@ -4377,6 +4377,7 @@
|
||||||
{ "px": [128,112], "src": [72,48], "f": 0, "t": 105, "d": [45,296] },
|
{ "px": [128,112], "src": [72,48], "f": 0, "t": 105, "d": [45,296] },
|
||||||
{ "px": [24,120], "src": [72,48], "f": 0, "t": 105, "d": [45,303] },
|
{ "px": [24,120], "src": [72,48], "f": 0, "t": 105, "d": [45,303] },
|
||||||
{ "px": [96,120], "src": [72,48], "f": 0, "t": 105, "d": [45,312] },
|
{ "px": [96,120], "src": [72,48], "f": 0, "t": 105, "d": [45,312] },
|
||||||
|
{ "px": [128,120], "src": [72,48], "f": 0, "t": 105, "d": [45,316] },
|
||||||
{ "px": [24,128], "src": [72,48], "f": 0, "t": 105, "d": [45,323] },
|
{ "px": [24,128], "src": [72,48], "f": 0, "t": 105, "d": [45,323] },
|
||||||
{ "px": [96,128], "src": [72,48], "f": 0, "t": 105, "d": [45,332] },
|
{ "px": [96,128], "src": [72,48], "f": 0, "t": 105, "d": [45,332] },
|
||||||
{ "px": [128,128], "src": [72,48], "f": 0, "t": 105, "d": [45,336] },
|
{ "px": [128,128], "src": [72,48], "f": 0, "t": 105, "d": [45,336] },
|
||||||
|
@ -4384,7 +4385,7 @@
|
||||||
{ "px": [48,136], "src": [72,48], "f": 0, "t": 105, "d": [45,346] },
|
{ "px": [48,136], "src": [72,48], "f": 0, "t": 105, "d": [45,346] },
|
||||||
{ "px": [128,136], "src": [72,48], "f": 0, "t": 105, "d": [45,356] },
|
{ "px": [128,136], "src": [72,48], "f": 0, "t": 105, "d": [45,356] },
|
||||||
{ "px": [80,120], "src": [8,8], "f": 0, "t": 17, "d": [130,310] },
|
{ "px": [80,120], "src": [8,8], "f": 0, "t": 17, "d": [130,310] },
|
||||||
{ "px": [120,120], "src": [16,8], "f": 0, "t": 18, "d": [59,315] },
|
{ "px": [112,120], "src": [0,8], "f": 0, "t": 16, "d": [57,314] },
|
||||||
{ "px": [48,128], "src": [104,8], "f": 0, "t": 29, "d": [79,326] },
|
{ "px": [48,128], "src": [104,8], "f": 0, "t": 29, "d": [79,326] },
|
||||||
{ "px": [72,120], "src": [48,8], "f": 0, "t": 22, "d": [83,309] }
|
{ "px": [72,120], "src": [48,8], "f": 0, "t": 22, "d": [83,309] }
|
||||||
],
|
],
|
||||||
|
|
196
src/circuit.zig
196
src/circuit.zig
|
@ -139,15 +139,15 @@ fn get_plugs(tile: u8) Plugs {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cell(this: @This(), cell: Cell) ?u8 {
|
pub fn getCoord(this: @This(), coord: world.Coordinate) ?u8 {
|
||||||
const i = this.indexOf(cell) orelse return null;
|
const i = this.indexOf(coord.toVec2()) orelse return null;
|
||||||
return if (this.map[i] != 0) this.map[i] else null;
|
return if (this.map[i] != 0) this.map[i] else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_cell(this: *@This(), cell: Cell, tile: u8) void {
|
pub fn setCoord(this: @This(), coord: world.Coordinate, tile: u8) void {
|
||||||
const i = this.indexOf(cell) orelse return;
|
const i = this.indexOf(coord.toVec2()) orelse return;
|
||||||
this.map[i] = tile;
|
this.map[i] = tile;
|
||||||
this.levels[i] = 0;
|
// this.levels[i] = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAXCELLS = 400;
|
const MAXCELLS = 400;
|
||||||
|
@ -156,37 +156,37 @@ const MAXSOURCES = 10;
|
||||||
const MAXDOORS = 40;
|
const MAXDOORS = 40;
|
||||||
const MAXLOGIC = 40;
|
const MAXLOGIC = 40;
|
||||||
|
|
||||||
pub const CellData = struct { level: u8 = 0, tile: u8 };
|
pub const NodeCoord = struct { coord: world.Coordinate, node_id: world.NodeID };
|
||||||
|
pub const Source = NodeCoord;
|
||||||
pub const BridgeState = struct { cells: [2]Cell, id: usize, enabled: bool };
|
pub const BridgeState = struct { coords: [2]world.Coordinate, id: usize, enabled: bool };
|
||||||
pub const DoorState = struct { cell: Cell, enabled: bool };
|
pub const DoorState = struct { coord: world.Coordinate, enabled: bool };
|
||||||
|
|
||||||
/// Tile id of the tiles
|
/// Tile id of the tiles
|
||||||
map: []u8,
|
map: []u8,
|
||||||
/// Logic levels of the tiles
|
/// CircuitNode ID for each tile
|
||||||
levels: []u8,
|
nodes: []world.NodeID,
|
||||||
map_size: Vec2,
|
map_size: Vec2,
|
||||||
bridges: util.Buffer(BridgeState),
|
bridges: util.Buffer(BridgeState),
|
||||||
sources: util.Buffer(Cell),
|
sources: util.Buffer(Source),
|
||||||
doors: util.Buffer(DoorState),
|
doors: util.Buffer(DoorState),
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
map: []u8,
|
map: []u8,
|
||||||
levels: []u8,
|
nodes: []u8,
|
||||||
map_size: Vec2,
|
map_size: Vec2,
|
||||||
bridges: []BridgeState,
|
bridges: []BridgeState,
|
||||||
sources: []Cell,
|
sources: []Source,
|
||||||
doors: []DoorState,
|
doors: []DoorState,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(opt: Options) @This() {
|
pub fn init(opt: Options) @This() {
|
||||||
std.debug.assert(opt.map.len == opt.levels.len);
|
std.debug.assert(opt.map.len == opt.nodes.len);
|
||||||
var this = @This(){
|
var this = @This(){
|
||||||
.map = opt.map,
|
.map = opt.map,
|
||||||
.levels = opt.levels,
|
.nodes = opt.nodes,
|
||||||
.map_size = opt.map_size,
|
.map_size = opt.map_size,
|
||||||
.bridges = util.Buffer(BridgeState).init(opt.bridges),
|
.bridges = util.Buffer(BridgeState).init(opt.bridges),
|
||||||
.sources = util.Buffer(Cell).init(opt.sources),
|
.sources = util.Buffer(Source).init(opt.sources),
|
||||||
.doors = util.Buffer(DoorState).init(opt.doors),
|
.doors = util.Buffer(DoorState).init(opt.doors),
|
||||||
};
|
};
|
||||||
return this;
|
return this;
|
||||||
|
@ -197,31 +197,40 @@ pub fn indexOf(this: @This(), cell: Cell) ?usize {
|
||||||
return @intCast(usize, @mod(cell[0], this.map_size[0]) + (cell[1] * this.map_size[1]));
|
return @intCast(usize, @mod(cell[0], this.map_size[0]) + (cell[1] * this.map_size[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable(this: *@This(), cell: Cell) void {
|
pub fn bridge(this: *@This(), coords: [2]world.Coordinate, bridgeID: usize) void {
|
||||||
const i = this.indexOf(cell) orelse return;
|
if (this.indexOf(coords[0].toVec2())) |_| {
|
||||||
this.levels[i] += 1;
|
if (this.indexOf(coords[1].toVec2())) |_| {
|
||||||
}
|
this.bridges.append(.{ .coords = coords, .id = bridgeID, .enabled = false });
|
||||||
|
|
||||||
pub fn bridge(this: *@This(), cells: [2]Cell, bridgeID: usize) void {
|
|
||||||
if (this.indexOf(cells[0])) |_| {
|
|
||||||
if (this.indexOf(cells[1])) |_| {
|
|
||||||
this.bridges.append(.{ .cells = cells, .id = bridgeID, .enabled = false });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addSource(this: *@This(), cell: Cell) void {
|
pub fn addSource(this: *@This(), source: Source) void {
|
||||||
if (this.indexOf(cell)) |_| {
|
w4.tracef("%d, %d", source.coord.val[0], source.coord.val[1]);
|
||||||
this.sources.append(cell);
|
if (this.indexOf(source.coord.toVec2())) |_| {
|
||||||
|
this.sources.append(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addDoor(this: *@This(), cell: Cell) !void {
|
pub fn addDoor(this: *@This(), coord: world.Coordinate) !void {
|
||||||
if (this.indexOf(cell)) |_| {
|
if (this.indexOf(coord.toVec2())) |_| {
|
||||||
this.doors.append(.{ .cell = cell, .enabled = false });
|
this.doors.append(.{ .coord = coord, .enabled = false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enabledBridge(this: @This(), id: usize) ?usize {
|
||||||
|
var count: usize = 0;
|
||||||
|
for (this.bridges.items) |b| {
|
||||||
|
if (b.enabled) {
|
||||||
|
if (count == id) {
|
||||||
|
return b.id;
|
||||||
|
}
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enabledBridges(this: @This(), alloc: std.mem.Allocator) !util.Buffer(usize) {
|
pub fn enabledBridges(this: @This(), alloc: std.mem.Allocator) !util.Buffer(usize) {
|
||||||
var items = try alloc.alloc(usize, this.bridges.len);
|
var items = try alloc.alloc(usize, this.bridges.len);
|
||||||
var buffer = util.Buffer(usize).init(items);
|
var buffer = util.Buffer(usize).init(items);
|
||||||
|
@ -243,28 +252,28 @@ pub fn enabledDoors(this: @This(), alloc: std.mem.Allocator) !util.Buffer(Cell)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isEnabled(this: @This(), cell: Cell) bool {
|
pub fn getNodeID(this: @This(), coord: world.Coordinate) ?world.NodeID {
|
||||||
const i = this.indexOf(cell) orelse return false;
|
const i = this.indexOf(coord.toVec2()) orelse return null;
|
||||||
return this.levels[i] >= 1;
|
if (this.nodes[i] == std.math.maxInt(world.NodeID)) return null;
|
||||||
|
return this.nodes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn switchOn(this: *@This(), cell: Cell) void {
|
pub fn switchOn(this: *@This(), coord: world.Coordinate) void {
|
||||||
if (this.get_cell(cell)) |tile| {
|
if (this.getCoord(coord)) |tile| {
|
||||||
if (T.is_switch(tile)) {
|
if (T.is_switch(tile)) {
|
||||||
if (switchIsOn(tile)) return;
|
if (switchIsOn(tile)) return;
|
||||||
const toggled = toggle_switch(tile);
|
const toggled = toggle_switch(tile);
|
||||||
this.set_cell(cell, toggled);
|
this.setCoord(coord, toggled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle(this: *@This(), c: Cell) ?u8 {
|
pub fn toggle(this: *@This(), coord: world.Coordinate) ?u8 {
|
||||||
const cell = c;
|
if (this.getCoord(coord)) |tile| {
|
||||||
if (this.get_cell(cell)) |tile| {
|
|
||||||
if (T.is_switch(tile)) {
|
if (T.is_switch(tile)) {
|
||||||
const toggled = toggle_switch(tile);
|
const toggled = toggle_switch(tile);
|
||||||
this.set_cell(cell, toggled);
|
this.setCoord(coord, toggled);
|
||||||
return toggled;
|
return toggled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +289,7 @@ pub fn clearMap(this: *@This()) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(this: *@This()) void {
|
pub fn clear(this: *@This()) void {
|
||||||
std.mem.set(u8, this.levels, 0);
|
std.mem.set(u8, this.nodes, std.math.maxInt(world.NodeID));
|
||||||
for (this.doors.items) |*door| {
|
for (this.doors.items) |*door| {
|
||||||
door.enabled = false;
|
door.enabled = false;
|
||||||
}
|
}
|
||||||
|
@ -294,70 +303,87 @@ pub fn reset(this: *@This()) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const w4 = @import("wasm4.zig");
|
const w4 = @import("wasm4.zig");
|
||||||
const Queue = util.Queue(Cell);
|
|
||||||
// Returns number of cells filled
|
// Returns number of cells filled
|
||||||
pub fn fill(this: *@This(), alloc: std.mem.Allocator) !usize {
|
pub fn fill(this: *@This(), alloc: std.mem.Allocator, db: world.Database, level: world.Level) !usize {
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
|
w4.tracef("[fill] begin");
|
||||||
|
|
||||||
var q_buf = try alloc.alloc(Cell, MAXCELLS);
|
const Queue = util.Queue(NodeCoord);
|
||||||
|
var q_buf = try alloc.alloc(NodeCoord, MAXCELLS);
|
||||||
var q = Queue.init(q_buf);
|
var q = Queue.init(q_buf);
|
||||||
|
|
||||||
for (this.sources.items) |source| {
|
for (this.sources.items) |source| {
|
||||||
|
w4.tracef("[fill] inserting source (%d, %d)", source.coord.val[0], source.coord.val[1]);
|
||||||
try q.insert(source);
|
try q.insert(source);
|
||||||
}
|
}
|
||||||
|
// if (this.sources.items.len == 0) {
|
||||||
|
// w4.tracef("[fill] no sources %d", this.sources.items.len);
|
||||||
|
// }
|
||||||
|
|
||||||
while (q.remove()) |cell| {
|
while (q.remove()) |node| {
|
||||||
const tile = this.get_cell(cell) orelse {
|
const tile = this.getCoord(node.coord) orelse continue;
|
||||||
for (this.doors.items) |*d| {
|
const index = this.indexOf(node.coord.toVec2()) orelse continue;
|
||||||
if (@reduce(.And, d.cell == cell)) {
|
const hasVisited = this.nodes[index] != std.math.maxInt(world.NodeID);
|
||||||
d.enabled = true;
|
|
||||||
}
|
w4.tracef("[fill] %d, %d, %d", tile, index, hasVisited);
|
||||||
}
|
if (hasVisited) continue;
|
||||||
|
|
||||||
|
this.nodes[index] = node.node_id;
|
||||||
|
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
if (get_logic(tile)) |_| {
|
||||||
|
// w4.tracef("[fill] logic");
|
||||||
|
const new_id = db.getLevelNodeID(level, node.coord) orelse {
|
||||||
|
w4.tracef("[fill] missing logic");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
const index = this.indexOf(cell) orelse continue;
|
try q.insert(.{ .node_id = new_id, .coord = node.coord.add(.{ 0, -1 }) });
|
||||||
const hasVisited = this.levels[index] != 0;
|
continue;
|
||||||
this.enable(cell);
|
|
||||||
if (hasVisited and !T.is_logic(tile)) continue;
|
|
||||||
count += 1;
|
|
||||||
if (get_logic(tile)) |logic| {
|
|
||||||
// TODO: implement other logic (though I'm pretty sure that requires a graph...)
|
|
||||||
if (logic != .And) continue;
|
|
||||||
if (this.levels[index] < 2) continue;
|
|
||||||
try q.insert(cell + util.Dir.up);
|
|
||||||
}
|
}
|
||||||
for (get_outputs(tile)) |conductor, i| {
|
for (get_outputs(tile)) |conductor, i| {
|
||||||
|
// w4.tracef("[fill] outputs");
|
||||||
if (!conductor) continue;
|
if (!conductor) continue;
|
||||||
|
// w4.tracef("[fill] conductor");
|
||||||
const s = @intToEnum(Side, i);
|
const s = @intToEnum(Side, i);
|
||||||
const delta = s.dir();
|
const delta = s.dir();
|
||||||
// TODO: check that cell can recieve from this side
|
// TODO: check that cell can recieve from this side
|
||||||
const nextCell = cell + delta;
|
const nextCoord = node.coord.addC(world.Coordinate.fromVec2(delta));
|
||||||
if (nextCell[0] < 0 or nextCell[1] < 0 or
|
const tl = world.Coordinate.init(.{ 0, 0 });
|
||||||
nextCell[0] >= this.map_size[0] or
|
const br = world.Coordinate.fromVec2(this.map_size);
|
||||||
nextCell[1] >= this.map_size[1])
|
// w4.tracef("[fill] next (%d, %d)", nextCoord.val[0], nextCoord.val[1]);
|
||||||
continue;
|
// w4.tracef("[fill] range (%d, %d)-(%d, %d)", tl.val[0], tl.val[1], br.val[0], br.val[1]);
|
||||||
const nextTile = this.get_cell(nextCell) orelse here: {
|
if (!nextCoord.within(tl, br)) continue;
|
||||||
for (this.doors.items) |*d| {
|
// w4.tracef("[fill] within %d", nextCoord.within(tl, br));
|
||||||
if (@reduce(.And, d.cell == nextCell)) {
|
const nextTile = this.getCoord(nextCoord) orelse 0;
|
||||||
d.enabled = true;
|
// w4.tracef("[fill] nextTile");
|
||||||
|
if (get_inputs(nextTile)[@enumToInt(s.opposite())]) {
|
||||||
|
// w4.tracef("[fill] get_inputs");
|
||||||
|
try q.insert(.{
|
||||||
|
.node_id = node.node_id,
|
||||||
|
.coord = nextCoord,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break :here 0;
|
|
||||||
};
|
|
||||||
if (get_inputs(nextTile)[@enumToInt(s.opposite())])
|
|
||||||
try q.insert(nextCell);
|
|
||||||
}
|
|
||||||
if (T.is_plug(tile)) {
|
if (T.is_plug(tile)) {
|
||||||
|
// w4.tracef("[fill] plug");
|
||||||
for (this.bridges.items) |*b| {
|
for (this.bridges.items) |*b| {
|
||||||
if (@reduce(.And, b.cells[0] == cell)) {
|
if (b.coords[0].eq(node.coord)) {
|
||||||
try q.insert(b.cells[1]);
|
try q.insert(.{
|
||||||
|
.coord = b.coords[1],
|
||||||
|
.node_id = node.node_id,
|
||||||
|
});
|
||||||
b.enabled = true;
|
b.enabled = true;
|
||||||
} else if (@reduce(.And, b.cells[1] == cell)) {
|
} else if (b.coords[1].eq(node.coord)) {
|
||||||
try q.insert(b.cells[0]);
|
try q.insert(.{
|
||||||
|
.coord = b.coords[0],
|
||||||
|
.node_id = node.node_id,
|
||||||
|
});
|
||||||
b.enabled = true;
|
b.enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
w4.tracef("[fill] end search step");
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -369,16 +395,18 @@ const tilemap_width = 16;
|
||||||
const tilemap_height = 16;
|
const tilemap_height = 16;
|
||||||
const tilemap_stride = 128;
|
const tilemap_stride = 128;
|
||||||
|
|
||||||
pub fn draw(this: @This(), offset: Vec2) void {
|
pub fn draw(this: @This(), db: world.Database, offset: Vec2) void {
|
||||||
var y: usize = 0;
|
var y: usize = 0;
|
||||||
while (y < height) : (y += 1) {
|
while (y < height) : (y += 1) {
|
||||||
var x: usize = 0;
|
var x: usize = 0;
|
||||||
while (x < width) : (x += 1) {
|
while (x < width) : (x += 1) {
|
||||||
const cell = Vec2{ @intCast(i32, x), @intCast(i32, y) };
|
const cell = Vec2{ @intCast(i32, x), @intCast(i32, y) };
|
||||||
const pos = cell * tile_size;
|
const pos = cell * tile_size;
|
||||||
const tile = this.get_cell(cell + offset) orelse continue;
|
const coord = world.Coordinate.fromVec2(cell + offset);
|
||||||
|
const tile = this.getCoord(coord) orelse continue;
|
||||||
if (tile == 0) continue;
|
if (tile == 0) continue;
|
||||||
if (this.isEnabled(cell + offset)) w4.DRAW_COLORS.* = 0x0210 else w4.DRAW_COLORS.* = 0x0310;
|
const energized = if (this.getNodeID(coord)) |node| db.circuit_info[node].energized else false;
|
||||||
|
if (energized) w4.DRAW_COLORS.* = 0x0210 else w4.DRAW_COLORS.* = 0x0310;
|
||||||
const t = Vec2{
|
const t = Vec2{
|
||||||
@intCast(i32, (tile % tilemap_width) * tile_size[0]),
|
@intCast(i32, (tile % tilemap_width) * tile_size[0]),
|
||||||
@intCast(i32, (tile / tilemap_width) * tile_size[0]),
|
@intCast(i32, (tile / tilemap_width) * tile_size[0]),
|
||||||
|
|
|
@ -18,6 +18,7 @@ pub const Options = struct {
|
||||||
plug: world.AutoTileset,
|
plug: world.AutoTileset,
|
||||||
switch_on: world.AutoTileset,
|
switch_on: world.AutoTileset,
|
||||||
switch_off: world.AutoTileset,
|
switch_off: world.AutoTileset,
|
||||||
|
db: world.Database,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn is_solid(tile: u7) bool {
|
fn is_solid(tile: u7) bool {
|
||||||
|
@ -32,6 +33,7 @@ pub fn extractLevel(opt: Options) !void {
|
||||||
const alloc = opt.alloc;
|
const alloc = opt.alloc;
|
||||||
const level = opt.level;
|
const level = opt.level;
|
||||||
const tileset = opt.tileset;
|
const tileset = opt.tileset;
|
||||||
|
const db = opt.db;
|
||||||
|
|
||||||
const tiles = level.tiles orelse return error.NullTiles;
|
const tiles = level.tiles orelse return error.NullTiles;
|
||||||
|
|
||||||
|
@ -138,7 +140,18 @@ pub fn extractLevel(opt: Options) !void {
|
||||||
const y = @divTrunc(i, width);
|
const y = @divTrunc(i, width);
|
||||||
const stride = width;
|
const stride = width;
|
||||||
|
|
||||||
if (circuit_map[i] == .Source) circuit.addSource(.{@intCast(i32, x), @intCast(i32, y)});
|
if (circuit_map[i] == .Source) {
|
||||||
|
const levelc = world.Coordinate.fromVec2(.{ @intCast(i32, x), @intCast(i32, y) });
|
||||||
|
const coord = world.Coordinate.fromWorld(level.world_x, level.world_y).addC(levelc);
|
||||||
|
w4.tracef("[extract] source (%d, %d)", coord.val[0], coord.val[1]);
|
||||||
|
if (db.getNodeID(coord)) |node_id| {
|
||||||
|
circuit.addSource(.{
|
||||||
|
.coord = levelc,
|
||||||
|
.node_id = node_id,
|
||||||
|
});
|
||||||
|
w4.tracef("[extract] node id (%d)", node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (circuit_map[i] == .None) {
|
if (circuit_map[i] == .None) {
|
||||||
autotiles[i] = null;
|
autotiles[i] = null;
|
||||||
|
|
99
src/game.zig
99
src/game.zig
|
@ -178,7 +178,7 @@ var ScoreCoin = Sprite{
|
||||||
|
|
||||||
var map_buf: [400]u8 = undefined;
|
var map_buf: [400]u8 = undefined;
|
||||||
|
|
||||||
var circuit_lvl_buf: [400]u8 = undefined;
|
var circuit_node_buf: [400]u8 = undefined;
|
||||||
var circuit_buf: [400]u8 = undefined;
|
var circuit_buf: [400]u8 = undefined;
|
||||||
|
|
||||||
var circuit_options: Circuit.Options = undefined;
|
var circuit_options: Circuit.Options = undefined;
|
||||||
|
@ -209,6 +209,8 @@ fn loadLevel(lvl: usize) !void {
|
||||||
level = try db.levelLoad(alloc, lvl);
|
level = try db.levelLoad(alloc, lvl);
|
||||||
const levelc = world.Coordinate.fromWorld(level.world_x, level.world_y);
|
const levelc = world.Coordinate.fromWorld(level.world_x, level.world_y);
|
||||||
|
|
||||||
|
w4.tracef("Loading level [%d] (%d, %d)", lvl, level.world_x, level.world_y);
|
||||||
|
|
||||||
try extract.extractLevel(.{
|
try extract.extractLevel(.{
|
||||||
.alloc = frame_alloc,
|
.alloc = frame_alloc,
|
||||||
.level = level,
|
.level = level,
|
||||||
|
@ -219,6 +221,7 @@ fn loadLevel(lvl: usize) !void {
|
||||||
.plug = world.Tiles.Plugs,
|
.plug = world.Tiles.Plugs,
|
||||||
.switch_off = world.Tiles.SwitchesOff,
|
.switch_off = world.Tiles.SwitchesOff,
|
||||||
.switch_on = world.Tiles.SwitchesOn,
|
.switch_on = world.Tiles.SwitchesOn,
|
||||||
|
.db = db,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tile_size = Vec2{ 8, 8 };
|
const tile_size = Vec2{ 8, 8 };
|
||||||
|
@ -258,7 +261,7 @@ fn loadLevel(lvl: usize) !void {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (db.getDoor(level, i)) |door| : (i += 1) {
|
while (db.getDoor(level, i)) |door| : (i += 1) {
|
||||||
const coord = door.coord.subC(levelc);
|
const coord = door.coord.subC(levelc);
|
||||||
try circuit.addDoor(coord.toVec2());
|
try circuit.addDoor(coord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +272,8 @@ fn loadLevel(lvl: usize) !void {
|
||||||
var e = false;
|
var e = false;
|
||||||
if (db.isEnergized(globalc)) {
|
if (db.isEnergized(globalc)) {
|
||||||
e = true;
|
e = true;
|
||||||
circuit.addSource(.{ join.val[0], join.val[1] });
|
const node_id = db.getNodeID(globalc) orelse continue;
|
||||||
|
circuit.addSource(.{ .coord = join, .node_id = node_id });
|
||||||
}
|
}
|
||||||
w4.tracef("---- Join %d: (%d, %d) <%d>", i, globalc.val[0], globalc.val[1], @boolToInt(e));
|
w4.tracef("---- Join %d: (%d, %d) <%d>", i, globalc.val[0], globalc.val[1], @boolToInt(e));
|
||||||
}
|
}
|
||||||
|
@ -282,7 +286,7 @@ fn loadLevel(lvl: usize) !void {
|
||||||
var e = false;
|
var e = false;
|
||||||
if (db.getSwitchState(globalc)) |state| {
|
if (db.getSwitchState(globalc)) |state| {
|
||||||
e = true;
|
e = true;
|
||||||
if (state != 0) circuit.switchOn(.{ _switch.val[0], _switch.val[1] });
|
if (state != 0) circuit.switchOn(levelc);
|
||||||
}
|
}
|
||||||
w4.tracef("---- Switch %d: (%d, %d) <%d>", i, globalc.val[0], globalc.val[1], @boolToInt(e));
|
w4.tracef("---- Switch %d: (%d, %d) <%d>", i, globalc.val[0], globalc.val[1], @boolToInt(e));
|
||||||
}
|
}
|
||||||
|
@ -378,10 +382,10 @@ pub fn start() !void {
|
||||||
|
|
||||||
circuit_options = .{
|
circuit_options = .{
|
||||||
.map = &circuit_buf,
|
.map = &circuit_buf,
|
||||||
.levels = &circuit_lvl_buf,
|
.nodes = &circuit_node_buf,
|
||||||
.map_size = level_size,
|
.map_size = level_size,
|
||||||
.bridges = try alloc.alloc(Circuit.BridgeState, 5),
|
.bridges = try alloc.alloc(Circuit.BridgeState, 5),
|
||||||
.sources = try alloc.alloc(util.Cell, 5),
|
.sources = try alloc.alloc(Circuit.Source, 5),
|
||||||
.doors = try alloc.alloc(Circuit.DoorState, 10),
|
.doors = try alloc.alloc(Circuit.DoorState, 10),
|
||||||
};
|
};
|
||||||
circuit = Circuit.init(circuit_options);
|
circuit = Circuit.init(circuit_options);
|
||||||
|
@ -481,7 +485,7 @@ pub fn update(time: usize) !State {
|
||||||
camera = newCamera;
|
camera = newCamera;
|
||||||
|
|
||||||
map.draw(camera);
|
map.draw(camera);
|
||||||
circuit.draw(camera);
|
circuit.draw(db, camera);
|
||||||
|
|
||||||
for (wires.slice()) |*wire| {
|
for (wires.slice()) |*wire| {
|
||||||
wireDrawProcess(1, wire);
|
wireDrawProcess(1, wire);
|
||||||
|
@ -503,12 +507,13 @@ pub fn update(time: usize) !State {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const pos = util.world2cell(player.pos.pos);
|
// const pos = util.world2cell(player.pos.pos);
|
||||||
const shouldHum = circuit.isEnabled(pos) or
|
const shouldHum = false;
|
||||||
circuit.isEnabled(pos + util.Dir.up) or
|
// circuit.isEnabled(pos) or
|
||||||
circuit.isEnabled(pos + util.Dir.down) or
|
// circuit.isEnabled(pos + util.Dir.up) or
|
||||||
circuit.isEnabled(pos + util.Dir.left) or
|
// circuit.isEnabled(pos + util.Dir.down) or
|
||||||
circuit.isEnabled(pos + util.Dir.right);
|
// circuit.isEnabled(pos + util.Dir.left) or
|
||||||
|
// circuit.isEnabled(pos + util.Dir.right);
|
||||||
if (shouldHum) {
|
if (shouldHum) {
|
||||||
w4.tone(.{ .start = 60 }, .{ .release = 255, .sustain = 0 }, 1, .{ .channel = .pulse1, .mode = .p50 });
|
w4.tone(.{ .start = 60 }, .{ .release = 255, .sustain = 0 }, 1, .{ .channel = .pulse1, .mode = .p50 });
|
||||||
}
|
}
|
||||||
|
@ -588,7 +593,8 @@ const Interaction = struct {
|
||||||
|
|
||||||
fn getNearestCircuitInteraction(pos: Vec2f) ?Interaction {
|
fn getNearestCircuitInteraction(pos: Vec2f) ?Interaction {
|
||||||
const cell = util.world2cell(pos);
|
const cell = util.world2cell(pos);
|
||||||
if (circuit.get_cell(cell)) |tile| {
|
const coord = Coord.fromVec2(cell);
|
||||||
|
if (circuit.getCoord(coord)) |tile| {
|
||||||
if (world.Tiles.is_switch(tile)) {
|
if (world.Tiles.is_switch(tile)) {
|
||||||
return Interaction{ .details = .lever, .pos = cell * Map.tile_size + Vec2{ 4, 4 } };
|
return Interaction{ .details = .lever, .pos = cell * Map.tile_size + Vec2{ 4, 4 } };
|
||||||
}
|
}
|
||||||
|
@ -598,9 +604,10 @@ fn getNearestCircuitInteraction(pos: Vec2f) ?Interaction {
|
||||||
|
|
||||||
fn getNearestPlugInteraction(pos: Vec2f, wireID: usize, which: usize) ?Interaction {
|
fn getNearestPlugInteraction(pos: Vec2f, wireID: usize, which: usize) ?Interaction {
|
||||||
const cell = util.world2cell(pos);
|
const cell = util.world2cell(pos);
|
||||||
if (circuit.get_cell(cell)) |tile| {
|
const coord = world.Coordinate.fromVec2(cell);
|
||||||
|
if (circuit.getCoord(coord)) |tile| {
|
||||||
if (world.Tiles.is_plug(tile)) {
|
if (world.Tiles.is_plug(tile)) {
|
||||||
const active = circuit.isEnabled(cell);
|
const active = db.isEnergized(coord);
|
||||||
return Interaction{
|
return Interaction{
|
||||||
.details = .{ .plug = .{ .wireID = wireID, .which = which } },
|
.details = .{ .plug = .{ .wireID = wireID, .which = which } },
|
||||||
.pos = cell * Map.tile_size + Vec2{ 4, 4 },
|
.pos = cell * Map.tile_size + Vec2{ 4, 4 },
|
||||||
|
@ -706,17 +713,16 @@ fn manipulationProcess(pos: *Pos, control: *Control) !void {
|
||||||
},
|
},
|
||||||
.lever => {
|
.lever => {
|
||||||
const cell = @divTrunc(i.pos, Map.tile_size);
|
const cell = @divTrunc(i.pos, Map.tile_size);
|
||||||
const new_switch = circuit.toggle(cell);
|
const coord = Coord.fromVec2(cell);
|
||||||
|
const new_switch = circuit.toggle(coord);
|
||||||
if (new_switch) |tile| {
|
if (new_switch) |tile| {
|
||||||
const T = world.Tiles;
|
const T = world.Tiles;
|
||||||
const new_state: u8 = switch (tile) {
|
const new_state: u8 = switch (tile) {
|
||||||
T.SwitchTeeWestOn, T.SwitchTeeEastOn, T.SwitchVerticalOn => 1,
|
T.SwitchTeeWestOn, T.SwitchTeeEastOn, T.SwitchVerticalOn => 1,
|
||||||
else => 0,
|
else => 0,
|
||||||
};
|
};
|
||||||
const x = level.world_x * 20 + @intCast(i16, cell[0]);
|
|
||||||
const y = level.world_y * 20 + @intCast(i16, cell[1]);
|
|
||||||
|
|
||||||
db.setSwitch(Coord.init(.{ x, y }), new_state);
|
db.setSwitch(coord.addC(Coord.fromWorld(level.world_x, level.world_y)), new_state);
|
||||||
}
|
}
|
||||||
try updateCircuit();
|
try updateCircuit();
|
||||||
},
|
},
|
||||||
|
@ -731,37 +737,35 @@ fn updateCircuit() !void {
|
||||||
wire.enabled = false;
|
wire.enabled = false;
|
||||||
if (!wire.begin().pinned or !wire.end().pinned) continue;
|
if (!wire.begin().pinned or !wire.end().pinned) continue;
|
||||||
const nodes = wire.nodes.constSlice();
|
const nodes = wire.nodes.constSlice();
|
||||||
const cellBegin = util.world2cell(nodes[0].pos);
|
const cellBegin = Coord.fromVec2(util.world2cell(nodes[0].pos));
|
||||||
const cellEnd = util.world2cell(nodes[nodes.len - 1].pos);
|
const cellEnd = Coord.fromVec2(util.world2cell(nodes[nodes.len - 1].pos));
|
||||||
|
|
||||||
circuit.bridge(.{ cellBegin, cellEnd }, wireID);
|
circuit.bridge(.{ cellBegin, cellEnd }, wireID);
|
||||||
|
|
||||||
const topleft = Coord.fromWorld(level.world_x, level.world_y);
|
const topleft = Coord.fromWorld(level.world_x, level.world_y);
|
||||||
const p1 = Coord.init(.{
|
const globalBegin = cellBegin.addC(topleft);
|
||||||
@intCast(i16, cellBegin[0]),
|
const globalEnd = cellEnd.addC(topleft);
|
||||||
@intCast(i16, cellBegin[1]),
|
|
||||||
}).addC(topleft);
|
|
||||||
const p2 = Coord.init(.{
|
|
||||||
@intCast(i16, cellEnd[0]),
|
|
||||||
@intCast(i16, cellEnd[1]),
|
|
||||||
}).addC(topleft);
|
|
||||||
|
|
||||||
db.connectPlugs(p1, p2) catch {
|
db.connectPlugs(globalBegin, globalEnd) catch {
|
||||||
w4.tracef("connect plugs error");
|
w4.tracef("connect plugs error");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try db.updateCircuit(frame_alloc);
|
||||||
|
|
||||||
// Simulate circuit
|
// Simulate circuit
|
||||||
_ = try circuit.fill(frame_alloc);
|
_ = try circuit.fill(frame_alloc, db, level);
|
||||||
|
w4.tracef("[updateCircuit] circuit filled");
|
||||||
|
// for (circuit.nodes) |node, i| {
|
||||||
|
// w4.tracef("%d: %d", i, node);
|
||||||
|
// }
|
||||||
|
|
||||||
// Energize wires
|
// Energize wires
|
||||||
for (wires.slice()) |*wire| {
|
{
|
||||||
const begin = wire.begin();
|
var i: usize = 0;
|
||||||
const end = wire.end();
|
while (circuit.enabledBridge(i)) |wireID| : (i += 1) {
|
||||||
const cellBegin = util.world2cell(begin.pos);
|
wires.slice()[wireID].enabled = true;
|
||||||
const cellEnd = util.world2cell(end.pos);
|
}
|
||||||
if ((circuit.isEnabled(cellBegin) and begin.pinned) or
|
|
||||||
(circuit.isEnabled(cellEnd) and end.pinned)) wire.enabled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add doors to map
|
// Add doors to map
|
||||||
|
@ -770,27 +774,22 @@ fn updateCircuit() !void {
|
||||||
const tile: u8 = if (door.kind == .Door) world.Tiles.Door else world.Tiles.Trapdoor;
|
const tile: u8 = if (door.kind == .Door) world.Tiles.Door else world.Tiles.Trapdoor;
|
||||||
const globalc = world.Coordinate.fromWorld(level.world_x, level.world_y);
|
const globalc = world.Coordinate.fromWorld(level.world_x, level.world_y);
|
||||||
const coord = door.coord.subC(globalc);
|
const coord = door.coord.subC(globalc);
|
||||||
w4.tracef("[getDoor] (%d, %d)", coord.val[0], coord.val[1]);
|
if (db.isEnergized(door.coord)) {
|
||||||
|
w4.tracef("[door] open (%d, %d)", door.coord.val[0], door.coord.val[1]);
|
||||||
|
try map.set_cell(coord.toVec2(), world.Tiles.Empty);
|
||||||
|
} else {
|
||||||
|
w4.tracef("[door] closed (%d, %d)", door.coord.val[0], door.coord.val[1]);
|
||||||
try map.set_cell(coord.toVec2(), tile);
|
try map.set_cell(coord.toVec2(), tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove doors that have been unlocked
|
|
||||||
const enabledDoors = try circuit.enabledDoors(frame_alloc);
|
|
||||||
defer frame_alloc.free(enabledDoors.items);
|
|
||||||
for (enabledDoors.items) |door| {
|
|
||||||
w4.tracef("[enabledDoors] (%d, %d)", door[0], door[1]);
|
|
||||||
try map.set_cell(door, world.Tiles.Empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try db.updateCircuit(frame_alloc);
|
|
||||||
|
|
||||||
for (db.circuit_info) |node, n| {
|
for (db.circuit_info) |node, n| {
|
||||||
const e = @boolToInt(node.energized);
|
const e = @boolToInt(node.energized);
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
.Conduit => |Conduit| w4.tracef("[%d]: Conduit [%d, %d] <%d>", n, Conduit[0], Conduit[1], e),
|
.Conduit => |Conduit| w4.tracef("[%d]: Conduit [%d, %d] <%d>", n, Conduit[0], Conduit[1], e),
|
||||||
.And => |And| w4.tracef("[%d]: And [%d, %d] <%d>", n, And[0], And[1], e),
|
.And => |And| w4.tracef("[%d]: And [%d, %d] <%d>", n, And[0], And[1], e),
|
||||||
.Xor => |Xor| w4.tracef("[%d]: Xor [%d, %d] <%d>", n, Xor[0], Xor[1], e),
|
.Xor => |Xor| w4.tracef("[%d]: Xor [%d, %d] <%d>", n, Xor[0], Xor[1], e),
|
||||||
.Source => w4.tracef("[%d]: Source", n),
|
.Source => w4.tracef("[%d]: Source (%d, %d)", n, node.coord.val[0], node.coord.val[1]),
|
||||||
.Socket => |Socket| {
|
.Socket => |Socket| {
|
||||||
const socket = Socket orelse std.math.maxInt(world.NodeID);
|
const socket = Socket orelse std.math.maxInt(world.NodeID);
|
||||||
w4.tracef("[%d]: Socket [%d] <%d>", n, socket, e);
|
w4.tracef("[%d]: Socket [%d] <%d>", n, socket, e);
|
||||||
|
|
|
@ -47,9 +47,9 @@ pub const Tiles = struct {
|
||||||
return tile >= 16 and tile < 20;
|
return tile >= 16 and tile < 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const LogicAnd = 21;
|
pub const LogicAnd = 20;
|
||||||
pub const LogicNot = 22;
|
pub const LogicNot = 21;
|
||||||
pub const LogicXor = 23;
|
pub const LogicXor = 22;
|
||||||
|
|
||||||
pub fn is_logic(tile: u8) bool {
|
pub fn is_logic(tile: u8) bool {
|
||||||
return tile >= 21 and tile <= 24;
|
return tile >= 21 and tile <= 24;
|
||||||
|
@ -753,7 +753,7 @@ pub const Database = struct {
|
||||||
|
|
||||||
// Circuit functions
|
// Circuit functions
|
||||||
|
|
||||||
fn getNodeID(db: *Database, coord: Coord) ?NodeID {
|
pub fn getNodeID(db: Database, coord: Coord) ?NodeID {
|
||||||
for (db.circuit_info) |node, i| {
|
for (db.circuit_info) |node, i| {
|
||||||
if (!coord.eq(node.coord)) continue;
|
if (!coord.eq(node.coord)) continue;
|
||||||
return @intCast(NodeID, i);
|
return @intCast(NodeID, i);
|
||||||
|
@ -761,6 +761,11 @@ pub const Database = struct {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getLevelNodeID(db: Database, level: Level, coord: Coord) ?NodeID {
|
||||||
|
const levelc = Coord.fromWorld(level.world_x, level.world_y);
|
||||||
|
return db.getNodeID(coord.addC(levelc));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn connectPlugs(db: *Database, p1: Coord, p2: Coord) !void {
|
pub fn connectPlugs(db: *Database, p1: Coord, p2: Coord) !void {
|
||||||
const p1id = db.getNodeID(p1) orelse return;
|
const p1id = db.getNodeID(p1) orelse return;
|
||||||
const p2id = db.getNodeID(p2) orelse return;
|
const p2id = db.getNodeID(p2) orelse return;
|
||||||
|
|
|
@ -480,17 +480,18 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
// Add switch outlets
|
// Add switch outlets
|
||||||
if (input_dir != .West and west) {
|
if (input_dir != .West and west) {
|
||||||
const out_node = @intCast(world.NodeID, nodes.items.len);
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
const new_coord = coord.add(.{1, 0});
|
||||||
try nodes.append(.{
|
try nodes.append(.{
|
||||||
.kind = .{ .SwitchOutlet = .{
|
.kind = .{ .SwitchOutlet = .{
|
||||||
.source = next_node,
|
.source = next_node,
|
||||||
.which = 0,
|
.which = 0,
|
||||||
} },
|
} },
|
||||||
.coord = coord,
|
.coord = new_coord,
|
||||||
});
|
});
|
||||||
const right = try alloc.create(Node);
|
const right = try alloc.create(Node);
|
||||||
right.* = Node{ .data = .{
|
right.* = Node{ .data = .{
|
||||||
.last_node = out_node,
|
.last_node = out_node,
|
||||||
.coord = coord.add(.{ 1, 0 }),
|
.coord = new_coord,
|
||||||
.last_coord = coord,
|
.last_coord = coord,
|
||||||
} };
|
} };
|
||||||
bfs_queue.append(right);
|
bfs_queue.append(right);
|
||||||
|
@ -498,17 +499,18 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
|
|
||||||
if (input_dir != .East and east) {
|
if (input_dir != .East and east) {
|
||||||
const out_node = @intCast(world.NodeID, nodes.items.len);
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
const new_coord = coord.add(.{-1, 0});
|
||||||
try nodes.append(.{
|
try nodes.append(.{
|
||||||
.kind = .{ .SwitchOutlet = .{
|
.kind = .{ .SwitchOutlet = .{
|
||||||
.source = next_node,
|
.source = next_node,
|
||||||
.which = 0,
|
.which = 0,
|
||||||
} },
|
} },
|
||||||
.coord = coord,
|
.coord = new_coord,
|
||||||
});
|
});
|
||||||
const left = try alloc.create(Node);
|
const left = try alloc.create(Node);
|
||||||
left.* = Node{ .data = .{
|
left.* = Node{ .data = .{
|
||||||
.last_node = out_node,
|
.last_node = out_node,
|
||||||
.coord = coord.add(.{ -1, 0 }),
|
.coord = new_coord,
|
||||||
.last_coord = coord,
|
.last_coord = coord,
|
||||||
} };
|
} };
|
||||||
bfs_queue.append(left);
|
bfs_queue.append(left);
|
||||||
|
@ -516,17 +518,18 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
|
|
||||||
if (input_dir != .South and south) {
|
if (input_dir != .South and south) {
|
||||||
const out_node = @intCast(world.NodeID, nodes.items.len);
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
const new_coord = coord.add(.{0, 1});
|
||||||
try nodes.append(.{
|
try nodes.append(.{
|
||||||
.kind = .{ .SwitchOutlet = .{
|
.kind = .{ .SwitchOutlet = .{
|
||||||
.source = next_node,
|
.source = next_node,
|
||||||
.which = 1,
|
.which = 1,
|
||||||
} },
|
} },
|
||||||
.coord = coord,
|
.coord = new_coord,
|
||||||
});
|
});
|
||||||
const down = try alloc.create(Node);
|
const down = try alloc.create(Node);
|
||||||
down.* = Node{ .data = .{
|
down.* = Node{ .data = .{
|
||||||
.last_node = out_node,
|
.last_node = out_node,
|
||||||
.coord = coord.add(.{ 0, 1 }),
|
.coord = new_coord,
|
||||||
.last_coord = coord,
|
.last_coord = coord,
|
||||||
} };
|
} };
|
||||||
bfs_queue.append(down);
|
bfs_queue.append(down);
|
||||||
|
@ -534,17 +537,18 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
|
|
||||||
if (input_dir != .North and north) {
|
if (input_dir != .North and north) {
|
||||||
const out_node = @intCast(world.NodeID, nodes.items.len);
|
const out_node = @intCast(world.NodeID, nodes.items.len);
|
||||||
|
const new_coord = coord.add(.{0, -1});
|
||||||
try nodes.append(.{
|
try nodes.append(.{
|
||||||
.kind = .{ .SwitchOutlet = .{
|
.kind = .{ .SwitchOutlet = .{
|
||||||
.source = next_node,
|
.source = next_node,
|
||||||
.which = 1,
|
.which = 1,
|
||||||
} },
|
} },
|
||||||
.coord = coord,
|
.coord = new_coord,
|
||||||
});
|
});
|
||||||
const up = try alloc.create(Node);
|
const up = try alloc.create(Node);
|
||||||
up.* = Node{ .data = .{
|
up.* = Node{ .data = .{
|
||||||
.last_node = out_node,
|
.last_node = out_node,
|
||||||
.coord = coord.add(.{ 0, -1 }),
|
.coord = new_coord,
|
||||||
.last_coord = coord,
|
.last_coord = coord,
|
||||||
} };
|
} };
|
||||||
bfs_queue.append(up);
|
bfs_queue.append(up);
|
||||||
|
@ -695,21 +699,5 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < nodes.items.len) : (i += 1) {
|
|
||||||
switch (nodes.items[i].kind) {
|
|
||||||
// .Source => {
|
|
||||||
// },
|
|
||||||
.And => {},
|
|
||||||
.Xor => {},
|
|
||||||
.Conduit => {},
|
|
||||||
.Plug => {},
|
|
||||||
.Switch => {},
|
|
||||||
.Join => {},
|
|
||||||
.Outlet => {},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue