@logic-pad/core 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/logic-core.global.d.ts +4 -1
- package/dist/data/solver/backtrack/backtrackSolver.js +1 -1
- package/dist/data/solver/backtrack/symbols/directionLinker.d.ts +2 -0
- package/dist/data/solver/backtrack/symbols/directionLinker.js +95 -14
- package/dist/data/solver/backtrack/symbols/lotus.d.ts +3 -1
- package/dist/data/solver/backtrack/symbols/lotus.js +24 -0
- package/dist/data/symbols/directionLinkerSymbol.d.ts +0 -1
- package/dist/data/symbols/directionLinkerSymbol.js +77 -94
- package/dist/data/symbols/lotusSymbol.js +18 -1
- package/package.json +1 -1
|
@@ -2011,7 +2011,6 @@ declare global {
|
|
|
2011
2011
|
get explanation(): string;
|
|
2012
2012
|
get configs(): readonly AnyConfig[] | null;
|
|
2013
2013
|
createExampleGrid(): GridData;
|
|
2014
|
-
private getColor;
|
|
2015
2014
|
private deltaCoordinate;
|
|
2016
2015
|
validateSymbol(grid: GridData): State;
|
|
2017
2016
|
copyWith({ x, y }: { x?: number; y?: number }): this;
|
|
@@ -2020,6 +2019,8 @@ declare global {
|
|
|
2020
2019
|
export declare abstract class DirectionLinkerBTModule extends BTModule {
|
|
2021
2020
|
instr: DirectionLinkerSymbol;
|
|
2022
2021
|
constructor(instr: DirectionLinkerSymbol);
|
|
2022
|
+
private initialPositions;
|
|
2023
|
+
private getInitialPositions;
|
|
2023
2024
|
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
2024
2025
|
protected abstract movePos(
|
|
2025
2026
|
grid: BTGridData,
|
|
@@ -2127,6 +2128,8 @@ declare global {
|
|
|
2127
2128
|
x: number,
|
|
2128
2129
|
y: number
|
|
2129
2130
|
): Position$1 | null;
|
|
2131
|
+
private getTileSafe;
|
|
2132
|
+
checkGlobal(grid: BTGridData): false | CheckResult;
|
|
2130
2133
|
}
|
|
2131
2134
|
export declare class MinesweeperSymbol extends NumberSymbol {
|
|
2132
2135
|
private static readonly CONFIGS;
|
|
@@ -4,6 +4,8 @@ import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
|
4
4
|
export default abstract class DirectionLinkerBTModule extends BTModule {
|
|
5
5
|
instr: DirectionLinkerSymbol;
|
|
6
6
|
constructor(instr: DirectionLinkerSymbol);
|
|
7
|
+
private initialPositions;
|
|
8
|
+
private getInitialPositions;
|
|
7
9
|
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
8
10
|
protected abstract movePos(grid: BTGridData, x: number, y: number): Position | null;
|
|
9
11
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BTModule, { BTTile, IntArray2D,
|
|
1
|
+
import BTModule, { BTTile, IntArray2D, } from '../data.js';
|
|
2
2
|
export default class DirectionLinkerBTModule extends BTModule {
|
|
3
3
|
constructor(instr) {
|
|
4
4
|
super();
|
|
@@ -8,31 +8,108 @@ export default class DirectionLinkerBTModule extends BTModule {
|
|
|
8
8
|
writable: true,
|
|
9
9
|
value: void 0
|
|
10
10
|
});
|
|
11
|
+
Object.defineProperty(this, "initialPositions", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
value: null
|
|
16
|
+
});
|
|
11
17
|
this.instr = instr;
|
|
12
18
|
}
|
|
19
|
+
getInitialPositions() {
|
|
20
|
+
if (this.instr.x % 1 !== 0 && this.instr.y % 1 !== 0)
|
|
21
|
+
return [
|
|
22
|
+
{ x: Math.floor(this.instr.x), y: Math.floor(this.instr.y) },
|
|
23
|
+
{ x: Math.ceil(this.instr.x), y: Math.ceil(this.instr.y) },
|
|
24
|
+
{ x: Math.floor(this.instr.x), y: Math.ceil(this.instr.y) },
|
|
25
|
+
{ x: Math.ceil(this.instr.x), y: Math.floor(this.instr.y) },
|
|
26
|
+
];
|
|
27
|
+
else if (this.instr.x % 1 !== 0)
|
|
28
|
+
return [
|
|
29
|
+
{ x: Math.floor(this.instr.x), y: this.instr.y },
|
|
30
|
+
{ x: Math.ceil(this.instr.x), y: this.instr.y },
|
|
31
|
+
];
|
|
32
|
+
else if (this.instr.y % 1 !== 0)
|
|
33
|
+
return [
|
|
34
|
+
{ x: this.instr.x, y: Math.floor(this.instr.y) },
|
|
35
|
+
{ x: this.instr.x, y: Math.ceil(this.instr.y) },
|
|
36
|
+
];
|
|
37
|
+
else
|
|
38
|
+
return [{ x: this.instr.x, y: this.instr.y }];
|
|
39
|
+
}
|
|
13
40
|
checkGlobal(grid) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const tile = grid.getTile(thisX, thisY);
|
|
17
|
-
if (tile === BTTile.Empty)
|
|
18
|
-
return createOneTileResult(grid, { x: thisX, y: thisY });
|
|
41
|
+
if (this.initialPositions === null)
|
|
42
|
+
this.initialPositions = this.getInitialPositions();
|
|
19
43
|
const tilesNeedCheck = IntArray2D.create(grid.width, grid.height);
|
|
20
44
|
const ratings = [];
|
|
21
|
-
|
|
45
|
+
let checkable = false;
|
|
46
|
+
for (const pos of this.initialPositions) {
|
|
47
|
+
const tile = grid.isInBound(pos.x, pos.y)
|
|
48
|
+
? grid.getTile(pos.x, pos.y)
|
|
49
|
+
: BTTile.NonExist;
|
|
50
|
+
if (tile === BTTile.Empty) {
|
|
51
|
+
const oppoPos = this.movePos(grid, pos.x, pos.y);
|
|
52
|
+
if (oppoPos === null ||
|
|
53
|
+
grid.getTile(oppoPos.x, oppoPos.y) === BTTile.NonExist)
|
|
54
|
+
return false;
|
|
55
|
+
else {
|
|
56
|
+
tilesNeedCheck.set(pos.x, pos.y, 1);
|
|
57
|
+
ratings.push({ pos, score: 1 });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (tile === BTTile.NonExist) {
|
|
61
|
+
const oppoPos = this.movePos(grid, pos.x, pos.y);
|
|
62
|
+
if (oppoPos !== null &&
|
|
63
|
+
grid.getTile(oppoPos.x, oppoPos.y) !== BTTile.NonExist) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const oppoPos = this.movePos(grid, pos.x, pos.y);
|
|
69
|
+
if (oppoPos !== null) {
|
|
70
|
+
const oppoTile = grid.getTile(oppoPos.x, oppoPos.y);
|
|
71
|
+
if (oppoTile === BTTile.Empty) {
|
|
72
|
+
tilesNeedCheck.set(pos.x, pos.y, 1);
|
|
73
|
+
ratings.push({ pos, score: 1 });
|
|
74
|
+
}
|
|
75
|
+
else if (oppoTile === BTTile.NonExist)
|
|
76
|
+
return false;
|
|
77
|
+
else
|
|
78
|
+
checkable = true;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!checkable) {
|
|
86
|
+
return { tilesNeedCheck, ratings };
|
|
87
|
+
}
|
|
88
|
+
const queue = this.initialPositions
|
|
89
|
+
.filter(pos => grid.isInBound(pos.x, pos.y) &&
|
|
90
|
+
grid.getTile(pos.x, pos.y) !== BTTile.NonExist)
|
|
91
|
+
.map(pos => {
|
|
92
|
+
const oppoPos = this.movePos(grid, pos.x, pos.y);
|
|
93
|
+
return {
|
|
94
|
+
pos,
|
|
95
|
+
color: grid.getTile(pos.x, pos.y),
|
|
96
|
+
oppoColor: grid.getTile(oppoPos.x, oppoPos.y),
|
|
97
|
+
};
|
|
98
|
+
});
|
|
22
99
|
const visited = IntArray2D.create(grid.width, grid.height);
|
|
23
100
|
// Visit all connected tiles
|
|
24
101
|
while (queue.length > 0) {
|
|
25
102
|
const curPos = queue.pop();
|
|
26
|
-
if (visited.get(curPos.x, curPos.y))
|
|
103
|
+
if (visited.get(curPos.pos.x, curPos.pos.y))
|
|
27
104
|
continue;
|
|
28
|
-
visited.set(curPos.x, curPos.y, 1);
|
|
29
|
-
const oppoPos = this.movePos(grid, curPos.x, curPos.y);
|
|
105
|
+
visited.set(curPos.pos.x, curPos.pos.y, 1);
|
|
106
|
+
const oppoPos = this.movePos(grid, curPos.pos.x, curPos.pos.y);
|
|
30
107
|
if (oppoPos === null)
|
|
31
108
|
return false;
|
|
32
109
|
const oppoTile = grid.getTile(oppoPos.x, oppoPos.y);
|
|
33
|
-
if (!(oppoTile === BTTile.Empty || oppoTile ===
|
|
110
|
+
if (!(oppoTile === BTTile.Empty || oppoTile === curPos.oppoColor))
|
|
34
111
|
return false;
|
|
35
|
-
for (const edge of grid.getEdges(curPos)) {
|
|
112
|
+
for (const edge of grid.getEdges(curPos.pos)) {
|
|
36
113
|
if (visited.get(edge.x, edge.y))
|
|
37
114
|
continue;
|
|
38
115
|
const edgeTile = grid.getTile(edge.x, edge.y);
|
|
@@ -40,8 +117,12 @@ export default class DirectionLinkerBTModule extends BTModule {
|
|
|
40
117
|
tilesNeedCheck.set(edge.x, edge.y, 1);
|
|
41
118
|
ratings.push({ pos: edge, score: 1 });
|
|
42
119
|
}
|
|
43
|
-
else if (edgeTile ===
|
|
44
|
-
queue.push(
|
|
120
|
+
else if (edgeTile === curPos.color) {
|
|
121
|
+
queue.push({
|
|
122
|
+
pos: edge,
|
|
123
|
+
color: curPos.color,
|
|
124
|
+
oppoColor: curPos.oppoColor,
|
|
125
|
+
});
|
|
45
126
|
}
|
|
46
127
|
}
|
|
47
128
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { Position } from '../../../primitives.js';
|
|
2
2
|
import LotusSymbol from '../../../symbols/lotusSymbol.js';
|
|
3
|
-
import { BTGridData } from '../data.js';
|
|
3
|
+
import { BTGridData, CheckResult } from '../data.js';
|
|
4
4
|
import DirectionLinkerBTModule from './directionLinker.js';
|
|
5
5
|
export default class LotusBTModule extends DirectionLinkerBTModule {
|
|
6
6
|
instr: LotusSymbol;
|
|
7
7
|
constructor(instr: LotusSymbol);
|
|
8
8
|
protected movePos(grid: BTGridData, x: number, y: number): Position | null;
|
|
9
|
+
private getTileSafe;
|
|
10
|
+
checkGlobal(grid: BTGridData): false | CheckResult;
|
|
9
11
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Orientation } from '../../../primitives.js';
|
|
2
|
+
import { BTTile } from '../data.js';
|
|
2
3
|
import DirectionLinkerBTModule from './directionLinker.js';
|
|
3
4
|
export default class LotusBTModule extends DirectionLinkerBTModule {
|
|
4
5
|
constructor(instr) {
|
|
@@ -33,4 +34,27 @@ export default class LotusBTModule extends DirectionLinkerBTModule {
|
|
|
33
34
|
}
|
|
34
35
|
return grid.isInBound(pos.x, pos.y) ? pos : null;
|
|
35
36
|
}
|
|
37
|
+
getTileSafe(grid, x, y) {
|
|
38
|
+
return grid.isInBound(x, y) ? grid.getTile(x, y) : BTTile.NonExist;
|
|
39
|
+
}
|
|
40
|
+
checkGlobal(grid) {
|
|
41
|
+
if (this.instr.orientation === Orientation.DownLeft ||
|
|
42
|
+
this.instr.orientation === Orientation.DownRight ||
|
|
43
|
+
this.instr.orientation === Orientation.UpLeft ||
|
|
44
|
+
this.instr.orientation === Orientation.UpRight) {
|
|
45
|
+
if (this.instr.x % 1 === 0 || this.instr.y % 1 === 0)
|
|
46
|
+
if (this.instr.x % 1 !== 0 || this.instr.y % 1 !== 0) {
|
|
47
|
+
if (this.getTileSafe(grid, Math.floor(this.instr.x), Math.floor(this.instr.y)) === BTTile.NonExist &&
|
|
48
|
+
this.getTileSafe(grid, Math.ceil(this.instr.x), Math.ceil(this.instr.y)) === BTTile.NonExist &&
|
|
49
|
+
this.getTileSafe(grid, Math.floor(this.instr.x), Math.ceil(this.instr.y)) === BTTile.NonExist &&
|
|
50
|
+
this.getTileSafe(grid, Math.ceil(this.instr.x), Math.floor(this.instr.y)) === BTTile.NonExist) {
|
|
51
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return super.checkGlobal(grid);
|
|
59
|
+
}
|
|
36
60
|
}
|
|
@@ -24,7 +24,6 @@ export default class DirectionLinkerSymbol extends Symbol {
|
|
|
24
24
|
get explanation(): string;
|
|
25
25
|
get configs(): readonly AnyConfig[] | null;
|
|
26
26
|
createExampleGrid(): GridData;
|
|
27
|
-
private getColor;
|
|
28
27
|
private deltaCoordinate;
|
|
29
28
|
validateSymbol(grid: GridData): State;
|
|
30
29
|
copyWith({ x, y }: {
|
|
@@ -2,6 +2,20 @@ import { ConfigType } from '../config.js';
|
|
|
2
2
|
import GridData from '../grid.js';
|
|
3
3
|
import { Color, Direction, State } from '../primitives.js';
|
|
4
4
|
import Symbol from './symbol.js';
|
|
5
|
+
function getColor(c, grid) {
|
|
6
|
+
if (!grid.isPositionValid(c.x, c.y) || !grid.getTile(c.x, c.y).exists) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return grid.getTile(c.x, c.y).color;
|
|
10
|
+
}
|
|
11
|
+
function makeTurtle(pos1, pos2, grid) {
|
|
12
|
+
return {
|
|
13
|
+
pos1,
|
|
14
|
+
color1: getColor(pos1, grid),
|
|
15
|
+
pos2,
|
|
16
|
+
color2: getColor(pos2, grid),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
5
19
|
class DirectionLinkerSymbol extends Symbol {
|
|
6
20
|
/**
|
|
7
21
|
* **Darts count opposite color cells in that direction**
|
|
@@ -51,12 +65,6 @@ class DirectionLinkerSymbol extends Symbol {
|
|
|
51
65
|
createExampleGrid() {
|
|
52
66
|
return DirectionLinkerSymbol.EXAMPLE_GRID;
|
|
53
67
|
}
|
|
54
|
-
getColor(c, grid) {
|
|
55
|
-
if (!grid.isPositionValid(c.x, c.y) || !grid.getTile(c.x, c.y).exists) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
return grid.getTile(c.x, c.y).color;
|
|
59
|
-
}
|
|
60
68
|
deltaCoordinate(c, direction) {
|
|
61
69
|
return {
|
|
62
70
|
x: c.x + DirectionLinkerSymbol.directionDeltas[direction].dx,
|
|
@@ -73,49 +81,56 @@ class DirectionLinkerSymbol extends Symbol {
|
|
|
73
81
|
// If the color of both are the opposite of the turtle, the turtle doesn't fire any other turtle
|
|
74
82
|
// If no turtle remains, go to final state
|
|
75
83
|
// Final state is State.Satisfied if no gray cell is found, State.Incomplete otherwise
|
|
76
|
-
|
|
77
|
-
if (
|
|
84
|
+
let checkedCouples = this.getInitialCheckedCouples(this.x, this.y, grid);
|
|
85
|
+
if (checkedCouples.some(({ color1, color2 }) => (color1 === null && color2 !== null) ||
|
|
86
|
+
(color1 !== null && color2 === null))) {
|
|
87
|
+
return State.Error;
|
|
88
|
+
}
|
|
89
|
+
if (checkedCouples.some(({ color1, color2 }) => color1 === Color.Gray || color2 === Color.Gray)) {
|
|
78
90
|
return State.Incomplete;
|
|
79
91
|
}
|
|
80
|
-
|
|
81
|
-
const queue = checkedCouples.
|
|
82
|
-
{ ...p1 },
|
|
83
|
-
{ ...p2 },
|
|
84
|
-
]);
|
|
92
|
+
checkedCouples = checkedCouples.filter(({ color1, color2 }) => color1 !== null && color2 !== null);
|
|
93
|
+
const queue = checkedCouples.slice();
|
|
85
94
|
let grayFound = false;
|
|
86
95
|
while (queue.length > 0) {
|
|
87
96
|
const turtle = queue.shift();
|
|
88
|
-
const
|
|
89
|
-
const color1 =
|
|
90
|
-
const color2 =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
colorSet.delete(null);
|
|
97
|
+
const { pos1, pos2, color1: baseColor1, color2: baseColor2 } = turtle;
|
|
98
|
+
const color1 = getColor(pos1, grid);
|
|
99
|
+
const color2 = getColor(pos2, grid);
|
|
100
|
+
if (color1 === Color.Gray || color2 === Color.Gray) {
|
|
101
|
+
grayFound = true;
|
|
94
102
|
}
|
|
95
|
-
if (
|
|
96
|
-
|
|
103
|
+
else if (color1 === null || color2 === null) {
|
|
104
|
+
if ((color1 === null && color2 === baseColor2) ||
|
|
105
|
+
(color2 === null && color1 === baseColor1)) {
|
|
106
|
+
return State.Error;
|
|
107
|
+
}
|
|
97
108
|
}
|
|
98
|
-
if (
|
|
99
|
-
|
|
109
|
+
else if (color1 !== baseColor1 || color2 !== baseColor2) {
|
|
110
|
+
if (color1 === baseColor1 || color2 === baseColor2) {
|
|
111
|
+
return State.Error;
|
|
112
|
+
}
|
|
100
113
|
}
|
|
101
|
-
if (color1 ===
|
|
114
|
+
if (color1 === baseColor1) {
|
|
102
115
|
const directions = Object.keys(this.linkedDirections);
|
|
103
116
|
for (const direction of directions) {
|
|
104
|
-
const newTurtle =
|
|
105
|
-
this.deltaCoordinate(
|
|
106
|
-
this.deltaCoordinate(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
const newTurtle = {
|
|
118
|
+
pos1: this.deltaCoordinate(pos1, direction),
|
|
119
|
+
pos2: this.deltaCoordinate(pos2, this.linkedDirections[direction]),
|
|
120
|
+
color1: baseColor1,
|
|
121
|
+
color2: baseColor2,
|
|
122
|
+
};
|
|
123
|
+
if (checkedCouples.some(({ pos1, pos2 }) => pos1.x === newTurtle.pos1.x &&
|
|
124
|
+
pos1.y === newTurtle.pos1.y &&
|
|
125
|
+
pos2.x === newTurtle.pos2.x &&
|
|
126
|
+
pos2.y === newTurtle.pos2.y) ||
|
|
127
|
+
(pos1.x === newTurtle.pos2.x &&
|
|
128
|
+
pos1.y === newTurtle.pos2.y &&
|
|
129
|
+
pos2.x === newTurtle.pos1.x &&
|
|
130
|
+
pos2.y === newTurtle.pos1.y)) {
|
|
116
131
|
continue;
|
|
117
132
|
}
|
|
118
|
-
checkedCouples.push(
|
|
133
|
+
checkedCouples.push(newTurtle);
|
|
119
134
|
queue.push(newTurtle);
|
|
120
135
|
}
|
|
121
136
|
}
|
|
@@ -125,73 +140,50 @@ class DirectionLinkerSymbol extends Symbol {
|
|
|
125
140
|
copyWith({ x, y }) {
|
|
126
141
|
return new DirectionLinkerSymbol(x ?? this.x, y ?? this.y);
|
|
127
142
|
}
|
|
128
|
-
getInitialCheckedCouples(x, y) {
|
|
143
|
+
getInitialCheckedCouples(x, y, grid) {
|
|
129
144
|
// 1x1
|
|
130
145
|
if (x % 1 === 0 && y % 1 === 0) {
|
|
131
|
-
return [
|
|
132
|
-
[
|
|
133
|
-
{ x, y },
|
|
134
|
-
{ x, y },
|
|
135
|
-
],
|
|
136
|
-
];
|
|
146
|
+
return [makeTurtle({ x, y }, { x, y }, grid)];
|
|
137
147
|
}
|
|
138
148
|
// 1x2
|
|
139
149
|
if (x % 1 === 0) {
|
|
140
150
|
return [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
: 0.5),
|
|
150
|
-
},
|
|
151
|
-
],
|
|
151
|
+
makeTurtle({ x, y: y - 0.5 }, {
|
|
152
|
+
x,
|
|
153
|
+
y: y +
|
|
154
|
+
(this.linkedDirections[Direction.Up] === Direction.Up &&
|
|
155
|
+
this.linkedDirections[Direction.Down] === Direction.Down
|
|
156
|
+
? -0.5
|
|
157
|
+
: 0.5),
|
|
158
|
+
}, grid),
|
|
152
159
|
];
|
|
153
160
|
}
|
|
154
161
|
// 2x1
|
|
155
162
|
if (y % 1 === 0) {
|
|
156
163
|
return [
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
y,
|
|
166
|
-
},
|
|
167
|
-
],
|
|
164
|
+
makeTurtle({ x: x - 0.5, y }, {
|
|
165
|
+
x: x +
|
|
166
|
+
(this.linkedDirections[Direction.Left] === Direction.Left &&
|
|
167
|
+
this.linkedDirections[Direction.Right] === Direction.Right
|
|
168
|
+
? -0.5
|
|
169
|
+
: 0.5),
|
|
170
|
+
y,
|
|
171
|
+
}, grid),
|
|
168
172
|
];
|
|
169
173
|
}
|
|
170
174
|
// 2x2
|
|
171
175
|
if (this.linkedDirections[Direction.Left] === Direction.Left &&
|
|
172
176
|
this.linkedDirections[Direction.Right] === Direction.Right) {
|
|
173
177
|
return [
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
{ x: x - 0.5, y: y + 0.5 },
|
|
177
|
-
],
|
|
178
|
-
[
|
|
179
|
-
{ x: x + 0.5, y: y - 0.5 },
|
|
180
|
-
{ x: x + 0.5, y: y + 0.5 },
|
|
181
|
-
],
|
|
178
|
+
makeTurtle({ x: x - 0.5, y: y - 0.5 }, { x: x - 0.5, y: y + 0.5 }, grid),
|
|
179
|
+
makeTurtle({ x: x + 0.5, y: y - 0.5 }, { x: x + 0.5, y: y + 0.5 }, grid),
|
|
182
180
|
];
|
|
183
181
|
}
|
|
184
182
|
if (this.linkedDirections[Direction.Up] === Direction.Up &&
|
|
185
183
|
this.linkedDirections[Direction.Down] === Direction.Down) {
|
|
186
184
|
return [
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
{ x: x + 0.5, y: y - 0.5 },
|
|
190
|
-
],
|
|
191
|
-
[
|
|
192
|
-
{ x: x - 0.5, y: y + 0.5 },
|
|
193
|
-
{ x: x + 0.5, y: y + 0.5 },
|
|
194
|
-
],
|
|
185
|
+
makeTurtle({ x: x - 0.5, y: y - 0.5 }, { x: x + 0.5, y: y - 0.5 }, grid),
|
|
186
|
+
makeTurtle({ x: x - 0.5, y: y + 0.5 }, { x: x + 0.5, y: y + 0.5 }, grid),
|
|
195
187
|
];
|
|
196
188
|
}
|
|
197
189
|
else if ((this.linkedDirections[Direction.Up] === Direction.Left &&
|
|
@@ -199,21 +191,12 @@ class DirectionLinkerSymbol extends Symbol {
|
|
|
199
191
|
(this.linkedDirections[Direction.Up] === Direction.Right &&
|
|
200
192
|
this.linkedDirections[Direction.Right] === Direction.Up)) {
|
|
201
193
|
return [
|
|
202
|
-
|
|
203
|
-
{ x: x - 0.5, y: y - 0.5 },
|
|
204
|
-
{ x: x - 0.5, y: y - 0.5 },
|
|
205
|
-
],
|
|
194
|
+
makeTurtle({ x: x - 0.5, y: y - 0.5 }, { x: x - 0.5, y: y - 0.5 }, grid),
|
|
206
195
|
];
|
|
207
196
|
}
|
|
208
197
|
return [
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
{ x: x + 0.5, y: y + 0.5 },
|
|
212
|
-
],
|
|
213
|
-
[
|
|
214
|
-
{ x: x - 0.5, y: y + 0.5 },
|
|
215
|
-
{ x: x + 0.5, y: y - 0.5 },
|
|
216
|
-
],
|
|
198
|
+
makeTurtle({ x: x - 0.5, y: y - 0.5 }, { x: x + 0.5, y: y + 0.5 }, grid),
|
|
199
|
+
makeTurtle({ x: x - 0.5, y: y + 0.5 }, { x: x + 0.5, y: y - 0.5 }, grid),
|
|
217
200
|
];
|
|
218
201
|
}
|
|
219
202
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigType } from '../config.js';
|
|
2
2
|
import GridData from '../grid.js';
|
|
3
|
-
import { Direction, Orientation } from '../primitives.js';
|
|
3
|
+
import { Direction, Orientation, State } from '../primitives.js';
|
|
4
4
|
import DirectionLinkerSymbol from './directionLinkerSymbol.js';
|
|
5
5
|
class LotusSymbol extends DirectionLinkerSymbol {
|
|
6
6
|
/**
|
|
@@ -67,6 +67,23 @@ class LotusSymbol extends DirectionLinkerSymbol {
|
|
|
67
67
|
return Object.freeze(GridData.create(['wwbww', 'bwbwb', 'bwwwb', 'bwwwb']).addSymbol(new LotusSymbol(2, 2, Orientation.Up)));
|
|
68
68
|
}
|
|
69
69
|
validateSymbol(grid) {
|
|
70
|
+
if (this.orientation === Orientation.DownLeft ||
|
|
71
|
+
this.orientation === Orientation.DownRight ||
|
|
72
|
+
this.orientation === Orientation.UpLeft ||
|
|
73
|
+
this.orientation === Orientation.UpRight) {
|
|
74
|
+
if (this.x % 1 === 0 || this.y % 1 === 0)
|
|
75
|
+
if (this.x % 1 !== 0 || this.y % 1 !== 0) {
|
|
76
|
+
if (!grid.getTile(Math.floor(this.x), Math.floor(this.y)).exists &&
|
|
77
|
+
!grid.getTile(Math.ceil(this.x), Math.ceil(this.y)).exists &&
|
|
78
|
+
!grid.getTile(Math.floor(this.x), Math.ceil(this.y)).exists &&
|
|
79
|
+
!grid.getTile(Math.ceil(this.x), Math.floor(this.y)).exists) {
|
|
80
|
+
return State.Satisfied;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
return State.Error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
70
87
|
return super.validateSymbol(grid);
|
|
71
88
|
}
|
|
72
89
|
copyWith({ x, y, orientation, }) {
|