1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2026-02-12 19:09:21 +00:00

rewrite cloneAndStackWith in binary form

This commit is contained in:
Dimava 2020-06-13 20:03:29 +03:00
parent 2f66381009
commit 439f2a7c3d

View File

@ -25,6 +25,13 @@ const logger = createLogger("shape_definition");
* @typedef {[ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?]} ShapeLayer * @typedef {[ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?, ShapeLayerItem?]} ShapeLayer
*/ */
/**
** Order is 0b1000, 0b0100, 0b0010, 0b0001, upper layers are << 4
* @typedef {number} FormStack
*/
const arrayQuadrantIndexToOffset = [ const arrayQuadrantIndexToOffset = [
new Vector(1, -1), // tr new Vector(1, -1), // tr
new Vector(1, 1), // br new Vector(1, 1), // br
@ -193,6 +200,14 @@ export class ShapeDefinition extends BasicSerializableObject {
return id; return id;
} }
/**
* Returns a filled form of shape
* @returns {FormStack}
*/
getForm() {
return this.layers.reduceRight((v, [q1, q2, q3, q4]) => (v << 4) | (!!q1 && 0b1000) | (!!q2 && 0b0100) | (!!q3 && 0b0010) | (!!q4 && 0b0001), 0);
}
/** /**
* Draws the shape definition * Draws the shape definition
* @param {number} x * @param {number} x
@ -418,50 +433,43 @@ export class ShapeDefinition extends BasicSerializableObject {
assert(false, "Can not stack entirely empty definition"); assert(false, "Can not stack entirely empty definition");
} }
// Put layer for layer on top let form = this.getForm();
for (let i = 0; i < definition.layers.length; ++i) { const dForm = definition.getForm();
const layerToAdd = definition.layers[i];
// On which layer we can merge this upper layer if ((form & dForm) == 0) {
let mergeOnLayerIndex = null; // merge
for (let i = 0; i < newLayers.length && i < definition.layers.length; ++i) {
// Go from top to bottom and check if there is anything intercepting it for (let q = 0; q < 4; q++) {
for (let k = newLayers.length - 1; k >= 0; --k) { newLayers[i][q] = newLayers[i][q] || definition.layers[i][q];
const lowerLayer = newLayers[k];
let canMerge = true;
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
const upperItem = layerToAdd[quadrantIndex];
const lowerItem = lowerLayer[quadrantIndex];
if (upperItem && lowerItem) {
// so, we can't merge it because two items conflict
canMerge = false;
break;
}
}
// If we can merge it, store it - since we go from top to bottom
// we can simply override it
if (canMerge) {
mergeOnLayerIndex = k;
} }
} }
for (let i = newLayers.length; i < definition.layers.length; ++i) {
if (mergeOnLayerIndex !== null) { newLayers.push(definition.layers[i].slice());
// Simply merge using an OR mask
for (let quadrantIndex = 0; quadrantIndex < 4; ++quadrantIndex) {
newLayers[mergeOnLayerIndex][quadrantIndex] =
newLayers[mergeOnLayerIndex][quadrantIndex] || layerToAdd[quadrantIndex];
}
} else {
// Add new layer
newLayers.push(layerToAdd);
} }
newLayers.splice(4);
return new ShapeDefinition({ layers: newLayers });
} }
newLayers.splice(4); // otherwise stack, layer by layer
for (let i = 0; i < definition.layers.length; ++i) {
let layerForm = (dForm & (0b1111 << (4 * i))) >> (4 * i);
let highestOverlay = 7;
while ( ((layerForm << (4 * highestOverlay)) & form) == 0 && highestOverlay >= 0 ) {
highestOverlay--;
}
// highestOverlay is topmost unmergeable layer, so go up 1 more
const mergeTagret = highestOverlay + 1;
form = form | (layerForm << (4 * mergeTagret));
if (newLayers.length <= mergeTagret) {
newLayers.push(definition.layers[i].slice());
continue;
}
for (let q = 0; q < 4; q++) {
newLayers[mergeTagret][q] = newLayers[mergeTagret][q] || definition.layers[i][q];
}
}
newLayers.splice(4);
return new ShapeDefinition({ layers: newLayers }); return new ShapeDefinition({ layers: newLayers });
} }