|
@@ -0,0 +1,282 @@
|
|
|
+/**
|
|
|
+ * The code box class
|
|
|
+ */
|
|
|
+class CodeBox {
|
|
|
+ constructor() {
|
|
|
+ /**
|
|
|
+ * Possible vectors the pointer can move in
|
|
|
+ * @type {Object}
|
|
|
+ */
|
|
|
+ this.directions = {
|
|
|
+ NORTH: [-1, 0],
|
|
|
+ EAST: [ 0, 1],
|
|
|
+ SOUTH: [ 1, 0],
|
|
|
+ WEST: [ 0, -1],
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * The current vector of the pointer
|
|
|
+ * @type {int[]}
|
|
|
+ */
|
|
|
+ this.curr_direction = this.directions.EAST;
|
|
|
+ /**
|
|
|
+ * The Set of instructions to execute
|
|
|
+ *
|
|
|
+ * Either a 1 or 2-dimensional array
|
|
|
+ * @type {Array|Array[]}
|
|
|
+ */
|
|
|
+ this.box = [];
|
|
|
+ /**
|
|
|
+ * The coordinates of the currently executing instruction inside the code box
|
|
|
+ * @type {int[]}
|
|
|
+ */
|
|
|
+ this.pointer = [0,0];
|
|
|
+ /**
|
|
|
+ * Was the instruction last moving in the left direction
|
|
|
+ *
|
|
|
+ * Used by the {@link Fisherman}
|
|
|
+ * @type {boolean}
|
|
|
+ */
|
|
|
+ this.dirWasLeft = false;
|
|
|
+ /**
|
|
|
+ * Are we currently under the influence of the {@link Fisherman}
|
|
|
+ * @type {boolean}
|
|
|
+ */
|
|
|
+ this.onTheHook = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement C and .
|
|
|
+ */
|
|
|
+ SetPointer(x, y) {
|
|
|
+ this.pointer = [x, y];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement ^
|
|
|
+ *
|
|
|
+ * Changes the swim direction upward
|
|
|
+ */
|
|
|
+ MoveUp() {
|
|
|
+ this.curr_direction = this.directions.NORTH;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement >
|
|
|
+ *
|
|
|
+ * Changes the swim direction rightward
|
|
|
+ */
|
|
|
+ MoveRight() {
|
|
|
+ this.curr_direction = this.directions.EAST;
|
|
|
+ this.dirWasLeft = false;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement v
|
|
|
+ *
|
|
|
+ * Changes the swim direction downward
|
|
|
+ */
|
|
|
+ MoveDown() {
|
|
|
+ this.curr_direction = this.directions.SOUTH;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement <
|
|
|
+ *
|
|
|
+ * Changes the swim direction leftward
|
|
|
+ */
|
|
|
+ MoveLeft() {
|
|
|
+ this.curr_direction = this.directions.WEST;
|
|
|
+ this.dirWasLeft = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement /
|
|
|
+ *
|
|
|
+ * Reflects the swim direction depending on its starting value
|
|
|
+ */
|
|
|
+ ReflectForward() {
|
|
|
+ if (this.curr_direction == this.directions.NORTH) {
|
|
|
+ this.MoveRight();
|
|
|
+ }
|
|
|
+ else if (this.curr_direction == this.directions.EAST) {
|
|
|
+ this.MoveUp();
|
|
|
+ }
|
|
|
+ else if (this.curr_direction == this.directions.SOUTH) {
|
|
|
+ this.MoveLeft();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.MoveDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement \
|
|
|
+ *
|
|
|
+ * Reflects the swim direction depending on its starting value
|
|
|
+ */
|
|
|
+ ReflectBack() {
|
|
|
+ if (this.curr_direction == this.directions.NORTH) {
|
|
|
+ this.MoveLeft();
|
|
|
+ }
|
|
|
+ else if (this.curr_direction == this.directions.EAST) {
|
|
|
+ this.MoveDown();
|
|
|
+ }
|
|
|
+ else if (this.curr_direction == this.directions.SOUTH) {
|
|
|
+ this.MoveRight();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.MoveUp();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement |
|
|
|
+ *
|
|
|
+ * Swaps the horizontal swim direction to its opposite
|
|
|
+ */
|
|
|
+ HorizontalMirror() {
|
|
|
+ if (this.curr_direction == this.directions.EAST) {
|
|
|
+ this.MoveLeft();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.MoveRight();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement _
|
|
|
+ *
|
|
|
+ * Swaps the horizontal swim direction to its opposite
|
|
|
+ */
|
|
|
+ VerticalMirror() {
|
|
|
+ if (this.curr_direction == this.directions.NORTH) {
|
|
|
+ this.MoveDown();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.MoveUp();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement #
|
|
|
+ *
|
|
|
+ * A combination of the vertical and the horizontal mirror
|
|
|
+ */
|
|
|
+ OmniMirror() {
|
|
|
+ if (this.curr_direction[0]) {
|
|
|
+ this.VerticalMirror();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.HorizontalMirror();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement x
|
|
|
+ *
|
|
|
+ * Pseudo-randomly switches the swim direction
|
|
|
+ */
|
|
|
+ ShuffleDirection() {
|
|
|
+ this.curr_direction = Object.values(this.directions)[Math.floor(Math.random() * 4)];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement `
|
|
|
+ *
|
|
|
+ * Changes the swim direction based on the previous direction
|
|
|
+ * @see https://esolangs.org/wiki/Starfish#Fisherman
|
|
|
+ */
|
|
|
+ Fisherman() {
|
|
|
+ if (this.curr_direction[0]) {
|
|
|
+ if (this.dirWasLeft) {
|
|
|
+ this.MoveLeft();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.MoveRight();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (this.onTheHook) {
|
|
|
+ this.onTheHook = false;
|
|
|
+ this.MoveUp();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.onTheHook = true;
|
|
|
+ this.MoveDown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+/**
|
|
|
+ * The stack class
|
|
|
+ */
|
|
|
+class Stack {
|
|
|
+ constructor() {
|
|
|
+ /**
|
|
|
+ * The stack
|
|
|
+ * @type {int[]}
|
|
|
+ */
|
|
|
+ this.stack = [];
|
|
|
+ /**
|
|
|
+ * A single value saved off the stack
|
|
|
+ * @type {int}
|
|
|
+ */
|
|
|
+ this.register = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement }
|
|
|
+ *
|
|
|
+ * Shifts the entire stack leftward by one value
|
|
|
+ */
|
|
|
+ ShiftLeft() {
|
|
|
+ const temp = this.stack.shift();
|
|
|
+ this.stack.push(temp);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement {
|
|
|
+ *
|
|
|
+ * Shifts the entire stack rightward by one value
|
|
|
+ */
|
|
|
+ ShiftRight() {
|
|
|
+ const temp = this.stack.pop();
|
|
|
+ this.stack.unshift(temp);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implement $
|
|
|
+ *
|
|
|
+ * Swaps the top two values of the stack
|
|
|
+ */
|
|
|
+ SwapTwo() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement :
|
|
|
+ *
|
|
|
+ * Duplicates the element on the top of the stack
|
|
|
+ */
|
|
|
+ Duplicate() {
|
|
|
+ this.stack.push(this.stack[this.stack.length-1]);
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * Implements ~
|
|
|
+ *
|
|
|
+ * Removes the element on the top of the stack
|
|
|
+ */
|
|
|
+ Remove() {
|
|
|
+ this.stack.pop();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement r
|
|
|
+ *
|
|
|
+ * Reverses the entire stack
|
|
|
+ */
|
|
|
+ Reverse() {
|
|
|
+ this.stack.reverse();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Implement l
|
|
|
+ *
|
|
|
+ * Pushes the length of the stack onto the top of the stack
|
|
|
+ */
|
|
|
+ PushLength() {
|
|
|
+ this.stack.push(this.stack.length);
|
|
|
+ }
|
|
|
+}
|