// Cloned by Raj Vibhute on 10 Nov 2022 from World "Complex World" by Starter user
// Please leave this clone trail here.
// ==== Starter World =================================================================================================
// This code is designed for use on the Ancient Brain site.
// This code may be freely copied and edited by anyone on the Ancient Brain site.
// To include a working run of this program on another site, see the "Embed code" links provided on Ancient Brain.
// ====================================================================================================================
const WALLMOVENO = 10, WALLMOVETICK = 1000;
AB.clockTick = 100; // 100,
// Speed of run: Step every n milliseconds. Default 100.
AB.maxSteps = 1000,
// Length of run: Maximum length of run in steps. Default 1000.
AB.screenshotStep = 50;
// Take screenshot on this step. (All resources should have finished loading.) Default 50.
//----- global constants: -----//
const show3d = true,
// All Images
TEXTURE_WALL = "/uploads/starter/door.jpg",
TEXTURE_MAZE = "/uploads/starter/latin.jpg",
TEXTURE_AGENT = "/uploads/rajv261/Agent.jpeg",
TEXTURE_ENEMY = "/uploads/rajv261/Enemy11.jpeg",
TEXTURE_PATH = "/uploads/rajv261/Enemy.jpeg",
//Music Tracks
MUSIC_BACK = "/uploads/rajv261/Rifle-Automatic-Fire-A-www.fesliyanstudios.com.mp3",
SOUND_ALARM = "/uploads/rajv261/Big-Grenade-Explosion-www.fesliyanstudios.com.mp3",
gridsize = 30; // 30,
// number of squares along side of world
NOBOXES = Math.trunc(gridsize * gridsize / 10 ), // 10
// density of maze - number of internal boxes
// (bug) use trunc or can get a non-intege
squaresize = 100, // size of square in pixels
MAXPOS = gridsize * squaresize,//length of one side in pixels
SKYCOLOR = 18756435,//a number, not a string
startRadiusConst = 0.8 * MAXPOS, // distance from centre to start the camera at
maxRadiusConst = 10 * MAXPOS; // maximum distance from camera we will render things
// Changes in AB World
//wallCutOff = AB.randomFloatAtoB(0, 0.6);
ABHandler.MAXCAMERAPOS = maxRadiusConst, ABHandler.GROUNDZERO = true;
const SKYBOX_ARRAY = [
"/uploads/starter/posx.jpg",
"/uploads/starter/negx.jpg",
"/uploads/starter/posy.jpg",
"/uploads/starter/negy.jpg",
"/uploads/starter/posz.jpg",
"/uploads/starter/negz.jpg"
];
//Actions picked by Mind
const ACTION_LEFT = 0,
ACTION_RIGHT = 1,
ACTION_UP = 2,
ACTION_DOWN = 3,
ACTION_STAYSTILL = 4,
// contents of a grid square
GRID_BLANK = 0,
GRID_WALL = 1,
GRID_MAZE = 2;
var BOXHEIGHT;
var theagent, theenemy;
var wall_texture, agent_texture, enemy_texture, maze_texture, path_texture;
var ei, ej, ai, aj;
var badsteps;
var goodsteps;
GRID = new Array(gridsize),
closedSet = [],
openSet = [],
path = [],
mazePieces = [],
nextBestSquare = null;
function loadResources() // asynchronous file loads - call initScene() when all finished
{
var e = new THREE.TextureLoader,
t = new THREE.TextureLoader,
i = new THREE.TextureLoader,
s = new THREE.TextureLoader,
a = new THREE.TextureLoader;
e.load(TEXTURE_WALL, function (e)
{
e.minFilter = THREE.LinearFilter,
wall_texture = e,
wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
}), t.load(TEXTURE_AGENT, function (e)
{
e.minFilter = THREE.LinearFilter,
agent_texture = e,
wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
}), i.load(TEXTURE_ENEMY, function (e)
{
e.minFilter = THREE.LinearFilter,
enemy_texture = e, wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
}), s.load(TEXTURE_MAZE, function (e)
{
e.minFilter = THREE.LinearFilter,
maze_texture = e,
wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
}), a.load(TEXTURE_PATH, function (e)
{
e.minFilter = THREE.LinearFilter,
path_texture = e,
wall_texture && agent_texture && enemy_texture && maze_texture && path_texture && initScene();
});
}
function translate(e, t)
{
var i = new THREE.Vector3;
return i.y = 0,
i.x = e * squaresize - MAXPOS / 2,
i.z = t * squaresize - MAXPOS / 2,
i;
}
function initScene()
{
var e, t, i;
for (e = 0; e < gridsize; e++) GRID[e] = new Array(gridsize);
for (e = 0; e < gridsize; e++) for (t = 0; t < gridsize; t++) 0 === e || e === gridsize - 1 || 0 === t || t === gridsize - 1 ? (GRID[e][t] = new Box(e, t, GRID_WALL, true),
GRID[e][t].show()) : GRID[e][t] = new Box(e, t, GRID_BLANK, false);
for (var s = 1; s <= NOBOXES; s++) e = AB.randomIntAtoB(1, gridsize - 2),
t = AB.randomIntAtoB(1, gridsize - 2),
GRID[e][t] = new Box(e, t, GRID_MAZE, true),
GRID[e][t].show(), mazePieces.push(GRID[e][t]);
for (e = 0; e < gridsize; e++) for (t = 0; t < gridsize; t++)
GRID[e][t].addNeighbors(GRID);
do
{
e = AB.randomIntAtoB(1, gridsize - 2),
t = AB.randomIntAtoB(1, gridsize - 2);
}
while (ei === e && ej === t || (ai === e && aj === t || !(!GRID[e][t].isWall && !mazePieces.includes(GRID[e][t]))));
ei = e,
ej = t,
i = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize),
(theenemy = new THREE.Mesh(i)).material = new THREE.MeshBasicMaterial({map: enemy_texture}),
ABWorld.scene.add(theenemy),
drawEnemy();
do
{
e = AB.randomIntAtoB(1, gridsize - 2),
t = AB.randomIntAtoB(1, gridsize - 2);
} while (ei === e && ej === t || (ai === e && aj === t || !(!GRID[e][t].isWall && !mazePieces.includes(GRID[e][t]))));
ai = e, aj = t, i = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize), (theagent = new THREE.Mesh(i)).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(), AB.runReady = true;
});
}
function drawEnemy()
{
theenemy.position.copy(translate(ei, ej)),
ABWorld.lookat.copy(theenemy.position);
}
function drawAgent()
{
theagent.position.copy(translate(ai, aj)),
ABWorld.follow.copy(theagent.position);
}
function Astar()
{
for (const e of path) e.highlight(false);
closedSet.splice(0, closedSet.length),
openSet.splice(0, openSet.length),
path.splice(0, path.length);
var e = GRID[ei][ej];
for (openSet.push(e); openSet.length > 0;)
{
for (var t = 0, i = 0; i < openSet.length; i++) openSet[i].f < openSet[t].f && (t = i);
var s = openSet[t],
a = GRID[ai][aj];
if (s === a)
{
for (var n = s; n.previous !== e;) n.highlight(true), path.push(n), n = n.previous;
return n;
}
openSet.splice(openSet.indexOf(s), 1), closedSet.push(s);
var r = s.neighbors;
for (i = 0; i < r.length; i++)
{
var o = r[i];
if (!closedSet.includes(o) && !o.isWall)
{
var u = s.g + (Math.abs(o.i - s.i) + Math.abs(o.j - s.j)),
d = false;
openSet.includes(o) ? u < o.g && (o.g = u, d = true) : (o.g = u, d = true, openSet.push(o)), d && (o.h = Math.abs(o.i - a.i) + Math.abs(o.j - a.j), o.f = o.g + o.h, o.previous = s);
}
}
}
}
function moveLogicalEnemy()
{
do
{
nextBestSquare = Astar();
}
while (!nextBestSquare);
ei === nextBestSquare.i && ej === nextBestSquare.j || (ai === nextBestSquare.i && aj === nextBestSquare.j || !(!GRID[nextBestSquare.i][nextBestSquare.j].isWall && !mazePieces.includes(GRID[nextBestSquare.i][nextBestSquare.j]))) || (ei = nextBestSquare.i, ej = nextBestSquare.j), nextBestSquare = null;
}
function moveLogicalAgent(e)
{
var t = ai, i = aj;
e == ACTION_LEFT ? t-- : e == ACTION_RIGHT ? t++ : e == ACTION_UP ? i++ : e == ACTION_DOWN && i--, ei === t && ej === i || (ai === t && aj === i || !(!GRID[t][i].isWall && !mazePieces.includes(GRID[t][i]))) || (ai = t, aj = i);
}
timer = setInterval(function ()
{
for (var e = 0; e < 10; e++)
{
var t, i, s = mazePieces[AB.randomIntAtoB(0, mazePieces.length - 1)];
do
{
t = AB.randomIntAtoB(1, gridsize - 2), i = AB.randomIntAtoB(1, gridsize - 2);
} while ((ei === t && ej === i || (ai === t && aj === i || !(!GRID[t][i].isWall && !mazePieces.includes(GRID[t][i])))) && t == s.i && i == s.j);
s.removeMazePiece(), mazePieces.splice(mazePieces.indexOf(s), 1);
var a = GRID[s.i][s.j];
a.squareType = GRID_BLANK,
a.isWall = false,
a.f = 0,
a.g = 0,
a.h = 0,
GRID[s.i][s.j] = a;
var n = GRID[t][i];
n.squareType = GRID_MAZE, n.isWall = true, n.f = 0, n.g = 0, n.h = 0, n.show(), mazePieces.push(n), GRID[t][i] = n, nextBestSquare = Astar();
}
},1000);
function Box(a, t, i, s)
{
this.uniqueId,
this.mazePieceId,
this.i = a,
this.j = t,
this.f = 0,
this.g = 0,
this.h = 0,
this.neighbors = [],
this.previous = void 0,
this.squareType = i,
this.isWall = s,
this.show = function ()
{
shape = new THREE.BoxGeometry(squaresize, BOXHEIGHT, squaresize),
thecube = new THREE.Mesh(shape),
this.squareType == GRID_WALL ? thecube.material = new THREE.MeshBasicMaterial({map: wall_texture}) : this.squareType == GRID_MAZE && (thecube.material = new THREE.MeshBasicMaterial({map: maze_texture}), this.mazePieceId = thecube.uuid),
thecube.position.copy(translate(this.i, this.j)), ABWorld.scene.add(thecube);
},
this.removeMazePiece = function ()
{
var e = ABWorld.scene.getObjectByProperty("uuid", this.mazePieceId);
ABWorld.scene.remove(a),
this.mazePieceId = null;
},
this.highlight = function (a)
{
if (a) thehighlightedshape = new THREE.BoxGeometry(squaresize, 0.001, squaresize),thehighlightedpiece = new THREE.Mesh(thehighlightedshape),thehighlightedpiece.material = new THREE.MeshBasicMaterial({map: path_texture}), thehighlightedpiece.position.copy(translate(this.i, this.j)),ABWorld.scene.add(thehighlightedpiece),this.uniqueId = thehighlightedpiece.uuid;
else
{
var t = ABWorld.scene.getObjectByProperty("uuid", this.uniqueId);
ABWorld.scene.remove(t),
this.uniqueId = null;
}
},
this.addNeighbors = function (a)
{
this.i < gridsize - 1 && this.neighbors.push(a[this.i + 1][this.j]),
this.i > 0 && this.neighbors.push(a[this.i - 1][this.j]),
this.j < gridsize - 1 && this.neighbors.push(a[this.i][this.j + 1]), this.j > 0 && this.neighbors.push(a[this.i][this.j - 1]);
};
}
var OURKEYS = [37, 38, 39, 40];
function keyHandler ( event )
{
if ( ! AB.runReady ) return true; // not ready yet
// if not one of our special keys, send it to default key handling:
if ( ! ourKeys ( event ) ) return true;
// else handle key and prevent default handling:
if ( event.keyCode == 37 ) moveLogicalAgent ( ACTION_LEFT );
if ( event.keyCode == 38 ) moveLogicalAgent ( ACTION_DOWN );
if ( event.keyCode == 39 ) moveLogicalAgent ( ACTION_RIGHT );
if ( event.keyCode == 40 ) moveLogicalAgent ( ACTION_UP );
// when the World is embedded in an iframe in a page, we want arrow key events handled by World and not passed up to parent
event.stopPropagation(); event.preventDefault(); return false;
}
function updateStatusBefore(e)
{
var t = AB.world.getState();
AB.msg("Step: " + AB.step + " x = (" + t.toString() + ") a = (" + e + ") ");
}
function updateStatusAfter()
{
var e = AB.world.getState(),
t = goodsteps / AB.step * 100;
AB.msg(" y = (" + e.toString() + ") <br> Bad steps: " + badsteps + " Good steps: " + goodsteps + " Score: " + t.toFixed(2) + "% ", 2);
}
AB.world.newRun = function ()
{
AB.loadingScreen(),
AB.runReady = false,
badsteps = 0,
goodsteps = 0,
BOXHEIGHT = squaresize,
ABWorld.init3d(startRadiusConst,
maxRadiusConst, 14548957),
loadResources(), document.onkeydown = keyHandler;
},
AB.world.getState = function ()
{
return [ai, aj, ei, ej];
},
AB.world.takeAction = function (e)
{
updateStatusBefore(e),
moveLogicalAgent(e),
AB.step % 2 == 0 && moveLogicalEnemy(),
Math.abs(ei - ai) < 2 && Math.abs(ej - aj) < 2 ? badsteps++ : goodsteps++,
drawAgent(),
drawEnemy(),
updateStatusAfter(),
(ei === ai - 1 && ej === aj || (ai === ai - 1 && aj === aj || !(!GRID[ai - 1][aj].isWall && !mazePieces.includes(GRID[ai - 1][aj])))) && (ei === ai + 1 && ej === aj || (ai === ai + 1 && aj === aj || !(!GRID[ai + 1][aj].isWall && !mazePieces.includes(GRID[ai + 1][aj])))) && (ei === ai && ej === aj + 1 || (ai === ai && aj === aj + 1 || !(!GRID[ai][aj + 1].isWall && !mazePieces.includes(GRID[ai][aj + 1])))) && (ei === ai && ej === aj - 1 || (ai === ai && aj === aj - 1 || !(!GRID[ai][aj - 1].isWall && !mazePieces.includes(GRID[ai][aj - 1])))) && (AB.abortRun = true,
goodsteps = 0,
musicPause(),
soundAlarm());
},
AB.world.endRun = function ()
{
musicPause(),
AB.msg(AB.abortRun ? "<br> <font color=red> <B> Laden Is Trapped. Final Score Zero. </B> </font>" : "<br> <font color=Red> <B> Chase Over. </B> </font>", 5);
},
AB.world.getScore = function ()
{
var e = goodsteps / AB.maxSteps * 100;
return Math.round(100 * e) / 100;
};
var backmusic = AB.backgroundMusic(MUSIC_BACK);
function musicPlay()
{
backmusic.play();
}
function musicPause()
{
backmusic.pause();
}
function soundAlarm()
{
new Audio(SOUND_ALARM).play();
}