'use strict';
AB.clockTick = 100, AB.maxSteps = 1e3, AB.screenshotStep = 50;
const show3d = true;
const TEXTURE_WALL = "/uploads/jfajou/TronCircuitry.jpg";
const TEXTURE_MAZE = "/uploads/jfajou/TronVector.jpg";
const TEXTURE_AGENT = "/uploads/starter/pacman.jpg";
const TEXTURE_ENEMY = "/uploads/jfajou/Ghost.jpg";
const MUSIC_BACK = "/uploads/starter/Defense.Line.mp3";
const SOUND_ALARM = "/uploads/starter/air.horn.mp3";
const gridsize = 50;
const NOBOXES = Math.trunc(gridsize * gridsize / 10);
const squaresize = 100;
const MAXPOS = gridsize * squaresize;
const SKYCOLOR = 14548957;
const startRadiusConst = .8 * MAXPOS;
const maxRadiusConst = 10 * MAXPOS;
ABHandler.MAXCAMERAPOS = maxRadiusConst, ABHandler.GROUNDZERO = true;
const SKYBOX_ARRAY = ["/uploads/starter/sky_pos_z.jpg", "/uploads/starter/sky_neg_z.jpg", "/uploads/starter/sky_pos_y.jpg", "/uploads/starter/sky_neg_y.jpg", "/uploads/starter/sky_pos_x.jpg", "/uploads/starter/sky_neg_x.jpg"];
const ACTION_LEFT = 0;
const ACTION_RIGHT = 1;
const ACTION_UP = 2;
const ACTION_DOWN = 3;
const ACTION_STAYSTILL = 4;
const GRID_BLANK = 0;
const GRID_WALL = 1;
const GRID_MAZE = 2;
var BOXHEIGHT;
var theagent;
var theenemy;
var wall_texture;
var agent_texture;
var enemy_texture;
var maze_texture;
var ei;
var ej;
var ai;
var aj;
var badsteps;
var goodsteps;
var startNode;
var endNode;
/** @type {!Array} */
var GRID = new Array(gridsize);
/** @type {!Array} */
var trappedSet = [];
/** @type {!Array} */
var winnerSet = [];
/** @type {boolean} */
var isASolution = false;
/** @type {!Array} */
var grid = new Array(gridsize);
/**
* @return {undefined}
*/
function loadResources() {
var mockObjectLoader = new THREE.TextureLoader;
var outbound_chart = new THREE.TextureLoader;
var inbound_chart = new THREE.TextureLoader;
var snippetFrame = new THREE.TextureLoader;
mockObjectLoader.load(TEXTURE_WALL, function (texture) {
texture.minFilter = THREE.LinearFilter;
/** @type {!Object} */
wall_texture = texture;
if (asynchFinished()) {
initScene();
}
});
outbound_chart.load(TEXTURE_AGENT, function (texture) {
texture.minFilter = THREE.LinearFilter;
/** @type {!Object} */
agent_texture = texture;
if (asynchFinished()) {
initScene();
}
});
inbound_chart.load(TEXTURE_ENEMY, function (texture) {
texture.minFilter = THREE.LinearFilter;
/** @type {!Object} */
enemy_texture = texture;
if (asynchFinished()) {
initScene();
}
});
snippetFrame.load(TEXTURE_MAZE, function (texture) {
texture.minFilter = THREE.LinearFilter;
/** @type {!Object} */
maze_texture = texture;
if (asynchFinished()) {
initScene();
}
});
}
/**
* @return {?}
*/
function asynchFinished() {
return !!(wall_texture && agent_texture && enemy_texture && maze_texture);
}
/**
* @param {number} x
* @param {number} y
* @return {?}
*/
function occupied(x, y) {
return ei == x && ej == y || (ai == x && aj == y || (GRID[x][y] == GRID_WALL || GRID[x][y] == GRID_MAZE));
}
/**
* @param {number} e
* @param {number} t
* @return {?}
*/
function translate(e, t) {
var globalBonePosition = new THREE.Vector3;
return globalBonePosition.y = 0, globalBonePosition.x = e * squaresize - MAXPOS / 2, globalBonePosition.z = t * squaresize - MAXPOS / 2, globalBonePosition;
}
/**
* @return {undefined}
*/
function initScene() {
var sphere;
var light;
/** @type {number} */
x = 0;
for (; x < gridsize; x++) {
/** @type {!Array} */
GRID[x] = new Array(gridsize);
}
/** @type {number} */
x = 0;
for (; x < gridsize; x++) {
/** @type {number} */
y = 0;
for (; y < gridsize; y++) {
if (0 == x || x == gridsize - 1 || 0 == y || y == gridsize - 1) {
GRID[x][y] = GRID_WALL;
sphere = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize);
(light = new THREE.Mesh(sphere)).material = new THREE.MeshBasicMaterial({
map: wall_texture
});
light.position.copy(translate(x, y));
ABWorld.scene.add(light);
} else {
GRID[x][y] = GRID_BLANK;
}
}
}
/** @type {number} */
var i = 1;
for (; i <= NOBOXES; i++) {
x = AB.randomIntAtoB(1, gridsize - 2);
y = AB.randomIntAtoB(1, gridsize - 2);
GRID[x][y] = GRID_MAZE;
sphere = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize);
(light = new THREE.Mesh(sphere)).material = new THREE.MeshBasicMaterial({
map: maze_texture
});
light.position.copy(translate(x, y));
ABWorld.scene.add(light);
}
do {
x = AB.randomIntAtoB(1, gridsize - 2);
y = AB.randomIntAtoB(1, gridsize - 2);
} while (occupied(x, y));
ei = x;
ej = y;
sphere = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize);
(theenemy = new THREE.Mesh(sphere)).material = new THREE.MeshBasicMaterial({
map: enemy_texture
});
ABWorld.scene.add(theenemy);
drawEnemy();
do {
x = AB.randomIntAtoB(1, gridsize - 2);
y = AB.randomIntAtoB(1, gridsize - 2);
} while (occupied(x, y));
ai = x;
aj = y;
sphere = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize);
(theagent = new THREE.Mesh(sphere)).material = new THREE.MeshBasicMaterial({
map: agent_texture
});
ABWorld.scene.add(theagent);
drawAgent();
ABWorld.scene.background = (new THREE.CubeTextureLoader).load(SKYBOX_ARRAY, function () {
ABWorld.render();
AB.removeLoading();
/** @type {boolean} */
AB.runReady = true;
});
/** @type {number} */
var x = 0;
for (; x < gridsize; x++) {
/** @type {!Array} */
grid[x] = new Array(gridsize);
}
/** @type {number} */
x = 0;
for (; x < gridsize; x++) {
/** @type {number} */
var y = 0;
for (; y < gridsize; y++) {
/** @type {!Node} */
grid[x][y] = new Node(x, y);
}
}
/** @type {number} */
x = 0;
for (; x < gridsize; x++) {
/** @type {number} */
y = 0;
for (; y < gridsize; y++) {
grid[x][y].addNeighbors(grid);
if (1 == grid[x][y].canBeStoppedHere) {
/** @type {boolean} */
isASolution = true;
}
}
}
if (0 == isASolution) {
/** @type {boolean} */
AB.abortRun = true;
console.log("There is no square available for the agent to be trapped, so we can finish here!");
}
}
/**
* @return {undefined}
*/
function drawEnemy() {
theenemy.position.copy(translate(ei, ej));
ABWorld.lookat.copy(theenemy.position);
}
/**
* @return {undefined}
*/
function drawAgent() {
theagent.position.copy(translate(ai, aj));
ABWorld.follow.copy(theagent.position);
}
/**
* @param {number} a
* @param {number} b
* @return {undefined}
*/
function Node(a, b) {
/** @type {number} */
this.i = a;
/** @type {number} */
this.j = b;
/** @type {number} */
this.g = 0;
/** @type {number} */
this.h = 0;
/** @type {number} */
this.f = this.g + this.h;
/** @type {!Array} */
this.neighbors = [];
this.previous = void 0;
if (GRID[a][b] == GRID_BLANK) {
/** @type {boolean} */
this.wall = false;
} else {
/** @type {boolean} */
this.wall = true;
}
/** @type {boolean} */
this.canBeStoppedHere = false;
/**
* @param {!Object} arr
* @return {undefined}
*/
this.addNeighbors = function (arr) {
var arom;
var i = this.i;
var j = this.j;
/** @type {number} */
var r = 0;
if (i < gridsize - 1) {
this.neighbors.push(arr[i + 1][j]);
if (1 == arr[i + 1][j].wall) {
r++;
} else {
arom = arr[i + 1][j];
}
}
if (i > 0) {
this.neighbors.push(arr[i - 1][j]);
if (1 == arr[i - 1][j].wall) {
r++;
} else {
arom = arr[i - 1][j];
}
}
if (j < gridsize - 1) {
this.neighbors.push(arr[i][j + 1]);
if (1 == arr[i][j + 1].wall) {
r++;
} else {
arom = arr[i][j + 1];
}
}
if (j > 0) {
this.neighbors.push(arr[i][j - 1]);
if (1 == arr[i][j - 1].wall) {
r++;
} else {
arom = arr[i][j - 1];
}
}
if (3 == r && 0 == arr[i][j].wall) {
console.log("***Can be stopped at " + i + ", " + j);
/** @type {boolean} */
this.canBeStoppedHere = true;
trappedSet.push(arr[i][j]);
winnerSet.push(arom);
}
if (i > 0 && j > 0) {
this.neighbors.push(arr[i - 1][j - 1]);
}
if (i < gridsize - 1 && j > 0) {
this.neighbors.push(arr[i + 1][j - 1]);
}
if (i > 0 && j < gridsize - 1) {
this.neighbors.push(arr[i - 1][j + 1]);
}
if (i < gridsize - 1 && j < gridsize - 1) {
this.neighbors.push(arr[i + 1][j + 1]);
}
};
}
/**
* @param {!Object} a
* @param {!Object} b
* @return {?}
*/
function getDist(a, b) {
/** @type {number} */
var sqsum = Math.pow(a.i - b.i, 2) + Math.pow(a.j - b.j, 2);
return Math.sqrt(ssum);
}
/**
* @return {undefined}
*/
function moveLogicalEnemy() {
var value;
/** @type {!Array} */
var values = [];
/** @type {!Array} */
var key = [];
startNode = grid[ei][ej];
endNode = grid[ai][aj];
values.push(startNode);
for (; values.length > 0;) {
/** @type {number} */
var j = 0;
/** @type {number} */
var i = 0;
for (; i < values.length; i++) {
if (values[i].f < values[j].f) {
/** @type {number} */
j = i;
}
}
if ((value = values[j]) == endNode) {
break;
}
/** @type {number} */
i = values.length - 1;
for (; i >= 0; i--) {
if (values[i] == value) {
values.splice(i, 1);
}
}
key.push(value);
var n = value.neighbors;
/** @type {number} */
i = 0;
for (; i < n.length; i++) {
var node = n[i];
if (!key.includes(node) && !node.wall) {
var cost = value.g + getDist(node, value);
/** @type {boolean} */
var d = false;
if (values.includes(node)) {
if (cost < node.g) {
node.g = cost;
/** @type {boolean} */
d = true;
}
} else {
node.g = cost;
/** @type {boolean} */
d = true;
values.push(node);
}
if (d) {
node.h = getDist(node, endNode);
node.previous = value;
}
}
}
}
var current = value;
for (; current.previous && (0, current.previous != startNode);) {
current = current.previous;
}
if (current !== endNode) {
ei = current.i;
ej = current.j;
} else {
if (trappedSet.includes(endNode)) {
var origin = winnerSet[trappedSet.indexOf(endNode)];
if (startNode.neighbors.includes(origin)) {
console.log("*****In the TRAP!!!!");
console.log("Winner location " + trappedSet.indexOf(endNode));
ei = origin.i;
ej = origin.j;
} else {
moveToRandomNeighbour();
}
} else {
moveToRandomNeighbour();
}
}
}
/**
* @return {undefined}
*/
function moveToRandomNeighbour() {
var i;
var neighbors = startNode.neighbors;
do {
i = AB.randomIntAtoB(0, neighbors.length - 1);
} while (occupied(neighbors[i].i, neighbors[i].j));
ei = neighbors[i].i;
ej = neighbors[i].j;
console.log("New end Node is " + ei + "," + ej);
}
/**
* @param {string} opt_parentWin
* @return {undefined}
*/
function moveLogicalAgent(opt_parentWin) {
var i = ai;
var charsetBitSize = aj;
if (opt_parentWin == ACTION_LEFT) {
i--;
} else {
if (opt_parentWin == ACTION_RIGHT) {
i++;
} else {
if (opt_parentWin == ACTION_UP) {
charsetBitSize++;
} else {
if (opt_parentWin == ACTION_DOWN) {
charsetBitSize--;
}
}
}
}
if (!occupied(i, charsetBitSize)) {
ai = i;
aj = charsetBitSize;
}
}
/** @type {!Array} */
var OURKEYS = [37, 38, 39, 40];
/**
* @param {!Event} event
* @return {?}
*/
function ourKeys(event) {
return OURKEYS.includes(event.keyCode);
}
/**
* @param {!Event} event
* @return {?}
*/
function keyHandler(event) {
return !AB.runReady || (!ourKeys(event) || (37 == event.keyCode && moveLogicalAgent(ACTION_LEFT), 38 == event.keyCode && moveLogicalAgent(ACTION_DOWN), 39 == event.keyCode && moveLogicalAgent(ACTION_RIGHT), 40 == event.keyCode && moveLogicalAgent(ACTION_UP), event.stopPropagation(), event.preventDefault(), false));
}
/**
* @return {?}
*/
function badstep() {
return Math.abs(ei - ai) < 2 && Math.abs(ej - aj) < 2;
}
/**
* @return {?}
*/
function agentBlocked() {
return occupied(ai - 1, aj) && occupied(ai + 1, aj) && occupied(ai, aj + 1) && occupied(ai, aj - 1);
}
/**
* @param {string} opt_parentWin
* @return {undefined}
*/
function updateStatusBefore(opt_parentWin) {
var default_favicon = AB.world.getState();
AB.msg(" Step: " + AB.step + " x = (" + default_favicon.toString() + ") a = (" + opt_parentWin + ") ");
}
/**
* @return {undefined}
*/
function updateStatusAfter() {
var default_favicon = AB.world.getState();
/** @type {number} */
var e_total = goodsteps / AB.step * 100;
AB.msg(" y = (" + default_favicon.toString() + ") <br> Bad steps: " + badsteps + " Good steps: " + goodsteps + " Score: " + e_total.toFixed(2) + "% ", 2);
}
AB.world.newRun = function () {
AB.loadingScreen();
/** @type {boolean} */
AB.runReady = false;
/** @type {number} */
badsteps = 0;
/** @type {number} */
goodsteps = 0;
BOXHEIGHT = squaresize;
ABWorld.init3d(startRadiusConst, maxRadiusConst, 14548957);
loadResources();
/** @type {function(!Event): ?} */
document.onkeydown = keyHandler;
}, AB.world.getState = function () {
return [ai, aj, ei, ej];
}, AB.world.takeAction = function (optionString) {
updateStatusBefore(optionString);
moveLogicalAgent(optionString);
if (AB.step % 2 == 0) {
moveLogicalEnemy();
}
if (badstep()) {
badsteps++;
} else {
goodsteps++;
}
drawAgent();
drawEnemy();
updateStatusAfter();
if (agentBlocked()) {
/** @type {boolean} */
AB.abortRun = true;
/** @type {number} */
goodsteps = 0;
musicPause();
soundAlarm();
}
}, AB.world.endRun = function () {
musicPause();
if (0 == isASolution) {
AB.msg(" <br> <font color=red> <B> The Agent cannot be trapped. The game has ended. </B> </font> ", 3);
} else {
if (AB.abortRun) {
AB.msg(" <br> <font color=red> <B> Agent trapped. Final score zero. </B> </font> ", 3);
} else {
AB.msg(" <br> <font color=green> <B> Run over. </B> </font> ", 3);
}
}
}, AB.world.getScore = function () {
/** @type {number} */
var ipw = goodsteps / AB.maxSteps * 100;
return Math.round(100 * ipw) / 100;
};
var backmusic = AB.backgroundMusic(MUSIC_BACK);
/**
* @return {undefined}
*/
function musicPlay() {
backmusic.play();
}
/**
* @return {undefined}
*/
function musicPause() {
backmusic.pause();
}
/**
* @return {undefined}
*/
function soundAlarm() {
(new Audio(SOUND_ALARM)).play();
};