From 5ce26d1016b864f1fb8af43bb9251d7b813a8a93 Mon Sep 17 00:00:00 2001 From: UMRnInside <30196401+UMRnInside@users.noreply.github.com> Date: Wed, 2 Nov 2022 16:30:06 +0800 Subject: [PATCH 1/3] LogicExecutor: fix `jump always` --- LogicExecutor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/LogicExecutor.js b/LogicExecutor.js index f6b8111..0b2c8ee 100644 --- a/LogicExecutor.js +++ b/LogicExecutor.js @@ -90,7 +90,8 @@ class LogicExecutor { case "greaterThan": return numberCmp ? (a > b ? 1 : 0) : null; case "greaterThanEq": return numberCmp ? (a >= b ? 1 : 0) : null; case "strictEqual": return numberCmp ? a === b : deepEqual(c, d); - + case "always": return true; // jump instruction used this + // TODO add arithmetic operations // REPLACE THIS ASAP case "shr": //AGDGSGDHSHD if(b<0) return this.doOp("shl",a,0-b); @@ -106,6 +107,8 @@ class LogicExecutor { ah = (Math.floor(a / 4294967296)>>>0).toString(2).slice(0-b); return parseInt(ah+al+sign.repeat(b),2); // I originally planned to put condition and logic ops here as well - but my sanity ran out. DO YOU SEE THESE BITSHIFTS? + // TODO: use JavaSctipt BigInt for bitwise operations + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt default: return null; break; From bf63fb24ba7f76c5dd1963a5774fb78619cd2b3d Mon Sep 17 00:00:00 2001 From: UMRnInside <30196401+UMRnInside@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:08:01 +0800 Subject: [PATCH 2/3] LogicExecutor: support more arithmetic operations --- LogicExecutor.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/LogicExecutor.js b/LogicExecutor.js index 0b2c8ee..e9da6d4 100644 --- a/LogicExecutor.js +++ b/LogicExecutor.js @@ -1,5 +1,9 @@ // Preface: Written for Chrome/Firefox/Safari/Terminal (Node JS) // Fuck IE. All my homies hate IE. + +// Mindustry Logic uses Degree Measure +// while most programming languages use Radian Measure +const deg2rad = Math.PI / 180.0; class LogicExecutor { maxInstructions = 1000; maxGraphicsBuffer = 256; @@ -91,7 +95,28 @@ class LogicExecutor { case "greaterThanEq": return numberCmp ? (a >= b ? 1 : 0) : null; case "strictEqual": return numberCmp ? a === b : deepEqual(c, d); case "always": return true; // jump instruction used this - // TODO add arithmetic operations + // Compare + case "min": return numberCmp ? Math.min(a, b) : null; + case "max": return numberCmp ? Math.max(a, b) : null; + // BEGIN arithmetic operations + case "abs": return Math.abs(a); + case "ceil": return Math.ceil(a); + case "floor": return Math.floor(a); + case "log": return Math.log(a); + case "log10": return Math.log(a) / Math.log(10); + case "rand": return Math.random() * a; + // Math.atan2(y, x) + case "angle": return numberCmp ? Math.atan2(b, a) / deg2rad : null; + case "len": return numberCmp ? Math.hypot(a, b) : null; + case "sin": return Math.sin(a * deg2rad); + case "cos": return Math.cos(a * deg2rad); + case "tan": return Math.tan(a * deg2rad); + case "asin": return Math.asin(a) / deg2rad; + case "acos": return Math.acos(a) / deg2rad; + case "atan": return Math.atan(a) / deg2rad; + // TODO: op noise + // END arithmetic operations + // REPLACE THIS ASAP case "shr": //AGDGSGDHSHD if(b<0) return this.doOp("shl",a,0-b); From 9af83270bda6ce6199928fc1246b35617240d3c6 Mon Sep 17 00:00:00 2001 From: UMRnInside <30196401+UMRnInside@users.noreply.github.com> Date: Wed, 2 Nov 2022 17:30:55 +0800 Subject: [PATCH 3/3] LogicExecutor: bitwise operations --- LogicExecutor.js | 53 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/LogicExecutor.js b/LogicExecutor.js index e9da6d4..7137ac8 100644 --- a/LogicExecutor.js +++ b/LogicExecutor.js @@ -4,6 +4,8 @@ // Mindustry Logic uses Degree Measure // while most programming languages use Radian Measure const deg2rad = Math.PI / 180.0; +const uint64_max = BigInt("0xffffffffffffffff"); + class LogicExecutor { maxInstructions = 1000; maxGraphicsBuffer = 256; @@ -77,7 +79,7 @@ class LogicExecutor { let a = parseFloat(this.getVar(c)); let b = parseFloat(this.getVar(d)); let numberCmp = isFinite(a) && isFinite(b); - let sign, ah, al; // do not implement + let bigA, bigB, result; switch(operator) { case "add": return numberCmp ? a + b : null; // fuck you no "a" + "b" case "sub": return numberCmp ? a - b : null; @@ -117,23 +119,42 @@ class LogicExecutor { // TODO: op noise // END arithmetic operations - // REPLACE THIS ASAP - case "shr": //AGDGSGDHSHD - if(b<0) return this.doOp("shl",a,0-b); - sign = a < 0 ? -1 : 1; - al = (a>>>b).toString(2); - ah = (Math.floor(a / 4294967296)>>>0).toString(2); - ah = ah.slice(1); - return parseInt(ah+al,2); + case "shr": + // just in case + bigA = BigInt(Math.floor(a)); + bigB = BigInt(Math.floor(b)); + result = BigInt.asIntN(64, bigA >> bigB); + // Yes, that's how Anuke does it, I guess + return parseInt(result.toString()); case "shl": - if(b<0) return this.doOp("shr",a,0-b); - sign = a < 0 ? "1" : "0"; - al = (a>>>0).toString(2); - ah = (Math.floor(a / 4294967296)>>>0).toString(2).slice(0-b); - return parseInt(ah+al+sign.repeat(b),2); + bigA = BigInt(Math.floor(a)); + bigB = BigInt(Math.floor(b)); + result = BigInt.asIntN(64, bigA << bigB); + return parseInt(result.toString()); + // TODO: code smell + case "and": + bigA = BigInt(Math.floor(a)); + bigB = BigInt(Math.floor(b)); + result = BigInt.asIntN(64, bigA & bigB); + return parseInt(result.toString()); + case "or": + bigA = BigInt(Math.floor(a)); + bigB = BigInt(Math.floor(b)); + result = BigInt.asIntN(64, bigA | bigB); + return parseInt(result.toString()); + case "xor": + bigA = BigInt(Math.floor(a)); + bigB = BigInt(Math.floor(b)); + result = BigInt.asIntN(64, bigA ^ bigB); + return parseInt(result.toString()); + // Oops, this is inexact + case "not": + bigA = BigInt(Math.floor(a)); + bigB = BigInt(Math.floor(b)); + result = BigInt.asIntN(64, bigA ^ uint64_max); + return parseInt(result.toString()); // I originally planned to put condition and logic ops here as well - but my sanity ran out. DO YOU SEE THESE BITSHIFTS? - // TODO: use JavaSctipt BigInt for bitwise operations - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt + // NO, I (UMRnInside) will use JavaSctipt BigInt for bitwise operations instead default: return null; break;