testChamber2

meta-analysis - if you choose a junk tech you instead get a random tech and spawn 2 research
micro-extruder should have 50% less lag

new community level testChamber2! by Oranger on n-gon discord
(be sure to enable community levels in settings)
This commit is contained in:
landgreen
2021-03-11 18:35:11 -08:00
parent 1056a77572
commit 3d04e61a04
8 changed files with 539 additions and 258 deletions

View File

@@ -1207,18 +1207,18 @@ const b = {
m.energy = 0; m.energy = 0;
} }
b.isExtruderOn = true b.isExtruderOn = true
const SPEED = 8 const SPEED = 14
const me = bullet.length; const me = bullet.length;
const where = Vector.add(m.pos, player.velocity) const where = Vector.add(m.pos, player.velocity)
bullet[me] = Bodies.polygon(where.x + 20 * Math.cos(m.angle), where.y + 20 * Math.sin(m.angle), 4, 0.01, { bullet[me] = Bodies.polygon(where.x + 20 * Math.cos(m.angle), where.y + 20 * Math.sin(m.angle), 4, 0.01, {
cycle: -0.5, cycle: -0.5,
isWave: true, isWave: true,
endCycle: simulation.cycle + 35 + 45 * tech.isPlasmaRange, endCycle: simulation.cycle + 53, // + 30 * tech.isPlasmaRange,
inertia: Infinity, inertia: Infinity,
frictionAir: 0, frictionAir: 0,
isInHole: true, //this keeps the bullet from entering wormholes isInHole: true, //this keeps the bullet from entering wormholes
minDmgSpeed: 0, minDmgSpeed: 0,
dmg: b.dmgScale * 1.2, //damage also changes when you divide by mob.mass on in .do() dmg: b.dmgScale * 1.5, //damage also changes when you divide by mob.mass on in .do()
classType: "bullet", classType: "bullet",
isBranch: false, isBranch: false,
restitution: 0, restitution: 0,
@@ -1270,7 +1270,7 @@ const b = {
y: SPEED * Math.sin(m.angle) y: SPEED * Math.sin(m.angle)
}); });
const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) const transverse = Vector.normalise(Vector.perp(bullet[me].velocity))
if (180 - Math.abs(Math.abs(b.lastAngle - m.angle) - 180) > 0.3) bullet[me].isBranch = true; //don't draw stroke for this bullet if (180 - Math.abs(Math.abs(b.lastAngle - m.angle) - 180) > 0.13) bullet[me].isBranch = true; //don't draw stroke for this bullet
b.lastAngle = m.angle //track last angle for the above angle difference calculation b.lastAngle = m.angle //track last angle for the above angle difference calculation
if (!b.wasExtruderOn) bullet[me].isBranch = true; if (!b.wasExtruderOn) bullet[me].isBranch = true;
} else { } else {
@@ -1825,8 +1825,8 @@ const b = {
}, },
spore(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death() spore(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
const bIndex = bullet.length; const bIndex = bullet.length;
const side = 4; if (bIndex < 500) { //can't make over 500 spores
bullet[bIndex] = Bodies.polygon(where.x, where.y, 4, side, { bullet[bIndex] = Bodies.polygon(where.x, where.y, 4, 4, {
// density: 0.0015, //frictionAir: 0.01, // density: 0.0015, //frictionAir: 0.01,
inertia: Infinity, inertia: Infinity,
isFreeze: isFreeze, isFreeze: isFreeze,
@@ -1924,8 +1924,10 @@ const b = {
// } else { // } else {
// this.force.y += this.mass * 0.0001; //gravity // this.force.y += this.mass * 0.0001; //gravity
// } // }
}, },
}); });
const SPEED = 4 + 8 * Math.random(); const SPEED = 4 + 8 * Math.random();
const ANGLE = 2 * Math.PI * Math.random() const ANGLE = 2 * Math.PI * Math.random()
Matter.Body.setVelocity(bullet[bIndex], { Matter.Body.setVelocity(bullet[bIndex], {
@@ -1939,6 +1941,7 @@ const b = {
m.displayHealth(); m.displayHealth();
bullet[bIndex].isMutualismActive = true bullet[bIndex].isMutualismActive = true
} }
}
}, },
iceIX(speed = 0, spread = 2 * Math.PI) { iceIX(speed = 0, spread = 2 * Math.PI) {
const me = bullet.length; const me = bullet.length;
@@ -3405,6 +3408,7 @@ const b = {
const me = bullet.length; const me = bullet.length;
const dir = m.angle + 0.02 * (Math.random() - 0.5) const dir = m.angle + 0.02 * (Math.random() - 0.5)
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 45, 20, b.fireAttributes(dir)); bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 45, 20, b.fireAttributes(dir));
Matter.Body.setDensity(bullet[me], 0.004); Matter.Body.setDensity(bullet[me], 0.004);
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
const SPEED = (m.crouch ? 52 : 43) + Math.random() * 7 const SPEED = (m.crouch ? 52 : 43) + Math.random() * 7

View File

@@ -16,7 +16,7 @@ const level = {
// simulation.zoomScale = 1000; // simulation.zoomScale = 1000;
// simulation.setZoom(); // simulation.setZoom();
// m.setField("nano-scale manufacturing") // m.setField("nano-scale manufacturing")
// b.giveGuns("laser") // b.giveGuns("shotgun")
// tech.isExplodeRadio = true // tech.isExplodeRadio = true
// for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot") // for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot")
// tech.giveTech("supercritical fission") // tech.giveTech("supercritical fission")
@@ -55,6 +55,8 @@ const level = {
// level.detours() //fan level // level.detours() //fan level
// level.basement(); //fan level // level.basement(); //fan level
// level.stronghold() //fan level // level.stronghold() //fan level
// level.testChamber2() //fan level
// powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "tech"); // powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "tech");
// tech.giveTech("undefined") // tech.giveTech("undefined")
@@ -768,7 +770,7 @@ const level = {
mapB.portalPair = mapA mapB.portalPair = mapA
return [portalA, portalB, mapA, mapB] return [portalA, portalB, mapA, mapB]
}, },
hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)", isOptical = false) { hazard(x, y, width, height, damage = 0.003, color = "hsla(160, 100%, 35%,0.75)") {
return { return {
min: { min: {
x: x, x: x,
@@ -782,15 +784,30 @@ const level = {
height: height, height: height,
maxHeight: height, maxHeight: height,
isOn: true, isOn: true,
query() { opticalQuery() {
if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak && isOptical)) { if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak)) {
const drain = 0.003 + m.fieldRegen if (m.immuneCycle < m.cycle) {
if (m.energy > drain) { m.immuneCycle = m.cycle + tech.collisionImmuneCycles;
m.energy -= drain m.damage(damage)
} else { simulation.drawList.push({ //add dmg to draw queue
if (damage < 0.02) { x: player.position.x,
m.damage(damage) y: player.position.y,
} else if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) { radius: damage * 1500,
color: simulation.mobDmgColor,
time: 20
});
}
}
},
query() {
if (this.isOn && this.height > 0 && Matter.Query.region([player], this).length) {
const drain = 0.003 + m.fieldRegen
if (m.energy > drain) {
m.energy -= drain
} else {
if (damage < 0.02) {
m.damage(damage)
} else if (m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; m.immuneCycle = m.cycle + tech.collisionImmuneCycles;
m.damage(damage) m.damage(damage)
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
@@ -802,19 +819,15 @@ const level = {
}); });
} }
} }
//float //float
if (!isOptical) { if (player.velocity.y > 5) player.force.y -= 0.95 * player.mass * simulation.g
if (player.velocity.y > 3) player.force.y -= 0.96 * player.mass * simulation.g const slowY = (player.velocity.y > 0) ? Math.max(0.4, 1 - 0.001 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
const slowY = (player.velocity.y > 0) ? Math.max(0.3, 1 - 0.0015 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
x: Math.max(0.6, 1 - 0.07 * Math.abs(player.velocity.x)) * player.velocity.x, x: Math.max(0.6, 1 - 0.07 * Math.abs(player.velocity.x)) * player.velocity.x,
y: slowY * player.velocity.y y: slowY * player.velocity.y
}); });
} }
}
//float power ups //float power ups
if (!isOptical) {
powerUpCollide = Matter.Query.region(powerUp, this) powerUpCollide = Matter.Query.region(powerUp, this)
for (let i = 0, len = powerUpCollide.length; i < len; i++) { for (let i = 0, len = powerUpCollide.length; i < len; i++) {
const diameter = 2 * powerUpCollide[i].size const diameter = 2 * powerUpCollide[i].size
@@ -825,7 +838,6 @@ const level = {
y: 0.95 * powerUpCollide[i].velocity.y y: 0.95 * powerUpCollide[i].velocity.y
}); });
} }
}
}, },
draw() { draw() {
if (this.isOn) { if (this.isOn) {
@@ -1117,9 +1129,9 @@ const level = {
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
level.setPosToSpawn(0, -50); //normal spawn level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 1500; level.exit.x = 1500;
level.exit.y = -1875; level.exit.y = -1875;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.defaultZoom = 1800 level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde"; document.body.style.backgroundColor = "#dcdcde";
@@ -1482,8 +1494,8 @@ const level = {
spawn.mapRect(1225, -1955, 175, 30); spawn.mapRect(1225, -1955, 175, 30);
const removeIndex2 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals const removeIndex2 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals
const hazard = level.hazard(350, -2025, 700, 10, 0.4, "hsl(0, 100%, 50%)", true) //laser const hazard = level.hazard(350, -2025, 700, 10, 0.4, "hsl(0, 100%, 50%)") //laser
const hazard2 = level.hazard(1775, -2550, 150, 10, 0.4, "hsl(0, 100%, 50%)", true) //laser const hazard2 = level.hazard(1775, -2550, 150, 10, 0.4, "hsl(0, 100%, 50%)") //laser
const button = level.button(2100, -2600) const button = level.button(2100, -2600)
@@ -1533,8 +1545,8 @@ const level = {
portal2[3].query() portal2[3].query()
portal3[2].query() portal3[2].query()
portal3[3].query() portal3[3].query()
hazard.query(); hazard.opticalQuery();
hazard2.query(); hazard2.opticalQuery();
if (button.isUp) { if (button.isUp) {
hazard.isOn = false; hazard.isOn = false;
hazard2.isOn = false; hazard2.isOn = false;
@@ -2971,6 +2983,42 @@ const level = {
}); });
World.add(engine.world, cons[cons.length - 1]); World.add(engine.world, cons[cons.length - 1]);
// spawn.bodyRect(-2775, 1300, 400, 100, 1); //hoist
// cons[cons.length] = Constraint.create({
// pointA: {
// x: -2375,
// y: 150
// },
// bodyB: body[body.length - 1],
// pointB: {
// x: 190,
// y: -50
// },
// stiffness: 0.0001,
// damping: 0.2,
// length: 1
// });
// cons[cons.length] = Constraint.create({
// pointA: {
// x: -2775,
// y: 150
// },
// bodyB: body[body.length - 1],
// pointB: {
// x: -190,
// y: -50
// },
// stiffness: 0.0001,
// damping: 0.2,
// length: 1
// });
// World.add(engine.world, [cons[cons.length - 1], cons[cons.length - 2]]);
//blocks //blocks
spawn.bodyRect(-165, -150, 30, 35, 1); spawn.bodyRect(-165, -150, 30, 35, 1);
spawn.bodyRect(-165, -115, 30, 35, 1); spawn.bodyRect(-165, -115, 30, 35, 1);
@@ -4019,7 +4067,7 @@ const level = {
// // tether ball // // tether ball
// spawn.tetherBoss(8000, 630, { x: 8550, y: 680 }) // spawn.tetherBoss(8000, 630, { x: 8550, y: 680 })
// let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
// me.onDeath = function() { // me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
// this.removeCons(); //remove constraint // this.removeCons(); //remove constraint
// spawnCouloirEnHaut() // spawnCouloirEnHaut()
// doorSortieSalle.isOpen = false; // doorSortieSalle.isOpen = false;
@@ -4033,7 +4081,7 @@ const level = {
if (mob[i].isBoss) me = mob[i] if (mob[i].isBoss) me = mob[i]
} }
if (me) { if (me) {
me.onDeath = function() { me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
spawnCouloirEnHaut() spawnCouloirEnHaut()
doorSortieSalle.isOpen = false; doorSortieSalle.isOpen = false;
}; };
@@ -4049,7 +4097,7 @@ const level = {
if (mob[i].isBoss) me = mob[i] if (mob[i].isBoss) me = mob[i]
} }
if (me) { if (me) {
me.onDeath = function() { me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs
spawnCouloirEnHaut() spawnCouloirEnHaut()
doorSortieSalle.isOpen = false; doorSortieSalle.isOpen = false;
}; };
@@ -4624,5 +4672,247 @@ const level = {
spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "snakeBoss", "laserBoss"]); spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "snakeBoss", "laserBoss"]);
} }
} }
} },
testChamber2() {
level.setPosToSpawn(-600, 400);
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 550;
level.exit.y = -2730;
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20);
const portal = level.portal({ //main portals
x: -1000,
y: 50
}, -Math.PI / 2, { //up
x: 1000,
y: 50
}, -Math.PI / 2) //up
const portal2 = level.portal({ //portals in upper right corner
x: 1400,
y: -2200
}, -Math.PI / 2, { //up
x: 1700,
y: -1700
}, -Math.PI / 2) //up
const rotor = level.rotor(-200, -1950, -0.001)
level.custom = () => {
level.playerExitCheck();
portal[2].query()
portal[3].query()
portal2[2].query()
portal2[3].query()
rotor.rotate();
};
level.customTopLayer = () => {
portal[0].draw();
portal[1].draw();
portal[2].draw();
portal[3].draw();
portal2[0].draw();
portal2[1].draw();
portal2[2].draw();
portal2[3].draw();
};
level.defaultZoom = 1700 // 4500 // 1400
simulation.zoomTransition(level.defaultZoom)
//section 1: before portals
spawn.mapRect(-925, 450, 1850, 250); //1-1 base
spawn.mapRect(-925, -300, 55, 755); //1 left wall
spawn.mapRect(-875, 50, 1100, 50); //1-1 ceiling
spawn.mapRect(620, -300, 305, 755); //1-1 and 1-2 right wall
spawn.bodyRect(200, 350, 230, 100);
spawn.bodyRect(300, 250, 150, 100);
spawn.mapRect(-875, -300, 580, 50); //1-2 ceiling on left
spawn.mapRect(0, -300, 625, 50); //1-2 ceiling on right
spawn.mapRect(0, -650, 150, 350); //1-3 right wall
spawn.mapRect(-925, -650, 975, 150); //1-3 ceiling
spawn.mapRect(-1280, 100, 205, 150); //1-4 floor
spawn.mapRect(-1280, 245, 360, 455); //bottom left corner
spawn.mapRect(-1600, -200, 200, 50); //1-4 platform 1
level.fill.push({
x: -875,
y: -250,
width: 1500,
height: 700,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: -925,
y: -505,
width: 930,
height: 255,
color: "rgba(0,0,0,0.1)"
});
//section 2: lower central room (gone through main portals 1 time)
spawn.mapRect(920, 245, 160, 455); //below right portal
spawn.mapRect(1075, -300, 500, 1000); //2-1 right floor
spawn.mapRect(1075, -2005, 550, 1055); //shute right wall
spawn.mapRect(875, -1000, 50, 300); //shute left 1
spawn.mapRect(860, -1030, 50, 300); //shute left 2
spawn.mapRect(850, -1100, 50, 300); //shute left 3
spawn.mapRect(830, -980, 50, 50); //shute left 4
spawn.mapRect(1075, -1000, 50, 300); //shute right 1
spawn.mapRect(1090, -1030, 50, 300); //shute right 2
spawn.mapRect(1100, -1100, 50, 300); //shute right 3
spawn.mapRect(1120, -980, 50, 50); //shute right 4
spawn.bodyRect(100, -1000, 50, 350);
spawn.bodyRect(100, -1015, 250, 15);
spawn.mapRect(-925, -1600, 100, 1000); //2-2 left wall
spawn.mapRect(725, -2150, 200, 750); //2-2 right wall
spawn.mapRect(725, -1200, 200, 200); //2-2 right wall 2
spawn.mapRect(300, -1000, 625, 50); //2 central ledge
level.fill.push({
x: 725,
y: -1400,
width: 200,
height: 200,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 925,
y: -2150,
width: 150,
height: 2175,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 925,
y: -3450,
width: 150,
height: 900,
color: "rgba(0,0,0,0.1)"
});
//section 3: upper left room and upper central room (gone through main portals 2 times)
spawn.mapRect(-1775, -1000, 700, 300); //3-1 floor
spawn.mapRect(-1900, -2300, 175, 1600); //3-1 left wall
spawn.mapRect(-1375, -1300, 300, 50); //3-1 platform 1
spawn.mapRect(-1600, -1650, 300, 50); //3-1 platform 2
spawn.mapRect(-1775, -2300, 700, 300); //3-1 ceiling
spawn.mapRect(-830, -1600, 300, 50); //2 upper left ledge
spawn.mapRect(250, -2150, 675, 50); //2 upper right ledge
spawn.mapRect(-925, -2300, 100, 400); //3-2 left wall
spawn.mapRect(-600, -2700, 1525, 150); //3-2 ceiling
spawn.mapRect(1075, -2150, 250, 150); //next to upper portal
level.fill.push({
x: -1730,
y: -2300,
width: 870,
height: 1600,
color: "rgba(0,0,0,0.1)"
});
//section 4: upper right portals
spawn.mapRect(1475, -2700, 150, 700); //4-1 left wall
spawn.mapRect(1775, -1650, 250, 150); //4-1 floor-ish
spawn.mapRect(1575, -1505, 450, 555); //below upper right portal
spawn.mapRect(1800, -2250, 400, 50); //4-1 platform 2
spawn.bodyRect(2200, -2250, 25, 300);
spawn.mapRect(2200, -1950, 400, 50); //4-1 platform 1
//spawn.bodyRect(2575, -2600, 25, 650);
spawn.mapRect(2600, -1650, 400, 50); //4-1 platform 0
spawn.mapRect(2200, -1350, 400, 50); //4-1 platform -1
spawn.bodyRect(2200, -1900, 25, 550);
spawn.bodyRect(2575, -1650, 25, 300);
spawn.mapRect(1780, -4200, 820, 1600); //top right corner
spawn.mapRect(800, -4200, 1800, -500); //4-2 ceiling
spawn.mapRect(1075, -3450, 250, 900); //4-2 center block
spawn.mapRect(800, -3450, 125, 900); //4-2 left wall
spawn.mapRect(1550, -4200, 310, 600); //4-2 upper right wall
level.fill.push({
x: 1800,
y: -2200,
width: 225,
height: 550,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 1800,
y: -2600,
width: 400,
height: 400,
color: "rgba(0,0,0,0.1)"
});
level.fill.push({
x: 2200,
y: -2600,
width: 400,
height: 1250,
color: "rgba(0,0,0,0.1)"
});
//section 5: after portals (gone through main portals 3 times)
spawn.mapRect(-700, -2700, 100, 450); //5-1 right wall
spawn.mapRect(-1450, -2700, 900, 50); //5-1 ceiling
spawn.mapRect(-925, -2300, 325, 50); //5-1 right floor
level.fill.push({
x: -1450,
y: -2655,
width: 755,
height: 355,
color: "rgba(0,0,0,0.1)"
});
//top left corner stuff
if (true) {
spawn.mapRect(-1900, -2450, 250, 450); //
} else {
spawn.boost(-1650, -2310, 400);
spawn.mapRect(-2200, -2700, 450, 50); //
spawn.mapRect(-1850, -3000, 500, 50); //
}
//exit room
spawn.mapRect(350, -3000, 50, 100); //exit room left wall
spawn.mapRect(350, -3000, 450, -1700); //exit room ceiling
spawn.bodyRect(350, -2900, 50, 50); //door
spawn.bodyRect(350, -2850, 50, 50); //door
spawn.bodyRect(350, -2800, 50, 50); //door
spawn.bodyRect(350, -2750, 50, 50); //door
level.fillBG.push({
x: 375,
y: -3000,
width: 450,
height: 300,
color: "#d4f4f4"
});
spawn.debris(-800, -50, 400, 6); //16 debris per level
spawn.debris(-1650, -2300, 250, 4); //16 debris per level
spawn.debris(-750, -650, 750, 6); //16 debris per level
//mobs
spawn.randomMob(-650, -100, 0.7); //1-2 left
spawn.randomMob(100, -150, 0.3); //1-2 right
spawn.randomMob(-100, -400, 0); //1-3 right
//spawn.randomMob(-1500, -300, 0.3); //1-4 platform
spawn.randomMob(1450, -450, 0); //2-1 right
spawn.randomMob(1700, -800, 1); //2-1 off the edge. chance is 1 because some enemies just fall
spawn.randomGroup(-550, -1000, -0.3); //2-2
spawn.randomMob(-1550, -1800, 0.7); //3-1 upper platform
//spawn.randomMob(-1225, -1400, 0.3); //3-1 lower platform
spawn.randomMob(450, -2350, 0.3); //3-2 right ledge
//spawn.randomMob(1150, -2250, 0); //3-2 far right
spawn.randomGroup(2400, -2300, -0.3); //4-1 floating
spawn.randomMob(2400, -1450, 0); //4-1 platform -1
spawn.randomMob(2800, -1800, 0.5); //4-1 platform 0
spawn.randomMob(-1100, -2800, 0.5); //5-2 left
spawn.randomMob(-550, -2800, 0.5); //5-2 middle
if (simulation.difficulty > 3) {
if (Math.random() < 0.5) {
spawn.randomLevelBoss(450, -1350, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "laserBoss"]);
} else {
spawn.randomLevelBoss(-300, -3200, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "laserBoss"]);
}
}
powerUps.addRerollToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275);
},
}; };

View File

@@ -647,7 +647,6 @@ const m = {
m.energy -= dmg; m.energy -= dmg;
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) { if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
tech.isDeathAvoidedThisLevel = true tech.isDeathAvoidedThisLevel = true
powerUps.research.changeRerolls(-1) powerUps.research.changeRerolls(-1)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`)

View File

@@ -112,11 +112,6 @@ const powerUps = {
document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}` document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}`
} }
if (tech.renormalization && Math.random() < 0.37 && amount < 0) powerUps.spawn(m.pos.x, m.pos.y, "research"); if (tech.renormalization && Math.random() < 0.37 && amount < 0) powerUps.spawn(m.pos.x, m.pos.y, "research");
if (tech.isResearchReality && amount < 0) {
m.switchWorlds()
simulation.trails()
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
}
if (tech.isRerollHaste) { if (tech.isRerollHaste) {
if (powerUps.research.count === 0) { if (powerUps.research.count === 0) {
tech.researchHaste = 0.66; tech.researchHaste = 0.66;
@@ -141,6 +136,11 @@ const powerUps = {
// simulation.makeTextLog(`${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)} estimated <strong class='color-m'>tech</strong> choices remaining`) // simulation.makeTextLog(`${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)} estimated <strong class='color-m'>tech</strong> choices remaining`)
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`) simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - powerUps.tech.banishLog.length)}`)
} }
if (tech.isResearchReality) {
m.switchWorlds()
simulation.trails()
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
}
powerUps[type].effect(); powerUps[type].effect();
}, },
}, },

View File

@@ -525,7 +525,9 @@ const simulation = {
level.levels.push("basement"); level.levels.push("basement");
level.levels.push("detours"); level.levels.push("detours");
level.levels.push("house"); level.levels.push("house");
level.levels.splice(0, 4); //remove 4 random levels to make up for adding the 4 community levels level.levels.push("testChamber2");
// level.levels.push("vats");
level.levels.splice(0, 5); //remove some random levels to make up for adding the community levels
} }
level.levels = shuffle(level.levels); //shuffles order of maps level.levels = shuffle(level.levels); //shuffles order of maps
level.levels.unshift("intro"); //add level to the start of the randomized levels list level.levels.unshift("intro"); //add level to the start of the randomized levels list
@@ -699,6 +701,7 @@ const simulation = {
let holdTarget; //if player is holding something this remembers it before it gets deleted let holdTarget; //if player is holding something this remembers it before it gets deleted
if (m.holdingTarget) holdTarget = m.holdingTarget; if (m.holdingTarget) holdTarget = m.holdingTarget;
simulation.fallHeight = 3000;
m.fireCDcycle = 0 m.fireCDcycle = 0
m.drop(); m.drop();
m.hole.isOn = false; m.hole.isOn = false;
@@ -993,6 +996,7 @@ const simulation = {
for (let i = 0, len = cons.length; i < len; ++i) { for (let i = 0, len = cons.length; i < len; ++i) {
ctx.moveTo(cons[i].pointA.x, cons[i].pointA.y); ctx.moveTo(cons[i].pointA.x, cons[i].pointA.y);
ctx.lineTo(cons[i].bodyB.position.x, cons[i].bodyB.position.y); ctx.lineTo(cons[i].bodyB.position.x, cons[i].bodyB.position.y);
// ctx.lineTo(cons[i].bodyB.position.x + cons[i].pointB.x, cons[i].bodyB.position.y + cons[i].pointB.y);
} }
for (let i = 0, len = consBB.length; i < len; ++i) { for (let i = 0, len = consBB.length; i < len; ++i) {
ctx.moveTo(consBB[i].bodyA.position.x, consBB[i].bodyA.position.y); ctx.moveTo(consBB[i].bodyA.position.x, consBB[i].bodyA.position.y);

View File

@@ -1579,7 +1579,7 @@ const spawn = {
} }
}; };
}, },
pulsar(x, y, radius = 30) { pulsar(x, y, radius = 40) {
mobs.spawn(x, y, 3, radius, "#f08"); mobs.spawn(x, y, 3, radius, "#f08");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
@@ -1587,10 +1587,11 @@ const spawn = {
me.radius *= 2 me.radius *= 2
me.vertices[1].x = me.position.x + Math.cos(me.angle) * me.radius; //make one end of the triangle longer me.vertices[1].x = me.position.x + Math.cos(me.angle) * me.radius; //make one end of the triangle longer
me.vertices[1].y = me.position.y + Math.sin(me.angle) * me.radius; me.vertices[1].y = me.position.y + Math.sin(me.angle) * me.radius;
me.fireCycle = 0 Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.fireCycle = Infinity
me.fireTarget = { x: 0, y: 0 } me.fireTarget = { x: 0, y: 0 }
me.pulseRadius = Math.min(400, 150 + simulation.difficulty * 3) me.pulseRadius = Math.min(400, 165 + simulation.difficulty * 3)
me.fireDelay = Math.max(70, 180 - simulation.difficulty) me.fireDelay = Math.max(75, 150 - simulation.difficulty * 0.5)
me.isFiring = false me.isFiring = false
me.onHit = function() {}; me.onHit = function() {};
me.canSeeTarget = function() { me.canSeeTarget = function() {
@@ -1681,7 +1682,7 @@ const spawn = {
this.torque += 0.000001 * this.inertia; this.torque += 0.000001 * this.inertia;
} else if (dot < -threshold) { } else if (dot < -threshold) {
this.torque -= 0.000001 * this.inertia; this.torque -= 0.000001 * this.inertia;
} else if (this.fireCycle > 90) { // aim } else if (this.fireCycle > 60) { // aim
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit) this.fireTarget = Vector.add(this.vertices[1], unit)
if (!this.canSeeTarget()) return if (!this.canSeeTarget()) return

View File

@@ -67,7 +67,7 @@
if (index === 'random') { if (index === 'random') {
let options = []; let options = [];
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed()) options.push(i); if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && !tech.tech[i].isLore) options.push(i);
} }
// give a random tech from the tech I don't have // give a random tech from the tech I don't have
if (options.length > 0) { if (options.length > 0) {
@@ -86,6 +86,12 @@
} }
if (!found) return //if name not found don't give any tech if (!found) return //if name not found don't give any tech
} }
if (tech.isMetaAnalysis && tech.tech[index].isJunk) {
tech.giveTech('random', true)
for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "research");
return
}
if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech
tech.tech[index].effect(); //give specific tech tech.tech[index].effect(); //give specific tech
tech.tech[index].count++ tech.tech[index].count++
@@ -1176,8 +1182,8 @@
tech.isBotDamage = false tech.isBotDamage = false
} }
}, { }, {
name: "bot replication", name: "ersatz bots",
description: "<strong class='color-dup'>duplicate</strong> your permanent <strong class='color-bot'>bots</strong><br>remove <strong>all</strong> of your <strong class='color-g'>guns</strong>", description: "<strong>double</strong> your permanent <strong class='color-bot'>bots</strong><br>remove <strong>all</strong> of your <strong class='color-g'>guns</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2000,7 +2006,7 @@
frequency: 1, frequency: 1,
isHealTech: true, isHealTech: true,
allowed() { allowed() {
return m.maxHealth > 1 || tech.isArmorFromPowerUps return m.health > 0.1 && (m.maxHealth > 1 || tech.isArmorFromPowerUps)
}, },
requires: "increased max health", requires: "increased max health",
effect() { effect() {
@@ -2134,9 +2140,9 @@
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return !tech.isImmortal && !tech.isResearchReality return !tech.isImmortal && !tech.isResearchReality && level.onLevel < 6
}, },
requires: "not quantum immortality, perturbation theory", requires: "before level 6, not quantum immortality, perturbation theory",
effect() { effect() {
tech.isSwitchReality = true; tech.isSwitchReality = true;
}, },
@@ -2150,9 +2156,9 @@
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return !tech.isImmortal && !tech.isSwitchReality return !tech.isImmortal && !tech.isSwitchReality && (powerUps.research.count > 2 || build.isExperimentSelection)
}, },
requires: "not quantum immortality, many-worlds", requires: "at least 2 research, not quantum immortality, many-worlds",
effect() { effect() {
tech.isResearchReality = true; tech.isResearchReality = true;
for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false); for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false);
@@ -2167,9 +2173,9 @@
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return (powerUps.research.count > 1 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste return (powerUps.research.count > 2 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste
}, },
requires: "not superdeterminism or Ψ(t) collapse<br>at least 2 research", requires: "not superdeterminism or Ψ(t) collapse<br>at least 3 research",
effect() { effect() {
tech.renormalization = true; tech.renormalization = true;
}, },
@@ -2313,26 +2319,25 @@
remove() { remove() {
tech.isShieldAmmo = false; tech.isShieldAmmo = false;
} }
}, { },
name: "stimulated emission", {
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>but, after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>", name: "meta-analysis",
description: "if you choose a <strong>junk</strong> <strong class='color-m'>tech</strong> you instead get a <br>random non-junk <strong class='color-m'>tech</strong> and spawn <strong>2</strong> <strong class='color-r'>research</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 2,
allowed() { allowed() {
return tech.duplicationChance() < 1 return tech.duplicateChance
}, },
requires: "below 100% duplication chance", requires: "replication",
effect: () => { effect() {
tech.isBayesian = true tech.isMetaAnalysis = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.maxDuplicationEvent()
}, },
remove() { remove() {
tech.isBayesian = false tech.isMetaAnalysis = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
} }
}, { },
{
name: "replication", name: "replication",
description: "<strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>12</strong> junk <strong class='color-m'>tech</strong> to the potential pool", description: "<strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>12</strong> junk <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 9, maxCount: 9,
@@ -2354,7 +2359,28 @@
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
if (this.count > 1) tech.removeJunkTechFromPool(12) if (this.count > 1) tech.removeJunkTechFromPool(12)
} }
}, { },
{
name: "stimulated emission",
description: "<strong>20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>but, after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
maxCount: 1,
count: 0,
frequency: 1,
allowed() {
return tech.duplicationChance() < 1
},
requires: "below 100% duplication chance",
effect: () => {
tech.isBayesian = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.maxDuplicationEvent()
},
remove() {
tech.isBayesian = false
if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal
}
},
{
name: "futures exchange", name: "futures exchange",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to cancel a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance", description: "clicking <strong style = 'font-size:150%;'>×</strong> to cancel a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.5%</strong> power up <strong class='color-dup'>duplication</strong> chance",
maxCount: 1, maxCount: 1,
@@ -2682,27 +2708,6 @@
tech.isSuperDeterminism = false; tech.isSuperDeterminism = false;
} }
}, },
// {
// name: "ammo technology",
// description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-g'>gun</strong> <strong class='color-m'>tech</strong><br>spawn <strong>6</strong> <strong class='color-g'>ammo</strong>",
// maxCount: 1,
// count: 0,
// frequency: 1,
// isNonRefundable: true,
// // isExperimentHide: true,
// // isBadRandomOption: true,
// allowed() {
// return !tech.isEnergyNoAmmo
// },
// requires: "not exciton lattice",
// effect() {
// for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "ammo");
// for (let i = 0, len = tech.tech.length; i < len; i++) {
// if (tech.tech[i].isGunTech) tech.tech[i].frequency *= 2
// }
// },
// remove() {}
// },
//************************************************** //**************************************************
//************************************************** gun //************************************************** gun
//************************************************** tech //************************************************** tech
@@ -4352,23 +4357,6 @@
// } // }
// }, // },
{ {
name: "plasma jet",
description: "increase <strong class='color-plasma'>plasma</strong> <strong>torch's</strong> range by <strong>27%</strong>",
isFieldTech: true,
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
},
requires: "plasma torch",
effect() {
tech.isPlasmaRange += 0.27;
},
remove() {
tech.isPlasmaRange = 1;
}
}, {
name: "plasma-bot", name: "plasma-bot",
description: "a <strong class='color-bot'>bot</strong> uses <strong class='color-f'>energy</strong> to emit <strong class='color-plasma'>plasma</strong><br>that <strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs", description: "a <strong class='color-bot'>bot</strong> uses <strong class='color-f'>energy</strong> to emit <strong class='color-plasma'>plasma</strong><br>that <strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs",
isFieldTech: true, isFieldTech: true,
@@ -4388,7 +4376,26 @@
remove() { remove() {
tech.plasmaBotCount = 0; tech.plasmaBotCount = 0;
} }
}, { },
{
name: "plasma jet",
description: "increase <strong class='color-plasma'>plasma</strong> <strong>torch's</strong> range by <strong>30%</strong>",
isFieldTech: true,
maxCount: 9,
count: 0,
frequency: 1,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && !tech.isExtruder
},
requires: "plasma torch, not micro-extruder",
effect() {
tech.isPlasmaRange += 0.3;
},
remove() {
tech.isPlasmaRange = 1;
}
},
{
name: "micro-extruder", name: "micro-extruder",
description: "<strong class='color-plasma'>plasma</strong> <strong>torch</strong> extrudes a thin <strong class='color-plasma'>hot</strong> wire<br>increases <strong class='color-d'>damage</strong>, and <strong class='color-f'>energy</strong> drain", description: "<strong class='color-plasma'>plasma</strong> <strong>torch</strong> extrudes a thin <strong class='color-plasma'>hot</strong> wire<br>increases <strong class='color-d'>damage</strong>, and <strong class='color-f'>energy</strong> drain",
isFieldTech: true, isFieldTech: true,
@@ -4396,9 +4403,9 @@
count: 0, count: 0,
frequency: 1, frequency: 1,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && tech.isPlasmaRange === 1
}, },
requires: "plasma torch", requires: "plasma torch, not plasma jet",
effect() { effect() {
tech.isExtruder = true; tech.isExtruder = true;
}, },
@@ -5790,5 +5797,6 @@
isFlipFlopOn: null, isFlipFlopOn: null,
isFlipFlopLevelReset: null, isFlipFlopLevelReset: null,
isFlipFlopDamage: null, isFlipFlopDamage: null,
isFlipFlopEnergy: null isFlipFlopEnergy: null,
isMetaAnalysis: null
} }

View File

@@ -1,29 +1,19 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
meta-analysis - if you choose a junk tech you instead get a random tech and spawn 2 research
micro-extruder should have 50% less lag
new community level testChamber2! by Oranger on n-gon discord
(be sure to enable community levels in settings)
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
inductive + MEE + 1st ion + negentrophy + electrolytes + tranceiver chip + dupe chance is ridiculously op fix issue where you have to press z once to get copy to work for simulation.enableConstructMode()
micro-extruder is laggy?
mouse event e.which is deprecated mouse event e.which is deprecated
fix door.isOpen actually meaning isClosed? fix door.isOpen actually meaning isClosed?
(once for me, and a few times for discord) player gets stuck in crouch animation
occurred after rerolling a power up (which triggered a switchWorlds)
can't jump, move slow
m.crouch = false
only fixed itself when you click fire (drones, so no recoil)
fire fixes:
if (m.holdingTarget) m.drop()
so probably the player is getting stuck holding a block, but the block is removed
what removes blocks?
fixed? I added: if (m.holdingTarget) m.drop(); to powerUps.endDraft and to m.switchWorlds
use the floor of portal sensor on the player? to unstuck player
(only once on my computer) once every 7 second check isn't running code (only once on my computer) once every 7 second check isn't running code
power ups don't teleport to exit power ups don't teleport to exit
complex spin statistics isn't activating complex spin statistics isn't activating
@@ -48,19 +38,19 @@ use the floor of portal sensor on the player? to unstuck player
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
add a delay between each fire for pulsar mobs
mob bullets that blow up allow levels to adjust the teleport limit in simulation.checks
draw outline of exploded region, 2 seconds later damage player in region and remove bullet
holding down the field button on fields that don't have a normal field graphic shows a field arc outline to indicate grabbing blocks copy time-like foam to shotgun
mob sniper: draw aim graphics before fire mob sniper: draw aim graphics before fire
tech laser: photon - laser, but it can only move 100 pixels a cycle tech laser: photon - laser, but it can only move 100 pixels a cycle
mob - grows after taking damage mob - after taking damage
mob - attack outwardly after taking damage attack outwardly
grows
teleports
tech- foam is attracted to mobs tech- foam is attracted to mobs
use a gravitational attraction model? use a gravitational attraction model?
@@ -78,15 +68,6 @@ mobile requirements:
tap screen regions to move (WASD) tap screen regions to move (WASD)
reduce font size reduce font size
tech: removes itself after a few levels
gives extra duplication for 2 levels, then removes all duplication
use ship tech to make a mob mode
differences from ship to mob
graphics
take no damage from mob collision
It would be cool if you could exit mob mode
decrease healing effects by 50% decrease healing effects by 50%
decrease level scaling healing reduction decrease level scaling healing reduction
net effect: healing at difficulty 40 (level 10 hard) should be 25% higher then current levels net effect: healing at difficulty 40 (level 10 hard) should be 25% higher then current levels
@@ -99,8 +80,6 @@ bosses should have 2x health, but only do about 50 health damage
boss flag cut damage done to boss by 20x <---- boss flag cut damage done to boss by 20x <----
make bosses not have extra density make bosses not have extra density
tech: spawn a bot after taking collision damage
map: laboratory map: laboratory
rooms with switches that change physics rooms with switches that change physics
gravity room gravity room
@@ -110,11 +89,6 @@ map: laboratory
portal + rotor + falling blocks = perpetual motion room portal + rotor + falling blocks = perpetual motion room
a button that spawns a heal. a button that spawns a heal.
copy time-like foam to other guns?
wave gun
shotgun
nail gun
lore: a tutorial / lore intro lore: a tutorial / lore intro
needs to be optional so it doesn't slow experienced players needs to be optional so it doesn't slow experienced players
put something on the intro map put something on the intro map
@@ -346,6 +320,7 @@ possible names for tech
genetic algorithm genetic algorithm
metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity
stochastic optimization stochastic optimization
meta-analysis
plot script: plot script: