Add direction enum, improve wire loading/saving

master
Louis Pearson 2022-08-11 00:42:48 -06:00
parent 05328945e6
commit 8a18d321b3
4 changed files with 321 additions and 176 deletions

View File

@ -5036,6 +5036,101 @@
"defUid": 60,
"px": [120,136],
"fieldInstances": []
},
{
"__identifier": "Wire",
"__grid": [18,5],
"__pivot": [0.5,0.5],
"__tags": [],
"__tile": null,
"__smartColor": "#BC2634",
"iid": "69613910-02f0-11ed-9529-d355f437215d",
"width": 8,
"height": 8,
"defUid": 93,
"px": [148,44],
"fieldInstances": [
{ "__identifier": "Point", "__value": [{ "cx": 12, "cy": 5 }], "__type": "Array<Point>", "__tile": null, "defUid": 94, "realEditorValues": [{
"id": "V_String",
"params": ["12,5"]
}] },
{ "__identifier": "Anchor", "__value": [ true, false ], "__type": "Array<Bool>", "__tile": null, "defUid": 98, "realEditorValues": [ null, {
"id": "V_Bool",
"params": [ false ]
} ] }
]
},
{
"__identifier": "Wire",
"__grid": [18,10],
"__pivot": [0.5,0.5],
"__tags": [],
"__tile": null,
"__smartColor": "#BC2634",
"iid": "725b0b40-02f0-11ed-9529-479e26eec218",
"width": 8,
"height": 8,
"defUid": 93,
"px": [148,84],
"fieldInstances": [
{ "__identifier": "Point", "__value": [ { "cx": 12, "cy": 11 }, { "cx": 6, "cy": 11 } ], "__type": "Array<Point>", "__tile": null, "defUid": 94, "realEditorValues": [ {
"id": "V_String",
"params": ["12,11"]
}, {
"id": "V_String",
"params": ["6,11"]
} ] },
{ "__identifier": "Anchor", "__value": [ true, false ], "__type": "Array<Bool>", "__tile": null, "defUid": 98, "realEditorValues": [ {
"id": "V_Bool",
"params": [ true ]
}, {
"id": "V_Bool",
"params": [ false ]
} ] }
]
},
{
"__identifier": "Wire",
"__grid": [11,10],
"__pivot": [0.5,0.5],
"__tags": [],
"__tile": null,
"__smartColor": "#BC2634",
"iid": "7c02a9a0-02f0-11ed-9529-2549e7fc0619",
"width": 8,
"height": 8,
"defUid": 93,
"px": [92,84],
"fieldInstances": [
{ "__identifier": "Point", "__value": [{ "cx": 16, "cy": 11 }], "__type": "Array<Point>", "__tile": null, "defUid": 94, "realEditorValues": [{
"id": "V_String",
"params": ["16,11"]
}] },
{ "__identifier": "Anchor", "__value": [ true, false ], "__type": "Array<Bool>", "__tile": null, "defUid": 98, "realEditorValues": [ null, {
"id": "V_Bool",
"params": [ false ]
} ] }
]
},
{
"__identifier": "Wire",
"__grid": [12,13],
"__pivot": [0.5,0.5],
"__tags": [],
"__tile": null,
"__smartColor": "#BC2634",
"iid": "852141e0-02f0-11ed-9529-25cb29c77f46",
"width": 8,
"height": 8,
"defUid": 93,
"px": [100,108],
"fieldInstances": [
{ "__identifier": "Point", "__value": [{ "cx": 15, "cy": 13 }], "__type": "Array<Point>", "__tile": null, "defUid": 94, "realEditorValues": [{
"id": "V_String",
"params": ["15,13"]
}] },
{ "__identifier": "Anchor", "__value": [ true, true ], "__type": "Array<Bool>", "__tile": null, "defUid": 98, "realEditorValues": [ null, null ] }
]
}
]
},
@ -5063,8 +5158,8 @@
1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,
0,10,0,0,0,0,0,10,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,6,13,13,13,13,13,1,13,13,13,13,1,0,
0,0,0,0,1,0,1,0,0,0,0,1,1,6,1,1,1,0,1,0,0,0,0,2,1,0,1,1,0,0,0,10,0,0,0,
0,10,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,3,0,1,6,1,1,
0,0,0,0,1,0,1,0,0,0,0,1,1,6,1,1,1,0,1,0,0,0,0,0,1,0,1,1,0,0,0,10,0,0,0,
0,10,0,1,0,0,0,0,2,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,3,0,1,6,1,1,
1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,2,12,0,10,0,0,0,9,
0,1,0,0,0,0,1,6,1,0,0,0,12,12,0,12,0,0,0,1,0,1,0,0,0,0,1,0,3,1,1,1,6,1,0,
12,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,3,0,1,0,
@ -5094,7 +5189,7 @@
{ "px": [64,64], "src": [112,48], "f": 0, "t": 110, "d": [41,168] },
{ "px": [48,144], "src": [56,48], "f": 0, "t": 103, "d": [42,366] },
{ "px": [64,144], "src": [56,48], "f": 0, "t": 103, "d": [42,368] },
{ "px": [152,72], "src": [88,48], "f": 0, "t": 107, "d": [43,199] },
{ "px": [152,80], "src": [88,48], "f": 0, "t": 107, "d": [43,219] },
{ "px": [8,8], "src": [48,48], "f": 0, "t": 102, "d": [44,21] },
{ "px": [24,24], "src": [48,48], "f": 0, "t": 102, "d": [44,63] },
{ "px": [32,24], "src": [48,48], "f": 0, "t": 102, "d": [44,64] },
@ -5121,8 +5216,8 @@
{ "px": [152,64], "src": [72,48], "f": 0, "t": 105, "d": [45,179] },
{ "px": [8,72], "src": [72,48], "f": 0, "t": 105, "d": [45,181] },
{ "px": [104,72], "src": [72,48], "f": 0, "t": 105, "d": [45,193] },
{ "px": [152,72], "src": [72,48], "f": 0, "t": 105, "d": [45,199] },
{ "px": [104,80], "src": [72,48], "f": 0, "t": 105, "d": [45,213] },
{ "px": [152,80], "src": [72,48], "f": 0, "t": 105, "d": [45,219] },
{ "px": [16,88], "src": [72,48], "f": 0, "t": 105, "d": [45,222] },
{ "px": [104,88], "src": [72,48], "f": 0, "t": 105, "d": [45,233] },
{ "px": [104,96], "src": [72,48], "f": 0, "t": 105, "d": [45,253] },
@ -5148,7 +5243,7 @@
{ "px": [48,80], "src": [0,8], "f": 0, "t": 16, "d": [129,206] },
{ "px": [88,80], "src": [0,8], "f": 0, "t": 16, "d": [129,211] },
{ "px": [144,40], "src": [16,8], "f": 0, "t": 18, "d": [59,118] },
{ "px": [144,72], "src": [16,8], "f": 0, "t": 18, "d": [59,198] },
{ "px": [144,80], "src": [16,8], "f": 0, "t": 18, "d": [59,218] },
{ "px": [96,104], "src": [24,8], "f": 0, "t": 19, "d": [56,272] },
{ "px": [64,120], "src": [80,8], "f": 0, "t": 26, "d": [53,308] },
{ "px": [152,88], "src": [96,8], "f": 0, "t": 28, "d": [78,239] },
@ -5363,109 +5458,6 @@
{ "px": [48,128], "src": [32,56], "f": 0, "t": 116, "d": [22,326] },
{ "px": [56,8], "src": [8,56], "f": 0, "t": 113, "d": [23,27] },
{ "px": [120,128], "src": [8,56], "f": 0, "t": 113, "d": [23,335] },
{ "px": [0,0], "src": [120,56], "f": 0, "t": 127, "d": [161,0] },
{ "px": [8,0], "src": [120,56], "f": 0, "t": 127, "d": [161,1] },
{ "px": [16,0], "src": [120,56], "f": 0, "t": 127, "d": [161,2] },
{ "px": [56,0], "src": [120,56], "f": 0, "t": 127, "d": [161,7] },
{ "px": [80,0], "src": [120,56], "f": 0, "t": 127, "d": [161,10] },
{ "px": [88,0], "src": [120,56], "f": 0, "t": 127, "d": [161,11] },
{ "px": [96,0], "src": [120,56], "f": 0, "t": 127, "d": [161,12] },
{ "px": [104,0], "src": [120,56], "f": 0, "t": 127, "d": [161,13] },
{ "px": [112,0], "src": [120,56], "f": 0, "t": 127, "d": [161,14] },
{ "px": [120,0], "src": [120,56], "f": 0, "t": 127, "d": [161,15] },
{ "px": [128,0], "src": [120,56], "f": 0, "t": 127, "d": [161,16] },
{ "px": [136,0], "src": [120,56], "f": 0, "t": 127, "d": [161,17] },
{ "px": [144,0], "src": [120,56], "f": 0, "t": 127, "d": [161,18] },
{ "px": [152,0], "src": [120,56], "f": 0, "t": 127, "d": [161,19] },
{ "px": [0,8], "src": [120,56], "f": 0, "t": 127, "d": [161,20] },
{ "px": [8,8], "src": [120,56], "f": 0, "t": 127, "d": [161,21] },
{ "px": [88,8], "src": [120,56], "f": 0, "t": 127, "d": [161,31] },
{ "px": [96,8], "src": [120,56], "f": 0, "t": 127, "d": [161,32] },
{ "px": [104,8], "src": [120,56], "f": 0, "t": 127, "d": [161,33] },
{ "px": [112,8], "src": [120,56], "f": 0, "t": 127, "d": [161,34] },
{ "px": [120,8], "src": [120,56], "f": 0, "t": 127, "d": [161,35] },
{ "px": [128,8], "src": [120,56], "f": 0, "t": 127, "d": [161,36] },
{ "px": [136,8], "src": [120,56], "f": 0, "t": 127, "d": [161,37] },
{ "px": [144,8], "src": [120,56], "f": 0, "t": 127, "d": [161,38] },
{ "px": [152,8], "src": [120,56], "f": 0, "t": 127, "d": [161,39] },
{ "px": [0,16], "src": [120,56], "f": 0, "t": 127, "d": [161,40] },
{ "px": [8,16], "src": [120,56], "f": 0, "t": 127, "d": [161,41] },
{ "px": [88,16], "src": [120,56], "f": 0, "t": 127, "d": [161,51] },
{ "px": [96,16], "src": [120,56], "f": 0, "t": 127, "d": [161,52] },
{ "px": [104,16], "src": [120,56], "f": 0, "t": 127, "d": [161,53] },
{ "px": [112,16], "src": [120,56], "f": 0, "t": 127, "d": [161,54] },
{ "px": [120,16], "src": [120,56], "f": 0, "t": 127, "d": [161,55] },
{ "px": [128,16], "src": [120,56], "f": 0, "t": 127, "d": [161,56] },
{ "px": [136,16], "src": [120,56], "f": 0, "t": 127, "d": [161,57] },
{ "px": [144,16], "src": [120,56], "f": 0, "t": 127, "d": [161,58] },
{ "px": [152,16], "src": [120,56], "f": 0, "t": 127, "d": [161,59] },
{ "px": [0,24], "src": [120,56], "f": 0, "t": 127, "d": [161,60] },
{ "px": [8,24], "src": [120,56], "f": 0, "t": 127, "d": [161,61] },
{ "px": [152,24], "src": [120,56], "f": 0, "t": 127, "d": [161,79] },
{ "px": [0,32], "src": [120,56], "f": 0, "t": 127, "d": [161,80] },
{ "px": [8,32], "src": [120,56], "f": 0, "t": 127, "d": [161,81] },
{ "px": [0,40], "src": [120,56], "f": 0, "t": 127, "d": [161,100] },
{ "px": [8,40], "src": [120,56], "f": 0, "t": 127, "d": [161,101] },
{ "px": [0,48], "src": [120,56], "f": 0, "t": 127, "d": [161,120] },
{ "px": [8,48], "src": [120,56], "f": 0, "t": 127, "d": [161,121] },
{ "px": [152,48], "src": [120,56], "f": 0, "t": 127, "d": [161,139] },
{ "px": [0,56], "src": [120,56], "f": 0, "t": 127, "d": [161,140] },
{ "px": [8,56], "src": [120,56], "f": 0, "t": 127, "d": [161,141] },
{ "px": [56,56], "src": [120,56], "f": 0, "t": 127, "d": [161,147] },
{ "px": [64,56], "src": [120,56], "f": 0, "t": 127, "d": [161,148] },
{ "px": [72,56], "src": [120,56], "f": 0, "t": 127, "d": [161,149] },
{ "px": [80,56], "src": [120,56], "f": 0, "t": 127, "d": [161,150] },
{ "px": [88,56], "src": [120,56], "f": 0, "t": 127, "d": [161,151] },
{ "px": [96,56], "src": [120,56], "f": 0, "t": 127, "d": [161,152] },
{ "px": [104,56], "src": [120,56], "f": 0, "t": 127, "d": [161,153] },
{ "px": [112,56], "src": [120,56], "f": 0, "t": 127, "d": [161,154] },
{ "px": [120,56], "src": [120,56], "f": 0, "t": 127, "d": [161,155] },
{ "px": [128,56], "src": [120,56], "f": 0, "t": 127, "d": [161,156] },
{ "px": [136,56], "src": [120,56], "f": 0, "t": 127, "d": [161,157] },
{ "px": [144,56], "src": [120,56], "f": 0, "t": 127, "d": [161,158] },
{ "px": [152,56], "src": [120,56], "f": 0, "t": 127, "d": [161,159] },
{ "px": [0,64], "src": [120,56], "f": 0, "t": 127, "d": [161,160] },
{ "px": [8,64], "src": [120,56], "f": 0, "t": 127, "d": [161,161] },
{ "px": [152,64], "src": [120,56], "f": 0, "t": 127, "d": [161,179] },
{ "px": [0,72], "src": [120,56], "f": 0, "t": 127, "d": [161,180] },
{ "px": [8,72], "src": [120,56], "f": 0, "t": 127, "d": [161,181] },
{ "px": [0,80], "src": [120,56], "f": 0, "t": 127, "d": [161,200] },
{ "px": [8,80], "src": [120,56], "f": 0, "t": 127, "d": [161,201] },
{ "px": [0,88], "src": [120,56], "f": 0, "t": 127, "d": [161,220] },
{ "px": [8,88], "src": [120,56], "f": 0, "t": 127, "d": [161,221] },
{ "px": [0,96], "src": [120,56], "f": 0, "t": 127, "d": [161,240] },
{ "px": [8,96], "src": [120,56], "f": 0, "t": 127, "d": [161,241] },
{ "px": [152,96], "src": [120,56], "f": 0, "t": 127, "d": [161,259] },
{ "px": [0,104], "src": [120,56], "f": 0, "t": 127, "d": [161,260] },
{ "px": [8,104], "src": [120,56], "f": 0, "t": 127, "d": [161,261] },
{ "px": [56,104], "src": [120,56], "f": 0, "t": 127, "d": [161,267] },
{ "px": [64,104], "src": [120,56], "f": 0, "t": 127, "d": [161,268] },
{ "px": [72,104], "src": [120,56], "f": 0, "t": 127, "d": [161,269] },
{ "px": [80,104], "src": [120,56], "f": 0, "t": 127, "d": [161,270] },
{ "px": [136,104], "src": [120,56], "f": 0, "t": 127, "d": [161,277] },
{ "px": [144,104], "src": [120,56], "f": 0, "t": 127, "d": [161,278] },
{ "px": [152,104], "src": [120,56], "f": 0, "t": 127, "d": [161,279] },
{ "px": [0,112], "src": [120,56], "f": 0, "t": 127, "d": [161,280] },
{ "px": [8,112], "src": [120,56], "f": 0, "t": 127, "d": [161,281] },
{ "px": [72,112], "src": [120,56], "f": 0, "t": 127, "d": [161,289] },
{ "px": [152,112], "src": [120,56], "f": 0, "t": 127, "d": [161,299] },
{ "px": [0,120], "src": [120,56], "f": 0, "t": 127, "d": [161,300] },
{ "px": [8,120], "src": [120,56], "f": 0, "t": 127, "d": [161,301] },
{ "px": [152,144], "src": [120,56], "f": 0, "t": 127, "d": [161,379] },
{ "px": [48,152], "src": [120,56], "f": 0, "t": 127, "d": [161,386] },
{ "px": [56,152], "src": [120,56], "f": 0, "t": 127, "d": [161,387] },
{ "px": [64,152], "src": [120,56], "f": 0, "t": 127, "d": [161,388] },
{ "px": [72,152], "src": [120,56], "f": 0, "t": 127, "d": [161,389] },
{ "px": [80,152], "src": [120,56], "f": 0, "t": 127, "d": [161,390] },
{ "px": [88,152], "src": [120,56], "f": 0, "t": 127, "d": [161,391] },
{ "px": [96,152], "src": [120,56], "f": 0, "t": 127, "d": [161,392] },
{ "px": [104,152], "src": [120,56], "f": 0, "t": 127, "d": [161,393] },
{ "px": [112,152], "src": [120,56], "f": 0, "t": 127, "d": [161,394] },
{ "px": [120,152], "src": [120,56], "f": 0, "t": 127, "d": [161,395] },
{ "px": [128,152], "src": [120,56], "f": 0, "t": 127, "d": [161,396] },
{ "px": [136,152], "src": [120,56], "f": 0, "t": 127, "d": [161,397] },
{ "px": [144,152], "src": [120,56], "f": 0, "t": 127, "d": [161,398] },
{ "px": [152,152], "src": [120,56], "f": 0, "t": 127, "d": [161,399] },
{ "px": [40,144], "src": [8,16], "f": 0, "t": 33, "d": [125,365] },
{ "px": [24,64], "src": [24,16], "f": 0, "t": 35, "d": [126,163] },
{ "px": [24,80], "src": [24,16], "f": 0, "t": 35, "d": [126,203] },

View File

@ -50,6 +50,19 @@ const Wire = struct {
node.pos = b + @splat(2, @intToFloat(f32, i)) * size / @splat(2, @intToFloat(f32, this.nodes.len));
}
}
pub fn addInline(this: *@This(), div: usize, point: Vec2f) !void {
const divf = @splat(2, @intToFloat(f32, div));
var last = this.end().pos;
const dist = point - last;
const chunk = dist / divf;
var i: usize = 0;
while (i < div) : (i += 1) {
const next = last + chunk;
last = next;
try this.nodes.append(Pos.init(next));
}
}
};
const Player = struct {
@ -202,6 +215,11 @@ const playerAnim = pac: {
break :pac animArr.slice();
};
fn posFromWorld(coord: world.Coordinate) Vec2f {
const tile_size = Vec2{ 8, 8 };
return util.vec2ToVec2f(coord.toVec2() * tile_size);
}
fn loadLevel(lvl: usize) !void {
fba.reset();
map.clear();
@ -236,24 +254,39 @@ fn loadLevel(lvl: usize) !void {
const coord0 = wire[0].coord.subC(levelc);
const coord1 = wire[1].coord.subC(levelc);
w4.tracef("---- Wire [%d, %d] (%d, %d), (%d, %d)", wireArr[0], wireArr[1], coord0.val[0], coord0.val[1], coord1.val[0], coord1.val[1]);
const p1 = util.vec2ToVec2f(coord0.toVec2() * tile_size + Vec2{ 4, 4 });
const p2 = util.vec2ToVec2f(coord1.toVec2() * tile_size + Vec2{ 4, 4 });
var w = try wires.addOne();
_ = try w.nodes.resize(0);
// const divisions = wire.divisions;
const divisions = 10;
var i: usize = 0;
while (i <= divisions) : (i += 1) {
try w.nodes.append(Pos.init(p1));
const divisions = 7;
var last_coord: world.Coordinate = undefined;
for (wireSlice) |world_wire| {
switch (world_wire) {
.Begin => |coord| {
last_coord = coord.subC(levelc);
w4.tracef("\t start (%d, %d)", last_coord.val[0], last_coord.val[1]);
try w.nodes.append(Pos.init(posFromWorld(last_coord) + Vec2f{ 4, 4 }));
},
.BeginPinned => |coord| {
last_coord = coord.subC(levelc);
w4.tracef("\t start [a] (%d, %d)", last_coord.val[0], last_coord.val[1]);
try w.nodes.append(Pos.init(posFromWorld(last_coord) + Vec2f{ 4, 4 }));
},
.Point => |offset| {
last_coord = last_coord.addOffset(offset);
w4.tracef("\t point (%d, %d) = last + (%d, %d)", last_coord.val[0], last_coord.val[1], offset[0], offset[1]);
try w.addInline(divisions, posFromWorld(last_coord) + Vec2f{ 4, 4 });
},
.PointPinned => |offset| {
last_coord = last_coord.addOffset(offset);
w4.tracef("\t point (%d, %d) = last + (%d, %d)", last_coord.val[0], last_coord.val[1], offset[0], offset[1]);
try w.addInline(divisions, posFromWorld(last_coord) + Vec2f{ 4, 4 });
},
.End => break,
}
}
w.begin().pos = p1;
w.end().pos = p2;
w.begin().pinned = wire[0].anchored;
w.end().pinned = wire[1].anchored;
w.straighten();
}
}
@ -313,27 +346,37 @@ fn moveLevel(direction: enum { L, R, U, D }) !void {
// Save wires back into database
const levelc = world.Coordinate.fromWorld(level.world_x, level.world_y);
while (wires.popOrNull()) |*w| {
var wire: [10]world.Wire = undefined;
// Are the ends anchored?
const aStart = w.begin().pinned;
const aEnd = w.begin().pinned;
const divby = @splat(2, @as(f32, 8));
const wstart = world.Coordinate.fromVec2f(w.begin().pos / divby).addC(levelc);
const offset = w.end().pos - w.begin().pos;
const end = world.Coordinate.fromVec2f(offset / divby).toOffset();
var wire: [3]world.Wire = undefined;
if (aStart) {
wire[0] = .{ .BeginPinned = wstart };
} else {
wire[0] = .{ .Begin = wstart };
w4.tracef("[moveLevel] new wire (%d,%d)", wstart.val[0], wstart.val[1]);
wire[0] = if (aStart) .{ .BeginPinned = wstart } else .{ .Begin = wstart };
var idx: usize = 1;
var last_pos = w.begin().pos;
for (w.nodes.constSlice()) |point, i| {
if (i == 0) continue;
const length = util.lengthf(point.pos - last_pos) / 8;
if (i % 8 == 0 or length > 6 or i == w.nodes.constSlice().len - 1) {
const diff = point.pos - last_pos;
const offset = world.Coordinate.fromVec2f(diff / divby).toOffset();
wire[idx] = if (point.pinned) .{ .PointPinned = offset } else .{ .Point = offset };
idx += 1;
last_pos = point.pos;
w4.tracef("\t offset (%d,%d)", offset[0], offset[1]);
}
}
if (aEnd) {
wire[1] = .{ .PointPinned = end };
} else {
wire[1] = .{ .Point = end };
}
wire[idx] = .End;
idx += 1;
wire[2] = .End;
db.addWire(&wire);
w4.tracef("\t finished, length %d", idx);
db.addWire(wire[0..idx]);
}
// TODO: Figure out the more principled way for checking boundaries

View File

@ -117,6 +117,15 @@ pub const CircuitType = enum(u5) {
Diode = 11,
Conduit_Vertical = 12,
Conduit_Horizontal = 13,
pub fn canConnect(circuit: CircuitType, side: Direction) bool {
return switch (circuit) {
.None => false,
.Conduit_Vertical => (side != .East and side != .West),
.Conduit_Horizontal => (side != .North and side != .South),
else => true,
};
}
};
pub const TileData = union(enum) {
@ -263,6 +272,33 @@ pub const Coordinate = struct {
}
};
pub const Direction = enum {
North,
West,
East,
South,
pub const each = [_]Direction{ .North, .West, .East, .South };
pub fn toOffset(dir: Direction) [2]i16 {
return switch (dir) {
.North => .{ 0, -1 },
.West => .{ -1, 0 },
.East => .{ 1, 0 },
.South => .{ 0, 1 },
};
}
pub fn getOpposite(dir: Direction) Direction {
return switch (dir) {
.North => .South,
.West => .East,
.East => .West,
.South => .North,
};
}
};
pub const Level = struct {
world_x: i8,
world_y: i8,
@ -332,6 +368,11 @@ pub const Level = struct {
return tiles[i];
}
pub fn getCircuit(level: Level, globalc: Coord) ?CircuitType {
const tile = level.getTile(globalc) orelse return null;
return tile.getCircuit();
}
pub fn getJoin(level: Level, which: usize) ?Coordinate {
const tiles = level.tiles orelse return null;
var joinCount: usize = 0;
@ -563,11 +604,11 @@ pub const Wire = union(enum) {
try coord.write(writer);
},
.Point => |point| {
const byte = @bitCast(u8, @intCast(i8, point[0])) | @bitCast(u8, @intCast(i8, point[1])) << 4;
const byte = (@bitCast(u8, @intCast(i8, point[0])) & 0b0000_1111) | (@bitCast(u8, @intCast(i8, point[1])) & 0b1111_0000) << 4;
try writer.writeByte(byte);
},
.PointPinned => |point| {
const byte = @bitCast(u8, @intCast(i8, point[0])) | @bitCast(u8, @intCast(i8, point[1])) << 4;
const byte = (@bitCast(u8, @intCast(i8, point[0])) & 0b0000_1111) | (@bitCast(u8, @intCast(i8, point[1])) & 0b1111_0000) << 4;
try writer.writeByte(byte);
},
.End => {},

View File

@ -3,6 +3,9 @@ const std = @import("std");
const LDtk = @import("../deps/zig-ldtk/src/LDtk.zig");
const world = @import("../src/world.zig");
const Coord = world.Coordinate;
const Dir = world.Direction;
const KB = 1024;
const MB = 1024 * KB;
@ -71,15 +74,15 @@ fn make(step: *std.build.Step) !void {
.wires = &wires,
});
for (parsed_level.tiles.?) |tile, i| {
if (tile == .tile) {
std.log.warn("{:0>2}: {}", .{ i, tile.tile });
} else if (tile == .flags) {
std.log.warn("{:0>2}: {s} {s}", .{ i, @tagName(tile.flags.solid), @tagName(tile.flags.circuit) });
} else {
std.log.warn("{:0>2}: {}", .{ i, tile });
}
}
// for (parsed_level.tiles.?) |tile, i| {
// if (tile == .tile) {
// std.log.warn("{:0>2}: {}", .{ i, tile.tile });
// } else if (tile == .flags) {
// std.log.warn("{:0>2}: {s} {s}", .{ i, @tagName(tile.flags.solid), @tagName(tile.flags.circuit) });
// } else {
// std.log.warn("{:0>2}: {}", .{ i, tile });
// }
// }
try levels.append(parsed_level);
}
@ -188,11 +191,11 @@ fn parseLevel(opt: struct {
kind_opt = .Trapdoor;
}
const levelc = world.Coordinate.fromWorld(world_x, world_y);
const levelc = Coord.fromWorld(world_x, world_y);
// Parsing code for wire entities. They're a little more complex
// than the rest
if (kind_opt) |kind| {
const entc = world.Coordinate.init(.{
const entc = Coord.init(.{
@intCast(i16, entity.__grid[0]),
@intCast(i16, entity.__grid[1]),
});
@ -202,28 +205,28 @@ fn parseLevel(opt: struct {
if (is_wire) {
var anchor1 = false;
var anchor2 = false;
const p1_c = world.Coordinate.init(.{
@intCast(i16, entity.__grid[0]),
@intCast(i16, entity.__grid[1]),
});
var p2_c = world.Coordinate.init(.{
const p1_c = Coord.init(.{
@intCast(i16, entity.__grid[0]),
@intCast(i16, entity.__grid[1]),
});
std.log.warn("[parseLevel:wire] {}", .{ p1_c });
var points: []Coord = undefined;
for (entity.fieldInstances) |field| {
if (std.mem.eql(u8, field.__identifier, "Anchor")) {
const anchors = field.__value.Array.items;
anchor1 = anchors[0].Bool;
anchor2 = anchors[1].Bool;
} else if (std.mem.eql(u8, field.__identifier, "Point")) {
const end = field.__value.Array.items.len - 1;
const endpoint = field.__value.Array.items[end];
const x = endpoint.Object.get("cx").?;
const y = endpoint.Object.get("cy").?;
p2_c.val = .{
@intCast(i16, x.Integer),
@intCast(i16, y.Integer),
};
points = try allocator.alloc(Coord, field.__value.Array.items.len);
for (field.__value.Array.items) |point, i| {
const x = point.Object.get("cx").?;
const y = point.Object.get("cy").?;
std.log.warn("\t{} {}", .{ x.Integer, y.Integer });
points[i] = Coord.init(.{
@intCast(i16, x.Integer),
@intCast(i16, y.Integer),
});
}
}
}
@ -233,11 +236,21 @@ fn parseLevel(opt: struct {
try wires.append(.{ .Begin = p1_c.addC(levelc) });
}
if (anchor2) {
try wires.append(.{ .PointPinned = p2_c.subC(p1_c).toOffset() });
} else {
try wires.append(.{ .Point = p2_c.subC(p1_c).toOffset() });
std.log.warn("\tConverting to wire nodes", .{});
var last_point = p1_c;
for (points) |point, i| {
const offset = point.subC(last_point).toOffset();
std.log.warn("\toffset: {} {}", .{ offset[0], offset[1] });
last_point = point;
if (i == points.len - 1) {
if (anchor2) {
try wires.append(.{ .PointPinned = offset });
continue;
}
}
try wires.append(.{ .Point = offset });
}
try wires.append(.End);
}
}
@ -317,17 +330,30 @@ fn parseLevel(opt: struct {
}
pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayList(world.CircuitNode) {
const Coord = world.Coordinate;
const SearchItem = struct {
coord: Coord,
last_coord: ?Coord = null,
last_node: world.NodeID,
fn next(current: @This(), current_node: world.NodeID, offset: [2]i16) @This() {
return @This(){
.coord = current.coord.add(offset),
.last_coord = current.coord,
.last_node = current_node,
};
}
};
const Queue = std.TailQueue(SearchItem);
const Node = Queue.Node;
var nodes = std.ArrayList(world.CircuitNode).init(alloc);
var node_input_dir = std.ArrayList(Dir).init(alloc);
defer node_input_dir.deinit();
var source_node = std.ArrayList(world.NodeID).init(alloc);
defer source_node.deinit();
var sources = Queue{};
var sockets = Queue{};
@ -390,11 +416,15 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
var next_node = last_node;
const tile = level.getTile(coord) orelse continue;
// std.log.warn("[buildCircuit] {} [{}] {}", .{ coord, node.data.last_node, tile });
if (tile != .flags) continue;
const flags = tile.flags;
const dir = if (last_node != std.math.maxInt(world.NodeID))
getInputDirection(coord, nodes.items[last_node].coord)
else
.South;
switch (flags.circuit) {
.Conduit => {
// Collects from two other nodes. Intersections will need to be stored so when
@ -411,6 +441,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.kind = .{ .Socket = null },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
},
.Plug => {
// Plugs by their nature end a conduit path, so don't add
@ -419,6 +451,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.kind = .{ .Plug = last_node },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
continue;
},
.Outlet => {
@ -427,6 +461,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.kind = .{ .Outlet = last_node },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
},
.Switch_Off => {
// Add switch
@ -438,6 +474,33 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
} },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
// Loop over sides, check if they are connected, and add a
// switch outlet if so
for (Dir.each) |side| {
const next_coord = coord.add(side.toOffset());
if (level.getCircuit(next_coord)) |circuit| {
if (circuit.canConnect(side.getOpposite()) and side != dir) {
const outlet = @intCast(world.NodeID, nodes.items.len);
const which = if (side == .North or side == .South) @as(u8, 1) else @as(u8, 0);
try nodes.append(.{
.kind = .{ .SwitchOutlet = .{
.source = next_node,
.which = which,
} },
.coord = next_coord,
});
try node_input_dir.append(side);
try source_node.append(next_node);
const outlet_search = try alloc.create(Node);
outlet_search.* = .{ .data = node.data.next(outlet, side.toOffset()) };
bfs_queue.append(outlet_search);
}
}
}
},
.Switch_On => {
// Add switch
@ -449,6 +512,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
} },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
},
.Join => {
const last_coord = node.data.last_coord.?;
@ -461,6 +526,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.kind = .{ .Join = last_node },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
}
},
.And => {
@ -469,6 +536,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.kind = .{ .And = .{ std.math.maxInt(world.NodeID), std.math.maxInt(world.NodeID) } },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
},
.Xor => {
next_node = @intCast(world.NodeID, nodes.items.len);
@ -476,6 +545,8 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.kind = .{ .Xor = .{ std.math.maxInt(world.NodeID), std.math.maxInt(world.NodeID) } },
.coord = coord,
});
try node_input_dir.append(dir);
try source_node.append(last_node);
},
.Diode => {
// TODO
@ -523,12 +594,13 @@ pub fn buildCircuit(alloc: std.mem.Allocator, levels: []world.Level) !std.ArrayL
.Source => {},
.And => {
const neighbors = try findNeighbors(alloc, levels, nodes.items, i);
defer neighbors.deinit();
std.log.warn("[{}]: Found {} neighbors", .{ i, neighbors.items.len });
for (neighbors.items) |node, a| {
std.log.warn("\tNeighbor {}: [{}] {}", .{ a, node.id, node.side });
// if (node.side == .North) linkNeighbor(nodes.items[node]);
if (node.side == .West) nodes.items[i].kind.And[0] = node.id;
if (node.side == .East) nodes.items[i].kind.And[1] = node.id;
for (neighbors.items) |neighbor, a| {
std.log.warn("\tNeighbor {}: [{}] {}", .{ a, neighbor.id, neighbor.side });
if (neighbor.side == .West) nodes.items[i].kind.And[0] = neighbor.id;
if (neighbor.side == .East) nodes.items[i].kind.And[1] = neighbor.id;
}
},
.Xor => {},
@ -555,7 +627,6 @@ fn findNeighbors(
nodes: []world.CircuitNode,
index: usize,
) !std.ArrayList(Neighbor) {
const Coord = world.Coordinate;
var visited = std.AutoHashMap(Coord, void).init(alloc);
defer visited.deinit();
@ -651,9 +722,7 @@ fn findNeighbors(
return neighbors;
}
const Dir = enum { North, West, East, South };
fn getInputDirection(coord: world.Coordinate, last_coord: world.Coordinate) Dir {
fn getInputDirection(coord: Coord, last_coord: Coord) Dir {
if (last_coord.eq(coord.add(.{ 0, -1 }))) {
return .North;
} else if (last_coord.eq(coord.add(.{ -1, 0 }))) {
@ -672,7 +741,7 @@ fn getLevel(levels: []world.Level, x: i8, y: i8) ?world.Level {
return null;
}
fn getNode(nodes: []world.CircuitNode, coord: world.Coordinate) ?world.NodeID {
fn getNode(nodes: []world.CircuitNode, coord: Coord) ?world.NodeID {
for (nodes) |node, i| {
if (node.coord.eq(coord)) return @intCast(world.NodeID, i);
}