xxxxxxxxxx
124
const DIMENSION = 15;
const TILE_SIZE = 25;
const dusa = new Dusa(`
#builtin INT_MINUS minus
#builtin INT_PLUS plus
size is ${DIMENSION}.
dim N :- size is N.
dim (minus N 1) :- dim N, N != 1.
delta 0 1.
delta 0 -1.
delta 1 0.
delta -1 0.
movePos (pos X Y) (pos X' Y') :-
reachPos (pos X Y),
delta DX DY,
plus X DX is X',
plus Y DY is Y',
dim X', dim Y'.
# waypoint 4 5.
waypoint is? (pos X Y) :- dim X, dim Y.
moveState (state X Y W) (state X' Y' W)
:- movePos (pos X Y) (pos X' Y'),
reachState (state X Y W).
moveState (state X Y false) (state X Y true)
:- reachPos (pos X Y), waypoint is (pos X Y).
start (state 1 1 false).
parent S is none :- start S.
parent S is? { S' } :-
parent S' is _,
moveState S' S.
reachState S :- parent S is _.
reachPos (pos X Y) :- reachState (state X Y _).
goal (state size size true).
after S is done :- goal S.
after S' is S :-
after S is _,
parent S is S'.
`);
let iteration = 0;
const iterator = dusa.solve();
function setup() {
createCanvas(
Math.max(DIMENSION * TILE_SIZE, 150),
DIMENSION * TILE_SIZE + 30
);
noLoop();
}
function touchStarted() {
draw();
}
function draw() {
stroke(167)
const { value: solution } = iterator.next();
erase();
rect(0, 0, Math.max(DIMENSION * TILE_SIZE, 150), 30);
noErase();
fill("black");
if (!solution && iteration == 0) {
text("There are no solutions", 0, 20);
return;
}
if (!solution) {
text(`Solution ${iteration} out of ${iteration}`, 0, 20);
return;
}
iteration += 1;
text(`Solution ${iteration} out of ?`, 0, 20);
const waypoint = solution.get('waypoint').args;
for (let col = 1; col <= DIMENSION; col++) {
for (let row = 1; row <= DIMENSION; row++) {
const x = (col-1) * TILE_SIZE;
const y = (row-1) * TILE_SIZE + 30;
const fstate = solution.get('after', { name: 'state', args: [col, row, { name: 'false' }] })
const tstate = solution.get('after', { name: 'state', args: [col, row, { name: 'true' }] })
if (waypoint[0] === col && waypoint[1] === row) {
fill("#fe96ca")
} else if (tstate && fstate) {
fill("#56d8a3"); // bright blue
} else if (tstate) {
fill("#09d3f2");
} else if (fstate) {
fill("#bdc653");
} else {
fill("white")
}
rect(x, y, TILE_SIZE, TILE_SIZE);
}
}
for (const [poskey, value] of solution.lookup('parent')) {
if (value.name !== 'state') continue;
const [col1, row1] = poskey.args;
const [col2, row2] = value.args;
// COMMENT OUT THIS LINE TO SHOW BOTH 'true' AND 'false' TREES OVERLAID
if (value.args[2].name === 'false') continue;
const x1 = (Number(col1)-0.5) * TILE_SIZE;
const x2 = (Number(col2)-0.5) * TILE_SIZE;
const y1 = (Number(row1)-0.5) * TILE_SIZE + 30;
const y2 = (Number(row2)-0.5) * TILE_SIZE + 30;
stroke(0)
line(x1,y1,x2,y2)
}
}