From 784c9332606635ffe81bf6aae5ac736359ec5032 Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 22 Jun 2022 07:21:26 -0700 Subject: [PATCH] power up selection code rewrite rewrite of the tech,gun,field selection code odds of new bugs is pretty high, but the code is shorter and faster, so easier to fix path integral is no longer a JUNK tech lets you choose from every option on next tech emergence is stackable +2 power up choices per stack tech: integrated circuit - if ON +7 power up choices if OFF -1 update matter.js engine 0.17.1 -> 0.18.0 shouldn't change anything big fixes --- js/level.js | 288 ++++++++++++++++- js/player.js | 4 +- js/powerup.js | 805 ++++++++++++++++++++++++++++++---------------- js/simulation.js | 2 +- js/spawn.js | 14 +- js/tech.js | 186 +++++++---- lib/matter.min.js | 4 +- todo.txt | 66 +++- 8 files changed, 984 insertions(+), 385 deletions(-) diff --git a/js/level.js b/js/level.js index 4a78987..8f5db5f 100644 --- a/js/level.js +++ b/js/level.js @@ -20,13 +20,14 @@ const level = { // m.setField("time dilation") // b.giveGuns("nail gun") // b.giveGuns("mine") - // tech.giveTech("needle gun") - // tech.giveTech("stress concentration") + // tech.giveTech("cross disciplinary") + // tech.giveTech("determinism") + // tech.giveTech("pseudoscience") // for (let i = 0; i < 100; ++i) tech.giveTech("nail-bot") - // tech.giveTech("rivet gun") - // tech.giveTech("needle ice") - // tech.giveTech("flash freeze") - // tech.giveTech("superfluidity") + // for (let i = 0; i < 9; ++i) tech.giveTech("emergence") + // tech.giveTech("decoherence") + // tech.giveTech("brainstorming") + // tech.giveTech("path integral") // m.maxHealth = 100 // m.health = m.maxHealth // for (let i = 0; i < 10; i++) tech.giveTech("tungsten carbide") @@ -39,9 +40,12 @@ const level = { // m.immuneCycle = Infinity //you can't take damage // level.difficultyIncrease(40) //30 is near max on hard //60 is near max on why // simulation.enableConstructMode() //used to build maps in testing mode - // level.perplex(); + // level.testChamber2(); // spawn.cellBossCulture(1900, -500) // level.testing(); //not in rotation, used for testing + // for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); + // for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); + // powerUps.research.changeRerolls(100) // spawn.starter(1900, -500, 300) // for (let i = 0; i < 50; ++i) spawn.starter(1900, -500) // spawn.powerUpBoss(1900, -500) @@ -4058,6 +4062,264 @@ const level = { }, -2 * Math.PI / 3) //up left } + }, + testChamber2() { + level.setPosToSpawn(0, -50); //lower start + level.exit.y = level.enter.y - 550; + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + level.exit.x = level.enter.x; + spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); + level.defaultZoom = 2200 + simulation.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#d0d5d5"; + color.map = "#444" + spawn.mapRect(0, -1955, 175, 30); + const removeIndex1 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals + 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 + let portal, portal2, portal3 + const hazard = level.hazard((simulation.isHorizontalFlipped ? -350 - 700 : 350), -2025, 700, 10, 0.4) //laser + spawn.mapRect(340, -2032.5, 20, 25); //laser nose + const hazard2 = level.hazard((simulation.isHorizontalFlipped ? -1775 - 150 : 1775), -2550, 150, 10, 0.4) //laser + spawn.mapRect(1920, -2557.5, 20, 25); //laser nose + const button = level.button(2100, -2600) + const buttonDoor = level.button(600, -550) + const door = level.door(312, -750, 25, 190, 185) + + level.custom = () => { + if (!(m.cycle % 60)) { //so much work to catch blocks caught at the bottom of the vertical portals + let touching = Matter.Query.collides(map[removeIndex1], body) + if (touching.length) { + Matter.Composite.remove(engine.world, touching[0].bodyB); + for (let i = 0, len = body.length; i < len; i++) { + if (body[i].id === touching[0].bodyB.id) { + body.splice(i, 1); + break + } + } + } + touching = Matter.Query.collides(map[removeIndex2], body) + if (touching.length) { + Matter.Composite.remove(engine.world, touching[0].bodyB); + for (let i = 0, len = body.length; i < len; i++) { + if (body[i].id === touching[0].bodyB.id) { + body.splice(i, 1); + break + } + } + } + } + + buttonDoor.query(); + buttonDoor.draw(); + if (buttonDoor.isUp) { + door.isClosing = true + } else { + door.isClosing = false + } + door.openClose(); + + portal[2].query() + portal[3].query() + portal2[2].query() + portal2[3].query() + portal3[2].query() + portal3[3].query() + + if (button.isUp) { + hazard.isOn = false; + hazard2.isOn = false; + } else { + hazard.isOn = true; + hazard2.isOn = true; + } + button.query(); + button.draw(); + + ctx.fillStyle = "#d4f4f4" + ctx.fillRect(-300, -1000, 650, 500) + level.exit.drawAndCheck(); + + level.enter.draw(); + }; + level.customTopLayer = () => { + door.draw(); + hazard.opticalQuery(); + hazard2.opticalQuery(); + portal[0].draw(); + portal[1].draw(); + portal[2].draw(); + portal[3].draw(); + portal2[0].draw(); + portal2[1].draw(); + portal2[2].draw(); + portal2[3].draw(); + portal3[0].draw(); + portal3[1].draw(); + portal3[2].draw(); + portal3[3].draw(); + }; + powerUps.spawnStartingPowerUps(1875, -3075); + + const powerUpPos = shuffle([{ //no debris on this level but 2 random spawn instead + x: -150, + y: -1775 + }, { + x: 2400, + y: -2650 + }, { + x: -175, + y: -1375 + }, { + x: 1325, + y: -150 + }]); + powerUps.chooseRandomPowerUp(powerUpPos[0].x, powerUpPos[0].y); + powerUps.chooseRandomPowerUp(powerUpPos[1].x, powerUpPos[1].y); + //outer wall + spawn.mapRect(2500, -3700, 1200, 3800); //right map wall + spawn.mapRect(-1400, -3800, 1100, 3900); //left map wall + spawn.mapRect(-1400, -4800, 5100, 1200); //map ceiling + spawn.mapRect(-1400, 0, 5100, 1200); //floor + //lower entrance /exit + spawn.mapRect(300, -375, 50, 225); + spawn.bodyRect(312, -150, 25, 140); + spawn.mapRect(300, -10, 50, 50); + spawn.mapVertex(1555, 0, "625 0 75 0 200 -100 500 -100"); //entrance ramp + //upper entrance / exit + spawn.mapRect(-400, -1050, 750, 50); + spawn.mapRect(300, -1050, 50, 300); + // spawn.bodyRect(312, -750, 25, 190); + spawn.mapRect(300, -560, 50, 50); + spawn.bodyRect(750, -725, 125, 125); + spawn.mapRect(1150, -1050, 250, 575); + spawn.mapRect(1725, -550, 50, 200); //walls around portal 3 + spawn.mapRect(1925, -550, 500, 200); + spawn.mapRect(1750, -390, 200, 40); + spawn.mapRect(-400, -550, 1800, 200); + spawn.mapRect(-200, -1700, 150, 25); //platform above exit room + spawn.mapRect(-200, -1325, 350, 25); + //portal 3 angled + spawn.mapRect(2425, -450, 100, 100); + //portal 1 bottom + spawn.mapRect(2290, -12, 375, 100); + spawn.mapRect(2350, -24, 375, 100); + spawn.mapRect(2410, -36, 375, 100); + //portal 1 top + spawn.mapRect(2290, -3012, 375, 50); + spawn.mapRect(2350, -3024, 375, 50); + spawn.mapRect(2410, -3036, 375, 50); + spawn.mapRect(1400, -3000, 1300, 50); //floor + spawn.mapRect(1750, -3050, 250, 75); + spawn.mapRect(1400, -3625, 50, 200); + spawn.mapRect(350, -3625, 50, 225); + spawn.mapRect(350, -3260, 50, 60); + spawn.mapRect(200, -3250, 1240, 50); + spawn.mapRect(1400, -3260, 50, 310); + spawn.bodyRect(1412, -3425, 25, 165); + spawn.mapRect(-150, -2925, 150, 25); + //portal 2 + spawn.mapRect(-300, -2600, 300, 675); //left platform + spawn.mapRect(1400, -2600, 375, 675); //right platform + spawn.mapRect(1925, -2600, 775, 675); //far right platform + spawn.bodyRect(2130, -2660, 50, 50); //button's block + spawn.mapRect(150, -2100, 200, 175); + spawn.mapRect(1050, -2100, 200, 175); + //mobs + spawn.randomMob(1075, -3500, -0.3); + spawn.randomMob(2175, -700, -0.2); + spawn.randomMob(-75, -850, -0.1); + spawn.randomMob(550, -3400, 0); + spawn.randomMob(0, -1175, 0.5); + spawn.randomMob(-75, -1150, 0.5); + spawn.randomMob(1075, -625, 0.5); + spawn.randomMob(800, -3400, -0.3); + spawn.randomMob(1225, -3375, -0.2); + spawn.randomMob(1200, -1125, -0.1); + spawn.randomMob(2050, -950, 0.5); + if (simulation.difficulty > 40) { + spawn.randomMob(2300, -2775, -0.5); + spawn.randomMob(600, -925, -0.5); + spawn.randomMob(1550, -2750, -0.5); + spawn.randomMob(1350, -1150, -0.5); + spawn.randomMob(-75, -1475, 0); + spawn.randomGroup(600, -2600, 0); + } + if (simulation.difficulty > 1) { + if (Math.random() < 0.5) { + spawn.randomLevelBoss(700, -1550); + } else { + spawn.randomLevelBoss(675, -2775); //["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "grenadierBoss"] + } + } + powerUps.addResearchToLevel() //needs to run after mobs are spawned + spawn.secondaryBossChance(1925, -1250) + + if (simulation.isHorizontalFlipped) { //flip the map horizontally + level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit + // level.setPosToSpawn(0, -50); //-x // no need since 0 + button.min.x = -button.min.x - 126 // flip the button horizontally + button.max.x = -button.max.x + 126 // flip the button horizontally + buttonDoor.min.x = -buttonDoor.min.x - 126 // flip the button horizontally + buttonDoor.max.x = -buttonDoor.max.x + 126 // flip the button horizontally + + //this makes the hazard draw, but not collide for reasons I don't understand + //so don't use it, instead just call the hazard differently based on this flip flag + // hazard.min.x = -hazard.min.x - hazard.width //-x-width + // hazard.max.x = -hazard.max.x - hazard.width //-x-width + // hazard2.min.x = -hazard2.min.x - hazard2.width //-x-width + // hazard2.max.x = -hazard2.max.x - hazard2.width //-x-width + portal = level.portal({ + x: -2475, + y: -140 + }, 2 * Math.PI, { //right + x: -2475, + y: -3140 + }, 2 * Math.PI) //right + + portal2 = level.portal({ + x: -75, + y: -2150 + }, -Math.PI / 2, { //up + x: -1325, + y: -2150 + }, -Math.PI / 2) //up + + portal3 = level.portal({ + x: -1850, + y: -585 + }, -Math.PI / 2, { //up + x: -2425, + y: -600 + }, -1 * Math.PI / 3) //up left + + // level.custom = () => { }; + // level.customTopLayer = () => {}; + + } else { + portal = level.portal({ + x: 2475, + y: -140 + }, Math.PI, { //left + x: 2475, + y: -3140 + }, Math.PI) //left + portal2 = level.portal({ + x: 75, + y: -2150 + }, -Math.PI / 2, { //up + x: 1325, + y: -2150 + }, -Math.PI / 2) //up + portal3 = level.portal({ + x: 1850, + y: -585 + }, -Math.PI / 2, { //up + x: 2425, + y: -600 + }, -2 * Math.PI / 3) //up left + } + }, sewers() { const button1 = level.button(6600, 2675) @@ -4075,7 +4337,10 @@ const level = { button1.query(); button1.draw(); ctx.fillStyle = "hsl(175, 15%, 76%)" - ctx.fillRect(9300, 2200, 600, 400) + ctx.fillRect(9100, 2200, 800, 400) + ctx.fillStyle = "rgba(0,0,0,0.03)" //shadows + ctx.fillRect(6250, 2025, 700, 650) + ctx.fillRect(8000, 2025, 600, 575) level.exit.drawAndCheck(); level.enter.draw(); }; @@ -4121,7 +4386,7 @@ const level = { spawn.bodyRect(1450, -300, 150, 50); const xPos = shuffle([600, 1250, 2000]); - spawn.mapRect(xPos[0], -200, 400, 100); + spawn.mapRect(xPos[0], -200, 300, 100); spawn.mapRect(xPos[1], -250, 300, 300); spawn.mapRect(xPos[2], -150, 300, 200); @@ -4228,7 +4493,10 @@ const level = { rotor.rotate(); ctx.fillStyle = "hsl(175, 15%, 76%)" - ctx.fillRect(-9300 - 600, 2200, 600, 400) + ctx.fillRect(-9900, 2200, 800, 400) + ctx.fillStyle = "rgba(0,0,0,0.03)" //shadows + ctx.fillRect(-6950, 2025, 700, 650) + ctx.fillRect(-8600, 2025, 600, 575) level.exit.drawAndCheck(); level.enter.draw(); diff --git a/js/player.js b/js/player.js index 08bd892..e2272e5 100644 --- a/js/player.js +++ b/js/player.js @@ -3367,7 +3367,7 @@ const m = { const drain = m.fieldRegen + 0.0004 if (m.energy > drain) { m.energy -= drain - if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1/4 seconds // and can't regen + if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1 cycle m.isBodiesAsleep = true; function sleep(who) { @@ -3469,7 +3469,7 @@ const m = { x: velocity.x, y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer }); - if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 1/4 seconds + if (m.immuneCycle < m.cycle + 5) m.immuneCycle = m.cycle + 5; //player is immune to damage for 1/4 seconds // move bots to player for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType) { diff --git a/js/powerup.js b/js/powerup.js index 92333b2..a41bae3 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -248,6 +248,7 @@ const powerUps = { } else if (type === "field") { m.setField(index) } else if (type === "tech") { + if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false setTimeout(() => { powerUps.lastTechIndex = index }, 10); simulation.makeTextLog(`tech.giveTech("${tech.tech[index].name}")`); tech.giveTech(index) @@ -270,7 +271,7 @@ const powerUps = { document.getElementById("choose-grid").style.transitionDuration = "0s"; }, 500); - // if (tech.isExtraChoice) { + // if (tech.extraChoices) { // document.body.style.overflowY = "scroll"; // document.body.style.overflowX = "hidden"; // } @@ -304,7 +305,7 @@ const powerUps = { }, endDraft(type, isCanceled = false) { //type should be a gun, tech, or field if (isCanceled) { - if (tech.isCancelTech && Math.random() < 0.94) { + if (tech.isCancelTech && Math.random() < 0.96) { // powerUps.research.use('tech') powerUps[type].effect(); return @@ -330,16 +331,16 @@ const powerUps = { // powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "tech", false); // simulation.makeTextLog(`options exchange: returns 1 tech`) // } - if (tech.isBanish && type === 'tech') { // banish researched tech by adding them to the list of banished tech - const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - for (let i = 0; i < banishLength; i++) { - const index = powerUps.tech.choiceLog.length - i - 1 - if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) { - tech.tech[powerUps.tech.choiceLog[index]].isBanished = true - } - } - simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) - } + // if (tech.isBanish && type === 'tech') { // banish researched tech by adding them to the list of banished tech + // const banishLength = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 + // for (let i = 0; i < banishLength; i++) { + // const index = powerUps.tech.choiceLog.length - i - 1 + // if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) { + // tech.tech[powerUps.tech.choiceLog[index]].isBanished = true + // } + // } + // simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) + // } } if (tech.isAnsatz && powerUps.research.count === 0) { for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); @@ -425,14 +426,14 @@ const powerUps = { powerUps.research.changeRerolls(-1) } powerUps.research.currentRerollCount++ - if (tech.isBanish && type === 'tech') { // banish researched tech - const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - for (let i = 0; i < banishLength; i++) { - const index = powerUps.tech.choiceLog.length - i - 1 - if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true - } - simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) - } + // if (tech.isBanish && type === 'tech') { // banish researched tech + // const banishLength = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 + // for (let i = 0; i < banishLength; i++) { + // const index = powerUps.tech.choiceLog.length - i - 1 + // if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true + // } + // simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) + // } if (tech.isResearchReality) { m.switchWorlds() simulation.trails() @@ -572,81 +573,261 @@ const powerUps = { } } }, + gun: { + name: "gun", + color: "#26a", + size() { + return 35; + }, + effect() { + if (m.alive) { + let text = "" + if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` + text += `

gun

` + + let options = []; + for (let i = 0; i < b.guns.length; i++) { + if (!b.guns[i].have) options.push(i); + } + let totalChoices = Math.min(options.length, tech.isDeterminism ? 1 : 3 + tech.extraChoices) + if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay + + + function removeOption(index) { + for (let i = 0; i < options.length; i++) { + if (options[i] === index) { + options.splice(i, 1) //remove a previous choice from option pool + return + } + } + } + + //check for guns that were a choice last time and remove them + for (let i = 0; i < b.guns.length; i++) { + if (options.length - 1 < totalChoices) break //you have to repeat choices if there are not enough choices left to display + if (b.guns[i].isRecentlyShown) removeOption(i) + } + for (let i = 0; i < b.guns.length; i++) b.guns[i].isRecentlyShown = false //reset recently shown back to zero + + if (options.length > 0) { + for (let i = 0; i < totalChoices; i++) { + const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options + text += `
  ${b.guns[choose].name}
${b.guns[choose].description}
` + b.guns[choose].isRecentlyShown = true + removeOption(choose) + if (options.length < 1) break + } + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + tech.junkResearchNumber = Math.floor(5 * Math.random()) + text += `
` + for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` + text += `
  pseudoscience
` + } else if (powerUps.research.count) { + text += `
` + for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` + text += `
  ${tech.isResearchReality?"alternate reality": "research"}
` + } + if (tech.isOneGun && b.inventory.length > 0) text += `
replaces your current gun
` + document.getElementById("choose-grid").innerHTML = text + powerUps.showDraft(); + } + } + }, + // pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { + // let options = []; + // for (let i = 0; i < who.length; i++) { + // if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) { + // options.push(i); + // } + // } + // //remove repeats from last selection + // const totalChoices = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 + // if (powerUps.gun.choiceLog.length > totalChoices || powerUps.gun.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove + // for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection + // if (options.length > totalChoices) { + // for (let j = 0, len = options.length; j < len; j++) { + // if (powerUps.gun.choiceLog[powerUps.gun.choiceLog.length - 1 - i] === options[j]) { + // options.splice(j, 1) //remove previous choice from option pool + // break + // } + // } + // } + // } + // } + // if (options.length > 0) { + // return options[Math.floor(Math.seededRandom(0, options.length))] + // } + // }, + // effectOld() { + // let choice1 = powerUps.gun.pick(b.guns) + // let choice2 = -1 + // let choice3 = -1 + // if (choice1 > -1) { + // let text = "" + // if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` + // text += `

gun

` + // text += `
  ${b.guns[choice1].name}
${b.guns[choice1].description}
` + // if (!tech.isDeterminism) { + // choice2 = powerUps.gun.pick(b.guns, choice1) + // if (choice2 > -1) text += `
  ${b.guns[choice2].name}
${b.guns[choice2].description}
` + // choice3 = powerUps.gun.pick(b.guns, choice1, choice2) + // if (choice3 > -1) text += `
  ${b.guns[choice3].name}
${b.guns[choice3].description}
` + // } + // if (tech.extraChoices) { + // let choice4 = powerUps.gun.pick(b.guns, choice1, choice2, choice3) + // if (choice4 > -1) text += `
  ${b.guns[choice4].name}
${b.guns[choice4].description}
` + // let choice5 = powerUps.gun.pick(b.guns, choice1, choice2, choice3, choice4) + // if (choice5 > -1) text += `
+ //
  ${b.guns[choice5].name}
${b.guns[choice5].description}
` + // powerUps.gun.choiceLog.push(choice4) + // powerUps.gun.choiceLog.push(choice5) + // } + // powerUps.gun.choiceLog.push(choice1) + // powerUps.gun.choiceLog.push(choice2) + // powerUps.gun.choiceLog.push(choice3) + // // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` + + // if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + // tech.junkResearchNumber = Math.floor(5 * Math.random()) + // text += `
` + // for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` + // text += `
  pseudoscience
` + // } else if (powerUps.research.count) { + // text += `
` + // for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` + // text += `
  ${tech.isResearchReality?"alternate reality": "research"}
` + // } + // if (tech.isOneGun && b.inventory.length > 0) text += `
replaces your current gun
` + // document.getElementById("choose-grid").innerHTML = text + // powerUps.showDraft(); + // } + // } + }, field: { name: "field", color: "#0cf", size() { return 45; }, - pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { - let options = []; - for (let i = 1; i < who.length; i++) { - if (i !== m.fieldMode && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i); - } - //remove repeats from last selection - const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - if (powerUps.field.choiceLog.length > totalChoices || powerUps.field.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove - for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection - if (options.length > totalChoices) { - for (let j = 0, len = options.length; j < len; j++) { - if (powerUps.field.choiceLog[powerUps.field.choiceLog.length - 1 - i] === options[j]) { - options.splice(j, 1) //remove previous choice from option pool - break - } - } - } - } - } - if (options.length > 0) { - // return options[Math.floor(Math.random() * options.length)] - return options[Math.floor(Math.seededRandom(0, options.length))] - } - }, - choiceLog: [], //records all previous choice options effect() { - let choice1 = powerUps.field.pick(m.fieldUpgrades) - let choice2 = -1 - let choice3 = -1 - if (choice1 > -1) { + if (m.alive) { let text = "" if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` text += `

field

` - text += `
  ${m.fieldUpgrades[choice1].name}
${m.fieldUpgrades[choice1].description}
` - powerUps.field.choiceLog.push(choice1) - if (!tech.isDeterminism) { - choice2 = powerUps.field.pick(m.fieldUpgrades, choice1) - if (choice2 > -1) text += `
  ${m.fieldUpgrades[choice2].name}
${m.fieldUpgrades[choice2].description}
` - choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2) - if (choice3 > -1) text += `
  ${m.fieldUpgrades[choice3].name}
${m.fieldUpgrades[choice3].description}
` - powerUps.field.choiceLog.push(choice2) - powerUps.field.choiceLog.push(choice3) - } - if (tech.isExtraChoice) { - let choice4 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3) - if (choice4 > -1) text += `
  ${m.fieldUpgrades[choice4].name}
${m.fieldUpgrades[choice4].description}
` - let choice5 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3, choice4) - if (choice5 > -1) text += `
  ${m.fieldUpgrades[choice5].name}
${m.fieldUpgrades[choice5].description}
` - powerUps.field.choiceLog.push(choice4) - powerUps.field.choiceLog.push(choice5) - } - if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { - tech.junkResearchNumber = Math.floor(4 * Math.random()) - text += `
` - for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` - text += `
  pseudoscience
` - } else if (powerUps.research.count) { - text += `
` - for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` - // text += `
  research
` - text += `  ${tech.isResearchReality?"alternate reality": "research"}` + let options = []; + for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter + if (i !== m.fieldMode) options.push(i); + } + let totalChoices = Math.min(options.length, tech.isDeterminism ? 1 : 3 + tech.extraChoices) + if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay + + function removeOption(index) { + for (let i = 0; i < options.length; i++) { + if (options[i] === index) { + options.splice(i, 1) //remove a previous choice from option pool + return + } + } + } + //check for fields that were a choice last time and remove them + for (let i = 0; i < m.fieldUpgrades.length; i++) { + if (options.length - 1 < totalChoices) break //you have to repeat choices if there are not enough choices left to display + if (m.fieldUpgrades[i].isRecentlyShown) removeOption(i) + } + for (let i = 0; i < m.fieldUpgrades.length; i++) m.fieldUpgrades[i].isRecentlyShown = false //reset recently shown back to zero + + if (options.length > 0) { + for (let i = 0; i < totalChoices; i++) { + const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options + text += `
  ${m.fieldUpgrades[choose].name}
${m.fieldUpgrades[choose].description}
` + m.fieldUpgrades[choose].isRecentlyShown = true + removeOption(choose) + if (options.length < 1) break + } + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + tech.junkResearchNumber = Math.floor(5 * Math.random()) + text += `
` + for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` + text += `
  pseudoscience
` + } else if (powerUps.research.count) { + text += `
` + for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` + text += `
  ${tech.isResearchReality?"alternate reality": "research"}
` + } + document.getElementById("choose-grid").innerHTML = text + powerUps.showDraft(); } - //(${powerUps.research.count}) - // text += `
${simulation.SVGrightMouse} activate the shield with the right mouse
fields shield you from damage
and let you pick up and throw blocks
` - document.getElementById("choose-grid").innerHTML = text - powerUps.showDraft(); } - } + }, + // pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { + // let options = []; + // for (let i = 1; i < who.length; i++) { + // if (i !== m.fieldMode && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i); + // } + // //remove repeats from last selection + // const totalChoices = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 + // if (powerUps.field.choiceLog.length > totalChoices || powerUps.field.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove + // for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection + // if (options.length > totalChoices) { + // for (let j = 0, len = options.length; j < len; j++) { + // if (powerUps.field.choiceLog[powerUps.field.choiceLog.length - 1 - i] === options[j]) { + // options.splice(j, 1) //remove previous choice from option pool + // break + // } + // } + // } + // } + // } + // if (options.length > 0) { + // // return options[Math.floor(Math.random() * options.length)] + // return options[Math.floor(Math.seededRandom(0, options.length))] + // } + // }, + // effectOld() { + // let choice1 = powerUps.field.pick(m.fieldUpgrades) + // let choice2 = -1 + // let choice3 = -1 + // if (choice1 > -1) { + // let text = "" + // if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` + // text += `

field

` + // text += `
  ${m.fieldUpgrades[choice1].name}
${m.fieldUpgrades[choice1].description}
` + // powerUps.field.choiceLog.push(choice1) + // if (!tech.isDeterminism) { + // choice2 = powerUps.field.pick(m.fieldUpgrades, choice1) + // if (choice2 > -1) text += `
  ${m.fieldUpgrades[choice2].name}
${m.fieldUpgrades[choice2].description}
` + // choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2) + // if (choice3 > -1) text += `
  ${m.fieldUpgrades[choice3].name}
${m.fieldUpgrades[choice3].description}
` + // powerUps.field.choiceLog.push(choice2) + // powerUps.field.choiceLog.push(choice3) + // } + // if (tech.extraChoices) { + // let choice4 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3) + // if (choice4 > -1) text += `
  ${m.fieldUpgrades[choice4].name}
${m.fieldUpgrades[choice4].description}
` + // let choice5 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3, choice4) + // if (choice5 > -1) text += `
  ${m.fieldUpgrades[choice5].name}
${m.fieldUpgrades[choice5].description}
` + // powerUps.field.choiceLog.push(choice4) + // powerUps.field.choiceLog.push(choice5) + // } + + // if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + // tech.junkResearchNumber = Math.floor(4 * Math.random()) + // text += `
` + // for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` + // text += `
  pseudoscience
` + // } else if (powerUps.research.count) { + // text += `
` + // for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` + // // text += `
  research
` + // text += `  ${tech.isResearchReality?"alternate reality": "research"}` + // } + // //(${powerUps.research.count}) + // // text += `
${simulation.SVGrightMouse} activate the shield with the right mouse
fields shield you from damage
and let you pick up and throw blocks
` + // document.getElementById("choose-grid").innerHTML = text + // powerUps.showDraft(); + // } + // } }, tech: { name: "tech", @@ -654,53 +835,98 @@ const powerUps = { size() { return 42; }, - choiceLog: [], //records all previous choice options - lastTotalChoices: 0, //tracks how many tech were available for random selection last time a tech was picked up - // banishLog: [], //records all tech permanently removed from the selection pool effect() { if (m.alive) { - function pick(skip1 = null, skip2 = null, skip3 = null, skip4 = null) { - let options = []; + let text = "" + if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` + text += `

tech

` + + let options = []; //generate all options + optionLengthNoDuplicates = 0 + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBanished) { + if (tech.tech[i].frequency > 0) optionLengthNoDuplicates++ + for (let j = 0, len = tech.tech[i].frequency; j < len; j++) options.push(i); + } + } + // console.log(optionLengthNoDuplicates, options.length) + + function removeOption(index) { + for (let i = options.length; i > -1; i--) { + if (index === options[i]) { + options.splice(i, 1) //remove all copies of that option form the options array (some tech are in the options array multiple times because of frequency) + optionLengthNoDuplicates-- + } + if (options.length < 1) return; + } + } + + //set total choices + let totalChoices = tech.isDeterminism ? 1 : 3 + tech.extraChoices + if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay + if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices + // console.log('if not enough options for all the choices') + totalChoices = optionLengthNoDuplicates + if (tech.isBanish) { //when you run out of options eject banish + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i, true) + } + simulation.makeTextLog(`decoherence tech ejected`) + simulation.makeTextLog(`options reset`) + } + } + if (tech.tooManyTechChoices) { + tech.tooManyTechChoices = false + totalChoices = optionLengthNoDuplicates + } + + + + //check for tech that were a choice last time and remove them + if (optionLengthNoDuplicates > totalChoices) { + // console.log('check for tech that were a choice last time and remove them', optionLengthNoDuplicates, options.length) for (let i = 0; i < tech.tech.length; i++) { - if (tech.tech[i].count < tech.tech[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && tech.tech[i].allowed() && !tech.tech[i].isBanished) { - for (let j = 0, len = tech.tech[i].frequency; j < len; j++) options.push(i); - } - } - powerUps.tech.lastTotalChoices = options.length //this is recorded so that banish can know how many tech were available - - const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - if (powerUps.tech.choiceLog.length > totalChoices || powerUps.tech.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove - for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection - if (options.length > totalChoices) { - for (let j = 0, len = options.length; j < len; j++) { - if (powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - 1 - i] === options[j]) { - options.splice(j, 1) //remove previous choice from option pool - break; - } - } + if (optionLengthNoDuplicates > totalChoices) { + if (tech.tech[i].isRecentlyShown) { + // console.log(i) + removeOption(i) } + } else { + break //you have to repeat choices if there are not enough choices left to display } + } + } + for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero + // powerUps.tech.lastTotalChoices = options.length //this is recorded so that banish can know how many tech were available + // console.log(optionLengthNoDuplicates, options.length) + if (options.length > 0) { + for (let i = 0; i < totalChoices; i++) { + if (options.length < 1) break + const choose = options[Math.floor(Math.seededRandom(0, options.length))] //pick an element from the array of options + if (tech.isBanish) { + tech.tech[choose].isBanished = true + if (i === 0) simulation.makeTextLog(`options.length = ${optionLengthNoDuplicates}`) + } + //avoid displaying repeated tech options at the same time + removeOption(choose) + tech.tech[choose].isRecentlyShown = true - if (options.length > 0) { - // const choose = options[Math.floor(Math.random() * options.length)] - const choose = options[Math.floor(Math.seededRandom(0, options.length))] const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : ""; - if (tech.tech[choose].isFieldTech) { text += `
- -
-
-
-         ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}
` + +
+
+
+         ${tech.tech[choose].name} ${isCount}${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}` } else if (tech.tech[choose].isGunTech) { text += `
- -
-
-
-         ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}
` + +
+
+
+         ${tech.tech[choose].name} ${isCount}${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}` } else if (tech.tech[choose].isLore) { text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` } else if (tech.tech[choose].isJunk) { @@ -708,65 +934,28 @@ const powerUps = { } else { text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` } - - // text += `
  ${tech.tech[choose].name}
${tech.tech[choose].description}
` - return choose - } else if (tech.isBanish) { //if no tech options available eject banish tech - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i) - } + if (options.length < 1) break } - } - - let text = "" - if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` - text += `

tech

` - let choice1 = pick() - // console.log(choice1) - let choice2 = null - let choice3 = null - if (choice1 !== null) { - powerUps.tech.choiceLog.push(choice1) - if (!tech.isDeterminism) { - choice2 = pick(choice1) - // if (choice2 > -1) text += `
  ${tech.tech[choice2].name}
${tech.tech[choice2].description}
` - choice3 = pick(choice1, choice2) - // if (choice3 > -1) text += `
  ${tech.tech[choice3].name}
${tech.tech[choice3].description}
` - powerUps.tech.choiceLog.push(choice2) - powerUps.tech.choiceLog.push(choice3) - } - if (tech.isExtraChoice) { - let choice4 = pick(choice1, choice2, choice3) - // if (choice4 > -1) text += `
  ${tech.tech[choice4].name}
${tech.tech[choice4].description}
` - let choice5 = pick(choice1, choice2, choice3, choice4) - // if (choice5 > -1) text += `
  ${tech.tech[choice5].name}
${tech.tech[choice5].description}
` - powerUps.tech.choiceLog.push(choice4) - powerUps.tech.choiceLog.push(choice5) - } - // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` - if (tech.isExtraGunField) { if (Math.random() > 0.5 && b.inventory.length < b.guns.length) { - //bonus gun in tech menu - let choiceGun = powerUps.gun.pick(b.guns) - powerUps.gun.choiceLog.push(choiceGun) - text += `
  ${b.guns[choiceGun].name}
${b.guns[choiceGun].description}
` + let gunOptions = []; + for (let i = 0; i < b.guns.length; i++) { + if (!b.guns[i].have) gunOptions.push(i); + } + const pick = gunOptions[Math.floor(Math.seededRandom(0, gunOptions.length))] //pick an element from the array of options + text += `
  ${b.guns[pick].name}
${b.guns[pick].description}
` } else { - //bonus field in tech menu - let choiceField = powerUps.field.pick(m.fieldUpgrades) - powerUps.field.choiceLog.push(choiceField) - text += `
  ${m.fieldUpgrades[choiceField].name}
${m.fieldUpgrades[choiceField].description}
` + let fieldOptions = []; + for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter + if (i !== m.fieldMode) fieldOptions.push(i); + } + const pick = options[Math.floor(Math.seededRandom(0, fieldOptions.length))] //pick an element from the array of options + text += `
  ${m.fieldUpgrades[pick].name}
${m.fieldUpgrades[pick].description}
` } } - if (tech.tooManyTechChoices) { - tech.tooManyTechChoices-- - for (let i = 0; i < powerUps.tech.lastTotalChoices; i++) pick() - } - if (tech.isBrainstorm && !tech.isBrainstormActive && !simulation.isChoosing) { tech.isBrainstormActive = true let count = 0 - requestAnimationFrame(cycle); function cycle() { count++ @@ -782,8 +971,8 @@ const powerUps = { tech.isBrainstormActive = false } } + requestAnimationFrame(cycle); } - //add in research button or pseudoscience button if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { tech.junkResearchNumber = Math.floor(5 * Math.random()) @@ -796,115 +985,160 @@ const powerUps = { // text += `  research` text += `  ${tech.isResearchReality?"alternate reality": "research"}` } - - // if (tech.isBrainstorm && tech.isBrainstormActive < 4) { - // setTimeout(() => { - // if (simulation.isChoosing) { - // tech.isBrainstormActive++ - // powerUps.tech.effect(); - // //turn off the normal 500ms delay - // document.getElementById("choose-grid").style.pointerEvents = "auto"; - // document.body.style.cursor = "auto"; - // document.getElementById("choose-grid").style.transitionDuration = "0s"; - // } else { - // tech.isBrainstormActive = 0; - // } - // }, 1000); - // } else { - // tech.isBrainstormActive = 0; - // } - document.getElementById("choose-grid").innerHTML = text powerUps.showDraft(); - } } - } - }, - gun: { - name: "gun", - color: "#26a", - size() { - return 35; - }, - pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { - let options = []; - for (let i = 0; i < who.length; i++) { - if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) { - options.push(i); - } - } - - //remove repeats from last selection - const totalChoices = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 - if (powerUps.gun.choiceLog.length > totalChoices || powerUps.gun.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove - for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection - if (options.length > totalChoices) { - for (let j = 0, len = options.length; j < len; j++) { - if (powerUps.gun.choiceLog[powerUps.gun.choiceLog.length - 1 - i] === options[j]) { - options.splice(j, 1) //remove previous choice from option pool - break - } - } - } - } - } - if (options.length > 0) { - // console.log(`random: ${Math.seededRandom(0, options.length)}`) - - return options[Math.floor(Math.seededRandom(0, options.length))] - // return options[Math.floor(Math.random() * options.length)] - } }, - choiceLog: [], //records all previous choice options - effect() { - let choice1 = powerUps.gun.pick(b.guns) - let choice2 = -1 - let choice3 = -1 - if (choice1 > -1) { - let text = "" - if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` - text += `

gun

` - text += `
  ${b.guns[choice1].name}
${b.guns[choice1].description}
` - if (!tech.isDeterminism) { - choice2 = powerUps.gun.pick(b.guns, choice1) - if (choice2 > -1) text += `
  ${b.guns[choice2].name}
${b.guns[choice2].description}
` - choice3 = powerUps.gun.pick(b.guns, choice1, choice2) - if (choice3 > -1) text += `
  ${b.guns[choice3].name}
${b.guns[choice3].description}
` - } - if (tech.isExtraChoice) { - let choice4 = powerUps.gun.pick(b.guns, choice1, choice2, choice3) - if (choice4 > -1) text += `
  ${b.guns[choice4].name}
${b.guns[choice4].description}
` - let choice5 = powerUps.gun.pick(b.guns, choice1, choice2, choice3, choice4) - if (choice5 > -1) text += `
-
  ${b.guns[choice5].name}
${b.guns[choice5].description}
` - powerUps.gun.choiceLog.push(choice4) - powerUps.gun.choiceLog.push(choice5) - } - powerUps.gun.choiceLog.push(choice1) - powerUps.gun.choiceLog.push(choice2) - powerUps.gun.choiceLog.push(choice3) - // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` + // effectOld() { + // if (m.alive) { + // function pick(skip1 = null, skip2 = null, skip3 = null, skip4 = null) { + // let options = []; + // for (let i = 0; i < tech.tech.length; i++) { + // if (tech.tech[i].count < tech.tech[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && tech.tech[i].allowed() && !tech.tech[i].isBanished) { + // for (let j = 0, len = tech.tech[i].frequency; j < len; j++) options.push(i); + // } + // } + // powerUps.tech.lastTotalChoices = options.length //this is recorded so that banish can know how many tech were available - if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { - tech.junkResearchNumber = Math.floor(5 * Math.random()) - text += `
` - for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` - text += `
  pseudoscience
` - } else if (powerUps.research.count) { - text += `
` - for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` - text += `
  ${tech.isResearchReality?"alternate reality": "research"}
` - } - if (tech.isOneGun && b.inventory.length > 0) text += `
replaces your current gun
` - document.getElementById("choose-grid").innerHTML = text - powerUps.showDraft(); - } - } + // const totalChoices = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 + // if (powerUps.tech.choiceLog.length > totalChoices || powerUps.tech.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove + // for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection + // if (options.length > totalChoices) { + // for (let j = 0, len = options.length; j < len; j++) { + // if (powerUps.tech.choiceLog[powerUps.tech.length - 1 - i] === options[j]) { + // options.splice(j, 1) //remove previous choice from option pool + // break; + // } + // } + // } + // } + // } + + // if (options.length > 0) { + // // const choose = options[Math.floor(Math.random() * options.length)] + // const choose = options[Math.floor(Math.seededRandom(0, options.length))] + // const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count+1}x)` : ""; + + // if (tech.tech[choose].isFieldTech) { + // text += `
+ // + //
+ //
+ //
+ //         ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}
` + // } else if (tech.tech[choose].isGunTech) { + // text += `
+ // + //
+ //
+ //
+ //         ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() :tech.tech[choose].description}
` + // } else if (tech.tech[choose].isLore) { + // text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` + // } else if (tech.tech[choose].isJunk) { + // text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` + // } else { + // text += `
  ${tech.tech[choose].name} ${isCount}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` + // } + + // // text += `
  ${tech.tech[choose].name}
${tech.tech[choose].description}
` + // return choose + // } else if (tech.isBanish) { //if no tech options available eject banish tech + // for (let i = 0, len = tech.tech.length; i < len; i++) { + // if (tech.tech[i].name === "decoherence") powerUps.ejectTech(i) + // } + // } + // } + + + // let text = "" + // if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` + // text += `

tech

` + // let choice1 = pick() + // // console.log(choice1) + // let choice2 = null + // let choice3 = null + // if (choice1 !== null) { + // powerUps.tech.choiceLog.push(choice1) + // if (!tech.isDeterminism) { + // choice2 = pick(choice1) + // // if (choice2 > -1) text += `
  ${tech.tech[choice2].name}
${tech.tech[choice2].description}
` + // choice3 = pick(choice1, choice2) + // // if (choice3 > -1) text += `
  ${tech.tech[choice3].name}
${tech.tech[choice3].description}
` + // powerUps.tech.choiceLog.push(choice2) + // powerUps.tech.choiceLog.push(choice3) + // } + // if (tech.extraChoices) { + // let choice4 = pick(choice1, choice2, choice3) + // // if (choice4 > -1) text += `
  ${tech.tech[choice4].name}
${tech.tech[choice4].description}
` + // let choice5 = pick(choice1, choice2, choice3, choice4) + // // if (choice5 > -1) text += `
  ${tech.tech[choice5].name}
${tech.tech[choice5].description}
` + // powerUps.tech.choiceLog.push(choice4) + // powerUps.tech.choiceLog.push(choice5) + // } + // // if (powerUps.research.count) text += `
  research ${powerUps.research.count}
` + + // if (tech.isExtraGunField) { + // if (Math.random() > 0.5 && b.inventory.length < b.guns.length) { + // //bonus gun in tech menu + // let choiceGun = powerUps.gun.pick(b.guns) + // powerUps.gun.choiceLog.push(choiceGun) + // text += `
  ${b.guns[choiceGun].name}
${b.guns[choiceGun].description}
` + // } else { + // //bonus field in tech menu + // let choiceField = powerUps.field.pick(m.fieldUpgrades) + // powerUps.field.choiceLog.push(choiceField) + // text += `
  ${m.fieldUpgrades[choiceField].name}
${m.fieldUpgrades[choiceField].description}
` + // } + // } + // if (tech.tooManyTechChoices) { + // tech.tooManyTechChoices-- + // for (let i = 0; i < powerUps.tech.lastTotalChoices; i++) pick() + // } + + // if (tech.isBrainstorm && !tech.isBrainstormActive && !simulation.isChoosing) { + // tech.isBrainstormActive = true + // let count = 0 + // requestAnimationFrame(cycle); + + // function cycle() { + // count++ + // if (count < tech.brainStormDelay * 5 && simulation.isChoosing) { + // if (!(count % tech.brainStormDelay)) { + // powerUps.tech.effect(); + // document.getElementById("choose-grid").style.pointerEvents = "auto"; //turn off the normal 500ms delay + // document.body.style.cursor = "auto"; + // document.getElementById("choose-grid").style.transitionDuration = "0s"; + // } + // requestAnimationFrame(cycle); + // } else { + // tech.isBrainstormActive = false + // } + // } + // } + + // //add in research button or pseudoscience button + // if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + // tech.junkResearchNumber = Math.floor(5 * Math.random()) + // text += `
` + // for (let i = 0; i < tech.junkResearchNumber; i++) text += `
` + // text += `
  pseudoscience
` + // } else if (powerUps.research.count) { + // text += `
` + // for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `
` + // // text += `
  research
` + // text += `  ${tech.isResearchReality?"alternate reality": "research"}` + // } + // document.getElementById("choose-grid").innerHTML = text + // powerUps.showDraft(); + // } + // } + // } }, onPickUp(who) { powerUps.research.currentRerollCount = 0 - if (tech.isTechDamage && who.name === "tech") m.damage(0.11) + if (tech.isTechDamage && who.name === "tech") m.damage(0.11 + 0.11 * tech.isEnergyHealth) if (tech.isMassEnergy) m.energy += 2; if (tech.isMineDrop && bullet.length < 150 && Math.random() < 0.6) { if (tech.isLaserMine && input.down) { @@ -1027,10 +1261,8 @@ const powerUps = { for (let i = 0; i < 3; i++) powerUps.spawnRandomPowerUp(x, y); } }, - ejectTech(choose = 'random') { - if (!simulation.isChoosing) - - + ejectTech(choose = 'random', isOverride = false) { + if (!simulation.isChoosing || isOverride) { //find which tech you have if (choose === 'random') { const have = [] @@ -1063,22 +1295,23 @@ const powerUps = { return false } } else if (tech.tech[choose].count) { - // simulation.makeTextLog(`
  ${tech.tech[choose].name} was ejected`, 600) //message about what tech was lost - simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`) + // simulation.makeTextLog(`
  ${tech.tech[choose].name} was ejected`, 600) //message about what tech was lost + simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`) - for (let i = 0; i < tech.tech[choose].count; i++) { - powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); - powerUp[powerUp.length - 1].isDuplicated = true + for (let i = 0; i < tech.tech[choose].count; i++) { + powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); + powerUp[powerUp.length - 1].isDuplicated = true + } + // remove a random tech from the list of tech you have + tech.tech[choose].remove(); + tech.tech[choose].count = 0; + tech.tech[choose].isLost = true; + simulation.updateTechHUD(); + m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech + return true + } else { + return false } - // remove a random tech from the list of tech you have - tech.tech[choose].remove(); - tech.tech[choose].count = 0; - tech.tech[choose].isLost = true; - simulation.updateTechHUD(); - m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech - return true - } else { - return false } }, pauseEjectTech(index) { diff --git a/js/simulation.js b/js/simulation.js index d73b16f..d196a85 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -105,7 +105,7 @@ const simulation = { simulation.isTimeSkipping = true; for (let i = 0; i < cycles; i++) { simulation.cycle++; - // m.walk_cycle += (m.flipLegs * m.Vx) * 0.5; //makes the legs look like they are moving fast (it's times 0.5 because when they move too fast it's a blur) + // m.walk_cycle += (m.flipLegs * m.Vx) * 0.5; //makes the legs look like they are moving fast this is just gonna run for each method call since it needs some tweaking simulation.gravity(); Engine.update(engine, simulation.delta); // level.custom(); diff --git a/js/spawn.js b/js/spawn.js index 48e0fa4..ac13490 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1,7 +1,7 @@ //main object for spawning things in a level const spawn = { nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"], - // other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss //these need a particular level to work so they are not included in the random pool + // other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss //these need a particular level to work so they are not included in the random pool randomBossList: [ "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", @@ -3576,7 +3576,7 @@ const spawn = { ctx.setLineDash([]); } }, - sprayBoss(x, y, radius = 35, isSpawnBossPowerUp = true) { + sprayBoss(x, y, radius = 40, isSpawnBossPowerUp = true) { mobs.spawn(x, y, 16, radius, "rgb(255,255,255)"); let me = mob[mob.length - 1]; me.isBoss = true; @@ -3588,7 +3588,7 @@ const spawn = { me.frictionAir = 0; me.restitution = 1 spawn.spawnOrbitals(me, radius + 50 + 125 * Math.random(), 1) - Matter.Body.setDensity(me, 0.0022 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.002 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.damageReduction = 0.09 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.startingDamageReduction = me.damageReduction me.isInvulnerable = false @@ -3630,8 +3630,8 @@ const spawn = { if (this.speed < 0.01) { Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(player.position, this.position)), 0.1)); } else { - if (Math.abs(this.velocity.y) < 11) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.07 }); - if (Math.abs(this.velocity.x) < 8) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.07, y: this.velocity.y }); + if (Math.abs(this.velocity.y) < 10) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.05 }); + if (Math.abs(this.velocity.x) < 8) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.05, y: this.velocity.y }); } } me.burstFire = function() { @@ -4816,8 +4816,8 @@ const spawn = { me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; me.onDeath = function() { if (simulation.difficulty > 11) { //explode AoE - const radius = 100 + simulation.difficulty + 60 * Math.random() - if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(this.position, player.position)) < radius) m.damage(0.0004 * radius * simulation.dmgScale); + const radius = 100 + 0.5 * simulation.difficulty + 50 * Math.random() + if (m.immuneCycle < m.cycle && Vector.magnitude(Vector.sub(this.position, player.position)) < radius) m.damage(0.0003 * radius * simulation.dmgScale); simulation.drawList.push({ //add dmg to draw queue x: this.position.x, y: this.position.y, diff --git a/js/tech.js b/js/tech.js index b174b70..7109ddc 100644 --- a/js/tech.js +++ b/js/tech.js @@ -4,6 +4,7 @@ const tech = { for (let i = 0, len = tech.tech.length; i < len; i++) { tech.tech[i].count = 0 tech.tech[i].isLost = false + tech.tech[i].isBanished = false tech.tech[i].remove(); if (tech.tech[i].isJunk) { tech.tech[i].frequency = 0 @@ -224,7 +225,7 @@ const tech = { damageFromTech() { let dmg = 1 //m.fieldDamage if (tech.isDeathSkipTime) dmg *= 1.67 - if (tech.isNoDraftPause) dmg *= 1.4 + if (tech.isNoDraftPause) dmg *= 1.34 if (tech.isCloakingDamage) dmg *= 1.35 if (tech.isTechDamage) dmg *= 1.9 if (tech.isMaxEnergyTech) dmg *= 1.5 @@ -1794,6 +1795,24 @@ const tech = { tech.isFlipFlopDamage = false; } }, + { + name: "integrated circuit", + description: "if ON +7 power up choices
if OFF -1 power up choices", + maxCount: 1, + count: 0, + frequency: 4, + frequencyDefault: 4, + allowed() { + return (tech.isFlipFlop || tech.isRelay) && !tech.isDeterminism + }, + requires: "ON/OFF tech not determinism", + effect() { + tech.isFlipFlopChoices = true //do you have this tech + }, + remove() { + tech.isFlipFlopChoices = false + } + }, { name: "transistor", description: "if ON generate 20 energy per second
if OFF drain 1 energy per second", @@ -2107,7 +2126,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isTechDamage && !tech.isMutualism //&& !tech.isAmmoFromHealth && !tech.isRewindGun + return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isMutualism //&& !tech.isAmmoFromHealth && !tech.isRewindGun }, requires: "not Zeno, ergodicity, piezoelectricity, CPT, antiscience, mutualism", effect: () => { @@ -2494,10 +2513,8 @@ const tech = { count: 0, frequency: 1, frequencyDefault: 1, - allowed() { - return !tech.isEnergyHealth - }, - requires: "not mass-energy", + allowed() { return true }, + requires: "", effect() { tech.isTechDamage = true; }, @@ -2776,7 +2793,7 @@ const tech = { { name: "Ψ(t) collapse", link: `Ψ(t) collapse`, - description: `after you research enter an alternate reality
spawn ${powerUps.orb.research(14)}`, + description: `after you research enter an alternate reality
spawn ${powerUps.orb.research(17)}`, maxCount: 1, count: 0, frequency: 1, @@ -2785,7 +2802,7 @@ const tech = { return !tech.isSwitchReality && !tech.isCollisionRealitySwitch && !tech.isJunkResearch }, requires: "not many-worlds, non-unitary, pseudoscience", - bonusResearch: 14, + bonusResearch: 17, effect() { tech.isResearchReality = true; for (let i = 0; i < this.bonusResearch; i++) powerUps.spawn(m.pos.x + Math.random() * 60, m.pos.y + Math.random() * 60, "research", false); @@ -2958,8 +2975,8 @@ const tech = { }, { name: "emergence", - description: "tech, fields, and guns have 5 choices
+5% JUNK to tech pool", - maxCount: 1, + description: "tech, fields, and guns have +2 choices
+4% JUNK to tech pool", + maxCount: 9, count: 0, frequency: 1, frequencyDefault: 1, @@ -2968,21 +2985,41 @@ const tech = { }, requires: "not determinism", effect: () => { - tech.isExtraChoice = true; - this.refundAmount += tech.addJunkTechToPool(0.05) + tech.extraChoices += 2; + this.refundAmount += tech.addJunkTechToPool(0.04) }, refundAmount: 0, remove() { - tech.isExtraChoice = false; + tech.extraChoices = 0; if (this.count > 0 && this.refundAmount > 0) { tech.removeJunkTechFromPool(this.refundAmount) this.refundAmount = 0 } } }, + { + name: "path integral", + link: `path integral`, + description: "your next tech choice
presents every possible option", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isNonRefundable: true, + // isJunk: true, + allowed() { return true }, + requires: "", + effect() { + tech.tooManyTechChoices = 1 + // for (let i = 0; i < this.bonusResearch; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); + }, + remove() { + tech.tooManyTechChoices = 0 + } + }, { name: "determinism", - description: "spawn 5 tech, but you have only
1 choice for tech, fields, and guns", + description: "spawn 5 tech
only 1 choice for tech, fields, and guns", maxCount: 1, count: 0, frequency: 1, @@ -2990,9 +3027,9 @@ const tech = { isBadRandomOption: true, isNonRefundable: true, allowed() { - return !tech.isExtraChoice && !tech.isExtraGunField + return !tech.extraChoices && !tech.isExtraGunField && !tech.isFlipFlopChoices }, - requires: "NOT EXPERIMENT MODE, not emergence, cross disciplinary", + requires: "NOT EXPERIMENT MODE, not emergence, cross disciplinary, integrated circuit", effect: () => { tech.isDeterminism = true; //if you change the number spawned also change it in Born rule @@ -3019,7 +3056,7 @@ const tech = { }, { name: "superdeterminism", - description: `spawn 5 tech, but you have no cancel
and ${powerUps.orb.research(1)}, no longer spawn`, + description: `spawn 5 tech
you have no cancel and ${powerUps.orb.research(1)}, no longer spawn`, maxCount: 1, count: 0, frequency: 4, @@ -3106,7 +3143,7 @@ const tech = { { name: "eternalism", // description: `increase damage by 60%, but time doesn't pause
while choosing a choosing a field, tech, or gun`, //${powerUps.orb.heal()} or - description: "+40% damage
time can't be paused (time can be dilated)", + description: "+34% damage
time can't be paused (time can be dilated)", maxCount: 1, count: 0, frequency: 1, @@ -3253,7 +3290,7 @@ const tech = { { name: "options exchange", link: `options exchange`, - description: `clicking × for a field, tech, or gun has a 94%
chance to randomize choices and not cancel`, + description: `clicking × for a field, tech, or gun has a 96%
chance to randomize choices and not cancel`, maxCount: 1, count: 0, frequency: 1, @@ -3564,7 +3601,7 @@ const tech = { allowed() { return !tech.isSuperDeterminism && tech.duplicationChance() > 0 && powerUps.research.count > 1 }, - requires: "NOT EXPERIMENT MODE, some duplication, not super determinism", + requires: "NOT EXPERIMENT MODE, some duplication, not superdeterminism", effect: () => { powerUps.research.changeRerolls(-2) simulation.makeTextLog(`m.research -= 2`) @@ -3602,7 +3639,7 @@ const tech = { // text = `` // let num = 3 - // if (tech.isExtraChoice) num = 5 + // if (tech.extraChoices) num = 5 // if (tech.isDeterminism) num = 1 // for (let i = 0; i < num; i++) { // const index = powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - i - 1] @@ -3627,7 +3664,7 @@ const tech = { // effect: () => { // powerUps.research.changeRerolls(-2) // let num = 3 - // if (tech.isExtraChoice) num = 5 + // if (tech.extraChoices) num = 5 // if (tech.isDeterminism) num = 1 // for (let i = 0; i < num; i++) { // const index = powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - i - 1] @@ -9570,7 +9607,7 @@ const tech = { remove() {} }, // { - // name: "JUNKie", //just crashes the game + // name: "JUNKie", //just crashes the game // description: "all junk", // maxCount: 1, // count: 0, @@ -9591,27 +9628,6 @@ const tech = { // tech.tooManyTechChoices = 0 // } // }, - { - name: "path integral", - link: `path integral`, - // description: "your next 3 tech choices
present almost every possible option", - description: "your next tech choice
presents almost every possible option", - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - isNonRefundable: true, - isJunk: true, - allowed() { return true }, - requires: "", - effect() { - tech.tooManyTechChoices = 1 - for (let i = 0; i < this.bonusResearch; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); - }, - remove() { - tech.tooManyTechChoices = 0 - } - }, { name: "rule 30", maxCount: 1, @@ -9625,7 +9641,7 @@ const tech = { effect() {}, remove() {}, state: [ - [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + [Math.random() > 0.8, false, false, false, Math.random() > 0.8, false, false, false, false, false, false, false, false, false, true, false, false, false, Math.random() > 0.8, false, false, false, Math.random() > 0.8, false, false, false, false, Math.random() > 0.8, false] ], rule(state, a, b, c) { //30 @@ -9640,25 +9656,68 @@ const tech = { }, id: 0, descriptionFunction() { - - if (this.id === 0 && Math.random() < 0.5) { - // for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed - this.name = "rule 90" - this.link = `${this.name}` - // console.log(this.name) - this.state[0] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false] - this.rule = function(state, a, b, c) { - if (state[a] && state[b] && state[c]) return false; // TTT => F - if (state[a] && state[b] && !state[c]) return true; // TTF => T - if (state[a] && !state[b] && state[c]) return false; //TFT => F - if (state[a] && !state[b] && !state[c]) return true; //TFF => T - if (!state[a] && state[b] && state[c]) return true; //FTT => T - if (!state[a] && state[b] && !state[c]) return false; //FTF => F - if (!state[a] && !state[b] && state[c]) return true; //FFT => T - if (!state[a] && !state[b] && !state[c]) return false; //FFF => F + const loop = () => { + if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) + let b = []; //produce next row + b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around + for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array + b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1)); + } + b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around + this.state.push(b) + if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML + if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research"); + setTimeout(() => { loop() }, 400); } } - + setTimeout(() => { loop() }, 400); + this.id++ + return `${this.outputText()}` + }, + outputText() { + let text = "" + for (let j = 0; j < this.state.length; j++) { + text += "

" + for (let i = 0; i < this.state[j].length; i++) { + if (this.state[j][i]) { + text += "⬛" //"█" //"■" + } else { + text += "⬜" //"    " //"□" + } + } + text += "

" + } + return text + }, + }, + { + name: "rule 90", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() {}, + remove() {}, + state: [ + [false, false, false, false, Math.random() > 0.8, false, false, false, false, Math.random() > 0.8, false, false, false, Math.random() > 0.8, true, true, false, false, false, false, Math.random() > 0.8, Math.random() > 0.8, false, false, false, false, false, false, Math.random() > 0.8] + ], + rule(state, a, b, c) { //90 + if (state[a] && state[b] && state[c]) return false; // TTT => F + if (state[a] && state[b] && !state[c]) return true; // TTF => T + if (state[a] && !state[b] && state[c]) return false; //TFT => F + if (state[a] && !state[b] && !state[c]) return true; //TFF => T + if (!state[a] && state[b] && state[c]) return true; //FTT => T + if (!state[a] && state[b] && !state[c]) return false; //FTF => F + if (!state[a] && !state[b] && state[c]) return true; //FFT => T + if (!state[a] && !state[b] && !state[c]) return false; //FFF => F + }, + id: 90, + descriptionFunction() { + // this.link = `${this.name}` const loop = () => { if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) let b = []; //produce next row @@ -9955,7 +10014,7 @@ const tech = { isFarAwayDmg: null, isEntanglement: null, isMassEnergy: null, - isExtraChoice: null, + extraChoices: null, laserBotCount: null, dynamoBotCount: null, nailBotCount: null, @@ -10134,6 +10193,7 @@ const tech = { // isFlipFlopLevelReset: null, isFlipFlopDamage: null, isFlipFlopEnergy: null, + isFlipFlopChoices: null, isRelay: null, relayIce: null, isMetaAnalysis: null, diff --git a/lib/matter.min.js b/lib/matter.min.js index da8f1e1..29d25db 100644 --- a/lib/matter.min.js +++ b/lib/matter.min.js @@ -1,6 +1,6 @@ /*! - * matter-js 0.17.1 by @liabru + * matter-js 0.18.0 by @liabru * http://brm.io/matter-js/ * License MIT */ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Matter",[],t):"object"==typeof exports?exports.Matter=t():e.Matter=t()}(this,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=22)}([function(e,t){var n={};e.exports=n,function(){n._nextId=0,n._seed=0,n._nowStartTime=+new Date,n._warnedOnce={},n._decomp=null,n.extend=function(e,t){var i,o;"boolean"==typeof t?(i=2,o=t):(i=1,o=!0);for(var r=i;r0;t--){var i=Math.floor(n.random()*(t+1)),o=e[t];e[t]=e[i],e[i]=o}return e},n.choose=function(e){return e[Math.floor(n.random()*e.length)]},n.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},n.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},n.isFunction=function(e){return"function"==typeof e},n.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},n.isString=function(e){return"[object String]"===toString.call(e)},n.clamp=function(e,t,n){return en?n:e},n.sign=function(e){return e<0?-1:1},n.now=function(){if("undefined"!=typeof window&&window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return Date.now?Date.now():new Date-n._nowStartTime},n.random=function(t,n){return n=void 0!==n?n:1,(t=void 0!==t?t:0)+e()*(n-t)};var e=function(){return n._seed=(9301*n._seed+49297)%233280,n._seed/233280};n.colorToNumber=function(e){return 3==(e=e.replace("#","")).length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},n.logLevel=1,n.log=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.info=function(){console&&n.logLevel>0&&n.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warn=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warnOnce=function(){var e=Array.prototype.slice.call(arguments).join(" ");n._warnedOnce[e]||(n.warn(e),n._warnedOnce[e]=!0)},n.deprecated=function(e,t,i){e[t]=n.chain((function(){n.warnOnce("🔅 deprecated 🔅",i)}),e[t])},n.nextId=function(){return n._nextId++},n.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;ne.max.x&&(e.max.x=o.x),o.xe.max.y&&(e.max.y=o.y),o.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},n.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},n.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},n.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},n.shift=function(e,t){var n=e.max.x-e.min.x,i=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+i}},function(e,t){var n={};e.exports=n,n.create=function(e,t){return{x:e||0,y:t||0}},n.clone=function(e){return{x:e.x,y:e.y}},n.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},n.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},n.rotate=function(e,t,n){var i=Math.cos(t),o=Math.sin(t);n||(n={});var r=e.x*i-e.y*o;return n.y=e.x*o+e.y*i,n.x=r,n},n.rotateAbout=function(e,t,n,i){var o=Math.cos(t),r=Math.sin(t);i||(i={});var a=n.x+((e.x-n.x)*o-(e.y-n.y)*r);return i.y=n.y+((e.x-n.x)*r+(e.y-n.y)*o),i.x=a,i},n.normalise=function(e){var t=n.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},n.dot=function(e,t){return e.x*t.x+e.y*t.y},n.cross=function(e,t){return e.x*t.y-e.y*t.x},n.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},n.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},n.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},n.mult=function(e,t){return{x:e.x*t,y:e.y*t}},n.div=function(e,t){return{x:e.x/t,y:e.y/t}},n.perp=function(e,t){return{x:(t=!0===t?-1:1)*-e.y,y:t*e.x}},n.neg=function(e){return{x:-e.x,y:-e.y}},n.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x)},n._temp=[n.create(),n.create(),n.create(),n.create(),n.create(),n.create()]},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.create=function(e,t){for(var n=[],i=0;i0)return!1}return!0},i.scale=function(e,t,n,r){if(1===t&&1===n)return e;var a,s;r=r||i.centre(e);for(var l=0;l=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},i.hull=function(e){var t,n,i=[],r=[];for((e=e.slice(0)).sort((function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y})),n=0;n=2&&o.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];i.length>=2&&o.cross3(i[i.length-2],i[i.length-1],t)<=0;)i.pop();i.push(t)}return i.pop(),r.pop(),i.concat(r)}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.on=function(e,t,n){for(var i,o=t.split(" "),r=0;r0){n||(n={}),i=t.split(" ");for(var c=0;c0&&r.rotateAbout(a.position,n,e.position,a.position)}},i.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y,e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},i.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},i.translate=function(e,t){i.setPosition(e,r.add(e.position,t))},i.rotate=function(e,t,n){if(n){var o=Math.cos(t),r=Math.sin(t),a=e.position.x-n.x,s=e.position.y-n.y;i.setPosition(e,{x:n.x+(a*o-s*r),y:n.y+(a*r+s*o)}),i.setAngle(e,e.angle+t)}else i.setAngle(e,e.angle+t)},i.scale=function(e,t,n,r){var a=0,s=0;r=r||e.position;for(var u=0;u0&&(a+=d.area,s+=d.inertia),d.position.x=r.x+(d.position.x-r.x)*t,d.position.y=r.y+(d.position.y-r.y)*n,l.update(d.bounds,d.vertices,e.velocity)}e.parts.length>1&&(e.area=a,e.isStatic||(i.setMass(e,e.density*a),i.setInertia(e,s))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},i.update=function(e,t,n,i){var a=Math.pow(t*n*e.timeScale,2),s=1-e.frictionAir*n*e.timeScale,u=e.position.x-e.positionPrev.x,d=e.position.y-e.positionPrev.y;e.velocity.x=u*s*i+e.force.x/e.mass*a,e.velocity.y=d*s*i+e.force.y/e.mass*a,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*s*i+e.torque/e.inertia*a,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(o.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity),p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},i.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var i=t.x-e.position.x,o=t.y-e.position.y;e.torque+=i*n.y-o*n.x},i._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n0&&r.motion=r.sleepThreshold&&i.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else i.set(r,!1)}},i.afterCollisions=function(e,t){for(var n=t*t*t,o=0;oi._motionWakeThreshold*n&&i.set(c,!1)}}}},i.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||o.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&o.trigger(e,"sleepEnd"))}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2),a=n(7),s=n(1),l=n(10),c=n(0);i._warming=.4,i._torqueDampen=1,i._minLength=1e-6,i.create=function(e){var t=e;t.bodyA&&!t.pointA&&(t.pointA={x:0,y:0}),t.bodyB&&!t.pointB&&(t.pointB={x:0,y:0});var n=t.bodyA?r.add(t.bodyA.position,t.pointA):t.pointA,i=t.bodyB?r.add(t.bodyB.position,t.pointB):t.pointB,o=r.magnitude(r.sub(n,i));t.length=void 0!==t.length?t.length:o,t.id=t.id||c.nextId(),t.label=t.label||"Constraint",t.type="constraint",t.stiffness=t.stiffness||(t.length>0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var a={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(a.type="pin",a.anchors=!1):t.stiffness<.9&&(a.type="spring"),t.render=c.extend(a,t.render),t},i.preSolveAll=function(e){for(var t=0;t0&&(d.position.x+=c.x,d.position.y+=c.y),0!==c.angle&&(o.rotate(d.vertices,c.angle,n.position),l.rotate(d.axes,c.angle),u>0&&r.rotateAbout(d.position,c.angle,n.position,d.position)),s.update(d.bounds,d.vertices,n.velocity)}c.angle*=i._warming,c.x*=i._warming,c.y*=i._warming}}},i.pointAWorld=function(e){return{x:(e.bodyA?e.bodyA.position.x:0)+e.pointA.x,y:(e.bodyA?e.bodyA.position.y:0)+e.pointA.y}},i.pointBWorld=function(e){return{x:(e.bodyB?e.bodyB.position.x:0)+e.pointB.x,y:(e.bodyB?e.bodyB.position.y:0)+e.pointB.y}}},function(e,t,n){var i={};e.exports=i;var o=n(17);i.create=function(e,t){var n=e.bodyA,o=e.bodyB,r=e.parentA,a=e.parentB,s={id:i.id(n,o),bodyA:n,bodyB:o,contacts:{},activeContacts:[],separation:0,isActive:!0,confirmedActive:!0,isSensor:n.isSensor||o.isSensor,timeCreated:t,timeUpdated:t,inverseMass:r.inverseMass+a.inverseMass,friction:Math.min(r.friction,a.friction),frictionStatic:Math.max(r.frictionStatic,a.frictionStatic),restitution:Math.max(r.restitution,a.restitution),slop:Math.max(r.slop,a.slop)};return i.update(s,e,t),s},i.update=function(e,t,n){var r=e.contacts,a=t.supports,s=e.activeContacts,l=t.parentA,c=t.parentB;if(e.collision=t,e.inverseMass=l.inverseMass+c.inverseMass,e.friction=Math.min(l.friction,c.friction),e.frictionStatic=Math.max(l.frictionStatic,c.frictionStatic),e.restitution=Math.max(l.restitution,c.restitution),e.slop=Math.max(l.slop,c.slop),s.length=0,t.collided){for(var u=0;u0&&o.area(C)1?(v=a.create(r.extend({parts:m.slice(0)},i)),a.setPosition(v,{x:e,y:t}),v):m[0]}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.create=function(e){var t={};return e||o.log("Mouse.create: element was undefined, defaulting to document.body","warn"),t.element=e||document.body,t.absolute={x:0,y:0},t.position={x:0,y:0},t.mousedownPosition={x:0,y:0},t.mouseupPosition={x:0,y:0},t.offset={x:0,y:0},t.scale={x:1,y:1},t.wheelDelta=0,t.button=-1,t.pixelRatio=parseInt(t.element.getAttribute("data-pixel-ratio"),10)||1,t.sourceEvents={mousemove:null,mousedown:null,mouseup:null,mousewheel:null},t.mousemove=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&(t.button=0,e.preventDefault()),t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.sourceEvents.mousemove=e},t.mousedown=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches?(t.button=0,e.preventDefault()):t.button=e.button,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mousedownPosition.x=t.position.x,t.mousedownPosition.y=t.position.y,t.sourceEvents.mousedown=e},t.mouseup=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&e.preventDefault(),t.button=-1,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mouseupPosition.x=t.position.x,t.mouseupPosition.y=t.position.y,t.sourceEvents.mouseup=e},t.mousewheel=function(e){t.wheelDelta=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail)),e.preventDefault()},i.setElement(t,t.element),t},i.setElement=function(e,t){e.element=t,t.addEventListener("mousemove",e.mousemove),t.addEventListener("mousedown",e.mousedown),t.addEventListener("mouseup",e.mouseup),t.addEventListener("mousewheel",e.mousewheel),t.addEventListener("DOMMouseScroll",e.mousewheel),t.addEventListener("touchmove",e.mousemove),t.addEventListener("touchstart",e.mousedown),t.addEventListener("touchend",e.mouseup)},i.clearSourceEvents=function(e){e.sourceEvents.mousemove=null,e.sourceEvents.mousedown=null,e.sourceEvents.mouseup=null,e.sourceEvents.mousewheel=null,e.wheelDelta=0},i.setOffset=function(e,t){e.offset.x=t.x,e.offset.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i.setScale=function(e,t){e.scale.x=t.x,e.scale.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i._getRelativeMousePosition=function(e,t,n){var i,o,r=t.getBoundingClientRect(),a=document.documentElement||document.body.parentNode||document.body,s=void 0!==window.pageXOffset?window.pageXOffset:a.scrollLeft,l=void 0!==window.pageYOffset?window.pageYOffset:a.scrollTop,c=e.changedTouches;return c?(i=c[0].pageX-r.left-s,o=c[0].pageY-r.top-l):(i=e.pageX-r.left-s,o=e.pageY-r.top-l),{x:i/(t.clientWidth/(t.width||t.clientWidth)*n),y:o/(t.clientHeight/(t.height||t.clientHeight)*n)}}},function(e,t,n){var i={};e.exports=i;var o=n(14),r=n(9),a=n(1);i.collisions=function(e,t){for(var n=[],s=t.pairs.table,l=0;l1?1:0;d1?1:0;f0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2);i.collides=function(e,t,n){var a,s,l,c,u=!1;if(n){var d=e.parent,p=t.parent,f=d.speed*d.speed+d.angularSpeed*d.angularSpeed+p.speed*p.speed+p.angularSpeed*p.angularSpeed;u=n&&n.collided&&f<.2,c=n}else c={collided:!1,bodyA:e,bodyB:t};if(n&&u){var v=c.axisBody,m=v===e?t:e,y=[v.axes[n.axisNumber]];if(l=i._overlapAxes(v.vertices,m.vertices,y),c.reused=!0,l.overlap<=0)return c.collided=!1,c}else{if((a=i._overlapAxes(e.vertices,t.vertices,e.axes)).overlap<=0)return c.collided=!1,c;if((s=i._overlapAxes(t.vertices,e.vertices,t.axes)).overlap<=0)return c.collided=!1,c;a.overlapo?o=s:s=0?a.index-1:u.length-1],c.x=o.x-d.x,c.y=o.y-d.y,l=-r.dot(n,c),s=o,o=u[(a.index+1)%u.length],c.x=o.x-d.x,c.y=o.y-d.y,(i=-r.dot(n,c))r?(o.warn("Plugin.register:",i.toString(t),"was upgraded to",i.toString(e)),i._registry[e.name]=e):n-1},i.isFor=function(e,t){var n=e.for&&i.dependencyParse(e.for);return!e.for||t.name===n.name&&i.versionSatisfies(t.version,n.range)},i.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=i.dependencies(e),r=o.topologicalSort(n),a=[],s=0;s0&&o.info(a.join(" "))}else o.warn("Plugin.use:",i.toString(e),"does not specify any dependencies to install.")},i.dependencies=function(e,t){var n=i.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=i.resolve(e)||e,t[r]=o.map(e.uses||[],(function(t){i.isPlugin(t)&&i.register(t);var r=i.dependencyParse(t),a=i.resolve(t);return a&&!i.versionSatisfies(a.version,r.range)?(o.warn("Plugin.dependencies:",i.toString(a),"does not satisfy",i.toString(r),"used by",i.toString(n)+"."),a._warned=!0,e._warned=!0):a||(o.warn("Plugin.dependencies:",i.toString(t),"used by",i.toString(n),"could not be resolved."),e._warned=!0),r.name}));for(var a=0;a=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-]+)?$/;t.test(e)||o.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=t.exec(e),i=Number(n[4]),r=Number(n[5]),a=Number(n[6]);return{isRange:Boolean(n[1]||n[2]),version:n[3],range:e,operator:n[1]||n[2]||"",major:i,minor:r,patch:a,parts:[i,r,a],prerelease:n[7],number:1e8*i+1e4*r+a}},i.versionSatisfies=function(e,t){t=t||"*";var n=i.versionParse(t),o=i.versionParse(e);if(n.isRange){if("*"===n.operator||"*"===e)return!0;if(">"===n.operator)return o.number>n.number;if(">="===n.operator)return o.number>=n.number;if("~"===n.operator)return o.major===n.major&&o.minor===n.minor&&o.patch>=n.patch;if("^"===n.operator)return n.major>0?o.major===n.major&&o.number>=n.number:n.minor>0?o.minor===n.minor&&o.patch>=n.patch:o.patch===n.patch}return e===t||"*"===e}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(5),a=n(1),s=n(4),l=n(2),c=n(12);!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout((function(){e(o.now())}),1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),i._goodFps=30,i._goodDelta=1e3/60,i.create=function(e){var t={controller:i,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,timing:{historySize:60,delta:0,deltaHistory:[],lastTime:0,lastTimestamp:0,lastElapsed:0,timestampElapsed:0,timestampElapsedHistory:[],engineDeltaHistory:[],engineElapsedHistory:[],elapsedHistory:[]},options:{width:800,height:600,pixelRatio:1,background:"#14151f",wireframeBackground:"#14151f",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showStats:!1,showPerformance:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},n=o.extend(t,e);return n.canvas&&(n.canvas.width=n.options.width||n.canvas.width,n.canvas.height=n.options.height||n.canvas.height),n.mouse=e.mouse,n.engine=e.engine,n.canvas=n.canvas||d(n.options.width,n.options.height),n.context=n.canvas.getContext("2d"),n.textures={},n.bounds=n.bounds||{min:{x:0,y:0},max:{x:n.canvas.width,y:n.canvas.height}},1!==n.options.pixelRatio&&i.setPixelRatio(n,n.options.pixelRatio),o.isElement(n.element)?n.element.appendChild(n.canvas):n.canvas.parentNode||o.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),n},i.run=function(t){!function o(r){t.frameRequestId=e(o),n(t,r),i.world(t,r),(t.options.showStats||t.options.showDebug)&&i.stats(t,t.context,r),(t.options.showPerformance||t.options.showDebug)&&i.performance(t,t.context,r)}()},i.stop=function(e){t(e.frameRequestId)},i.setPixelRatio=function(e,t){var n=e.options,i=e.canvas;"auto"===t&&(t=p(i)),n.pixelRatio=t,i.setAttribute("data-pixel-ratio",t),i.width=n.width*t,i.height=n.height*t,i.style.width=n.width+"px",i.style.height=n.height+"px"},i.lookAt=function(e,t,n,i){i=void 0===i||i,t=o.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},a=0;ar.max.x&&(r.max.x=u.x),l.yr.max.y&&(r.max.y=u.y))}var d=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,f=e.canvas.height,v=e.canvas.width/f,m=d/p,y=1,g=1;m>v?g=m/v:y=v/m,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+d*y,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*g,i&&(e.bounds.min.x+=.5*d-d*y*.5,e.bounds.max.x+=.5*d-d*y*.5,e.bounds.min.y+=.5*p-p*g*.5,e.bounds.max.y+=.5*p-p*g*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(c.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}),c.setOffset(e.mouse,e.bounds.min))},i.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,i=t/e.options.width,o=n/e.options.height;e.context.setTransform(e.options.pixelRatio/i,0,0,e.options.pixelRatio/o,0,0),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},i.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},i.world=function(e,t){var n,u=o.now(),d=e.engine,p=d.world,f=e.canvas,m=e.context,y=e.options,g=e.timing,x=r.allBodies(p),h=r.allConstraints(p),b=y.wireframes?y.wireframeBackground:y.background,S=[],w=[],A={timestamp:d.timing.timestamp};if(s.trigger(e,"beforeRender",A),e.currentBackground!==b&&v(e,b),m.globalCompositeOperation="source-in",m.fillStyle="transparent",m.fillRect(0,0,f.width,f.height),m.globalCompositeOperation="source-over",y.hasBounds){for(n=0;n1?1:0;a1?1:0;s1?1:0;r1?1:0;s1?1:0;r1?1:0;r1?1:0;o0)){var u=i.activeContacts[0].vertex.x,d=i.activeContacts[0].vertex.y;2===i.activeContacts.length&&(u=(i.activeContacts[0].vertex.x+i.activeContacts[1].vertex.x)/2,d=(i.activeContacts[0].vertex.y+i.activeContacts[1].vertex.y)/2),o.bodyB===o.supports[0].body||!0===o.bodyA.isStatic?s.moveTo(u-8*o.normal.x,d-8*o.normal.y):s.moveTo(u+8*o.normal.x,d+8*o.normal.y),s.lineTo(u,d)}l.wireframes?s.strokeStyle="rgba(255,165,0,0.7)":s.strokeStyle="orange",s.lineWidth=1,s.stroke()},i.separations=function(e,t,n){var i,o,r,a,s,l=n,c=e.options;for(l.beginPath(),s=0;s0&&c.trigger(e,"collisionStart",{pairs:A.collisionStart}),r.preSolvePosition(A.list),m=0;m0&&c.trigger(e,"collisionActive",{pairs:A.collisionActive}),A.collisionEnd.length>0&&c.trigger(e,"collisionEnd",{pairs:A.collisionEnd}),i._bodiesClearForces(b),c.trigger(e,"afterUpdate",h),e.timing.lastElapsed=p.now()-f,e},i.merge=function(e,t){if(p.extend(e,t),t.world){e.world=t.world,i.clear(e);for(var n=u.allBodies(e.world),r=0;rf.friction*f.frictionStatic*L*n&&(O=T,V=a.clamp(f.friction*R*n,-O,O));var F=r.cross(P,g),D=r.cross(M,g),H=b/(m.inverseMass+y.inverseMass+m.inverseInertia*F*F+y.inverseInertia*D*D);if(E*=H,V*=H,k<0&&k*k>i._restingThresh*n)w.normalImpulse=0;else{var j=w.normalImpulse;w.normalImpulse=Math.min(w.normalImpulse+E,0),E=w.normalImpulse-j}if(I*I>i._restingThreshTangent*n)w.tangentImpulse=0;else{var W=w.tangentImpulse;w.tangentImpulse=a.clamp(w.tangentImpulse+V,-O,O),V=w.tangentImpulse-W}o.x=g.x*E+x.x*V,o.y=g.y*E+x.y*V,m.isStatic||m.isSleeping||(m.positionPrev.x+=o.x*m.inverseMass,m.positionPrev.y+=o.y*m.inverseMass,m.anglePrev+=r.cross(P,o)*m.inverseInertia),y.isStatic||y.isSleeping||(y.positionPrev.x-=o.x*y.inverseMass,y.positionPrev.y-=o.y*y.inverseMass,y.anglePrev-=r.cross(M,o)*y.inverseInertia)}}}}},function(e,t,n){var i={};e.exports=i;var o=n(9),r=n(0);i._pairMaxIdleLife=1e3,i.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},i.update=function(e,t,n){var i,r,a,s,l=e.list,c=e.table,u=e.collisionStart,d=e.collisionEnd,p=e.collisionActive;for(u.length=0,d.length=0,p.length=0,s=0;si._pairMaxIdleLife&&c.push(a);for(a=0;au.bounds.max.x||f.bounds.max.yu.bounds.max.y))){var v=i._getRegion(e,f);if(!f.region||v.id!==f.region.id||o){f.region&&!o||(f.region=v);var m=i._regionUnion(v,f.region);for(a=m.startCol;a<=m.endCol;a++)for(s=m.startRow;s<=m.endRow;s++){l=d[c=i._getBucketId(a,s)];var y=a>=v.startCol&&a<=v.endCol&&s>=v.startRow&&s<=v.endRow,g=a>=f.region.startCol&&a<=f.region.endCol&&s>=f.region.startRow&&s<=f.region.endRow;!y&&g&&g&&l&&i._bucketRemoveBody(e,l,f),(f.region===v||y&&!g||o)&&(l||(l=i._createBucket(d,c)),i._bucketAddBody(e,l,f))}f.region=v,p=!0}}}p&&(e.pairsList=i._createActivePairsList(e))},i.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},i._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),o=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),a=Math.max(e.endRow,t.endRow);return i._createRegion(n,o,r,a)},i._getRegion=function(e,t){var n=t.bounds,o=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),a=Math.floor(n.min.y/e.bucketHeight),s=Math.floor(n.max.y/e.bucketHeight);return i._createRegion(o,r,a,s)},i._createRegion=function(e,t,n,i){return{id:e+","+t+","+n+","+i,startCol:e,endCol:t,startRow:n,endRow:i}},i._getBucketId=function(e,t){return"C"+e+"R"+t},i._createBucket=function(e,t){return e[t]=[]},i._bucketAddBody=function(e,t,n){for(var i=0;i0?i.push(n):delete e.pairs[t[o]];return i}},function(e,t,n){var i=e.exports=n(23);i.Axes=n(10),i.Bodies=n(11),i.Body=n(6),i.Bounds=n(1),i.Common=n(0),i.Composite=n(5),i.Composites=n(24),i.Constraint=n(8),i.Contact=n(17),i.Detector=n(13),i.Engine=n(18),i.Events=n(4),i.Grid=n(21),i.Mouse=n(12),i.MouseConstraint=n(25),i.Pair=n(9),i.Pairs=n(20),i.Plugin=n(15),i.Query=n(26),i.Render=n(16),i.Resolver=n(19),i.Runner=n(27),i.SAT=n(14),i.Sleeping=n(7),i.Svg=n(28),i.Vector=n(2),i.Vertices=n(3),i.World=n(29),i.Engine.run=i.Runner.run,i.Common.deprecated(i.Engine,"run","Engine.run ➤ use Matter.Runner.run(engine) instead")},function(e,t,n){var i={};e.exports=i;var o=n(15),r=n(0);i.name="matter-js",i.version="0.17.1",i.uses=[],i.used=[],i.use=function(){o.use(i,Array.prototype.slice.call(arguments))},i.before=function(e,t){return e=e.replace(/^Matter./,""),r.chainPathBefore(i,e,t)},i.after=function(e,t){return e=e.replace(/^Matter./,""),r.chainPathAfter(i,e,t)}},function(e,t,n){var i={};e.exports=i;var o=n(5),r=n(8),a=n(0),s=n(6),l=n(11),c=a.deprecated;i.stack=function(e,t,n,i,r,a,l){for(var c,u=o.create({label:"Stack"}),d=e,p=t,f=0,v=0;vm&&(m=x),s.translate(g,{x:.5*h,y:.5*x}),d=g.bounds.max.x+r,o.addBody(u,g),c=g,f+=1}else d+=r}p+=m+a,d=e}return u},i.chain=function(e,t,n,i,s,l){for(var c=e.bodies,u=1;u0)for(c=0;c0&&(p=f[c-1+(l-1)*t],o.addConstraint(e,r.create(a.extend({bodyA:p,bodyB:d},s)))),i&&cp||a<(c=p-c)||a>n-1-c))return 1===d&&s.translate(u,{x:(a+(n%2==1?1:-1))*f,y:0}),l(e+(u?a*f:0)+a*r,i,a,c,u,d)}))},i.newtonsCradle=function(e,t,n,i,a){for(var s=o.create({label:"Newtons Cradle"}),c=0;c1?1:0;ue.deltaMax?e.deltaMax:i)/e.delta,e.delta=i),0!==e.timeScalePrev&&(s*=a.timeScale/e.timeScalePrev),0===a.timeScale&&(s=0),e.timeScalePrev=a.timeScale,e.correction=s,e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),o.trigger(e,"tick",l),o.trigger(e,"beforeUpdate",l),r.update(t,i,s),o.trigger(e,"afterUpdate",l),o.trigger(e,"afterTick",l)},i.stop=function(e){t(e.frameRequestId)},i.start=function(e,t){i.run(e,t)}}()},function(e,t,n){var i={};e.exports=i;n(1);var o=n(0);i.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||o.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,a,s,l,c,u,d,p,f,v,m=[],y=0,g=0,x=0;t=t||15;var h=function(e,t,n){var i=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&i?(f=p.x,v=p.y):(f=0,v=0);var o={x:f+e,y:v+t};!i&&p||(p=o),m.push(o),g=f+e,x=v+t}},b=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":g=e.x,x=e.y;break;case"H":g=e.x;break;case"V":x=e.y}h(g,x,e.pathSegType)}};for(i._svgPathToAbsolute(e),a=e.getTotalLength(),c=[],n=0;n0;t--){var i=Math.floor(n.random()*(t+1)),o=e[t];e[t]=e[i],e[i]=o}return e},n.choose=function(e){return e[Math.floor(n.random()*e.length)]},n.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},n.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},n.isFunction=function(e){return"function"==typeof e},n.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},n.isString=function(e){return"[object String]"===toString.call(e)},n.clamp=function(e,t,n){return en?n:e},n.sign=function(e){return e<0?-1:1},n.now=function(){if("undefined"!=typeof window&&window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return Date.now?Date.now():new Date-n._nowStartTime},n.random=function(t,n){return n=void 0!==n?n:1,(t=void 0!==t?t:0)+e()*(n-t)};var e=function(){return n._seed=(9301*n._seed+49297)%233280,n._seed/233280};n.colorToNumber=function(e){return 3==(e=e.replace("#","")).length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},n.logLevel=1,n.log=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.info=function(){console&&n.logLevel>0&&n.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warn=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warnOnce=function(){var e=Array.prototype.slice.call(arguments).join(" ");n._warnedOnce[e]||(n.warn(e),n._warnedOnce[e]=!0)},n.deprecated=function(e,t,i){e[t]=n.chain((function(){n.warnOnce("🔅 deprecated 🔅",i)}),e[t])},n.nextId=function(){return n._nextId++},n.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;ne.max.x&&(e.max.x=o.x),o.xe.max.y&&(e.max.y=o.y),o.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},n.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},n.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},n.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},n.shift=function(e,t){var n=e.max.x-e.min.x,i=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+i}},function(e,t){var n={};e.exports=n,n.create=function(e,t){return{x:e||0,y:t||0}},n.clone=function(e){return{x:e.x,y:e.y}},n.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},n.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},n.rotate=function(e,t,n){var i=Math.cos(t),o=Math.sin(t);n||(n={});var r=e.x*i-e.y*o;return n.y=e.x*o+e.y*i,n.x=r,n},n.rotateAbout=function(e,t,n,i){var o=Math.cos(t),r=Math.sin(t);i||(i={});var a=n.x+((e.x-n.x)*o-(e.y-n.y)*r);return i.y=n.y+((e.x-n.x)*r+(e.y-n.y)*o),i.x=a,i},n.normalise=function(e){var t=n.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},n.dot=function(e,t){return e.x*t.x+e.y*t.y},n.cross=function(e,t){return e.x*t.y-e.y*t.x},n.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},n.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},n.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},n.mult=function(e,t){return{x:e.x*t,y:e.y*t}},n.div=function(e,t){return{x:e.x/t,y:e.y/t}},n.perp=function(e,t){return{x:(t=!0===t?-1:1)*-e.y,y:t*e.x}},n.neg=function(e){return{x:-e.x,y:-e.y}},n.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x)},n._temp=[n.create(),n.create(),n.create(),n.create(),n.create(),n.create()]},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.create=function(e,t){for(var n=[],i=0;i0)return!1;a=n}return!0},i.scale=function(e,t,n,r){if(1===t&&1===n)return e;var a,s;r=r||i.centre(e);for(var l=0;l=0?l-1:e.length-1],u=e[l],d=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},i.hull=function(e){var t,n,i=[],r=[];for((e=e.slice(0)).sort((function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y})),n=0;n=2&&o.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];i.length>=2&&o.cross3(i[i.length-2],i[i.length-1],t)<=0;)i.pop();i.push(t)}return i.pop(),r.pop(),i.concat(r)}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.on=function(e,t,n){for(var i,o=t.split(" "),r=0;r0){n||(n={}),i=t.split(" ");for(var c=0;c0&&r.rotateAbout(a.position,n,e.position,a.position)}},i.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y,e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},i.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},i.translate=function(e,t){i.setPosition(e,r.add(e.position,t))},i.rotate=function(e,t,n){if(n){var o=Math.cos(t),r=Math.sin(t),a=e.position.x-n.x,s=e.position.y-n.y;i.setPosition(e,{x:n.x+(a*o-s*r),y:n.y+(a*r+s*o)}),i.setAngle(e,e.angle+t)}else i.setAngle(e,e.angle+t)},i.scale=function(e,t,n,r){var a=0,s=0;r=r||e.position;for(var u=0;u0&&(a+=d.area,s+=d.inertia),d.position.x=r.x+(d.position.x-r.x)*t,d.position.y=r.y+(d.position.y-r.y)*n,l.update(d.bounds,d.vertices,e.velocity)}e.parts.length>1&&(e.area=a,e.isStatic||(i.setMass(e,e.density*a),i.setInertia(e,s))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},i.update=function(e,t,n,i){var a=Math.pow(t*n*e.timeScale,2),s=1-e.frictionAir*n*e.timeScale,u=e.position.x-e.positionPrev.x,d=e.position.y-e.positionPrev.y;e.velocity.x=u*s*i+e.force.x/e.mass*a,e.velocity.y=d*s*i+e.force.y/e.mass*a,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*s*i+e.torque/e.inertia*a,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(o.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity),p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},i.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var i=t.x-e.position.x,o=t.y-e.position.y;e.torque+=i*n.y-o*n.x},i._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n0&&r.motion=r.sleepThreshold&&i.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else i.set(r,!1)}},i.afterCollisions=function(e,t){for(var n=t*t*t,o=0;oi._motionWakeThreshold*n&&i.set(c,!1)}}}},i.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||o.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&o.trigger(e,"sleepEnd"))}},function(e,t,n){var i={};e.exports=i;var o,r,a,s=n(3),l=n(9);o=[],r={overlap:0,axis:null},a={overlap:0,axis:null},i.create=function(e,t){return{pair:null,collided:!1,bodyA:e,bodyB:t,parentA:e.parent,parentB:t.parent,depth:0,normal:{x:0,y:0},tangent:{x:0,y:0},penetration:{x:0,y:0},supports:[]}},i.collides=function(e,t,n){if(i._overlapAxes(r,e.vertices,t.vertices,e.axes),r.overlap<=0)return null;if(i._overlapAxes(a,t.vertices,e.vertices,t.axes),a.overlap<=0)return null;var o,c,u=n&&n.table[l.id(e,t)];u?o=u.collision:((o=i.create(e,t)).collided=!0,o.bodyA=e.idP?P=s:sC?C=s:so?o=a:al.frictionStatic?s.frictionStatic:l.frictionStatic,e.restitution=s.restitution>l.restitution?s.restitution:l.restitution,e.slop=s.slop>l.slop?s.slop:l.slop,t.pair=e,a.length=0;for(var u=0;u0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var a={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(a.type="pin",a.anchors=!1):t.stiffness<.9&&(a.type="spring"),t.render=c.extend(a,t.render),t},i.preSolveAll=function(e){for(var t=0;t0&&(d.position.x+=c.x,d.position.y+=c.y),0!==c.angle&&(o.rotate(d.vertices,c.angle,n.position),l.rotate(d.axes,c.angle),u>0&&r.rotateAbout(d.position,c.angle,n.position,d.position)),s.update(d.bounds,d.vertices,n.velocity)}c.angle*=i._warming,c.x*=i._warming,c.y*=i._warming}}},i.pointAWorld=function(e){return{x:(e.bodyA?e.bodyA.position.x:0)+e.pointA.x,y:(e.bodyA?e.bodyA.position.y:0)+e.pointA.y}},i.pointBWorld=function(e){return{x:(e.bodyB?e.bodyB.position.x:0)+e.pointB.x,y:(e.bodyB?e.bodyB.position.y:0)+e.pointB.y}}},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.fromVertices=function(e){for(var t={},n=0;n0&&o.area(M)1?(v=a.create(r.extend({parts:y.slice(0)},i)),a.setPosition(v,{x:e,y:t}),v):y[0]}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.create=function(e){var t={};return e||o.log("Mouse.create: element was undefined, defaulting to document.body","warn"),t.element=e||document.body,t.absolute={x:0,y:0},t.position={x:0,y:0},t.mousedownPosition={x:0,y:0},t.mouseupPosition={x:0,y:0},t.offset={x:0,y:0},t.scale={x:1,y:1},t.wheelDelta=0,t.button=-1,t.pixelRatio=parseInt(t.element.getAttribute("data-pixel-ratio"),10)||1,t.sourceEvents={mousemove:null,mousedown:null,mouseup:null,mousewheel:null},t.mousemove=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&(t.button=0,e.preventDefault()),t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.sourceEvents.mousemove=e},t.mousedown=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches?(t.button=0,e.preventDefault()):t.button=e.button,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mousedownPosition.x=t.position.x,t.mousedownPosition.y=t.position.y,t.sourceEvents.mousedown=e},t.mouseup=function(e){var n=i._getRelativeMousePosition(e,t.element,t.pixelRatio);e.changedTouches&&e.preventDefault(),t.button=-1,t.absolute.x=n.x,t.absolute.y=n.y,t.position.x=t.absolute.x*t.scale.x+t.offset.x,t.position.y=t.absolute.y*t.scale.y+t.offset.y,t.mouseupPosition.x=t.position.x,t.mouseupPosition.y=t.position.y,t.sourceEvents.mouseup=e},t.mousewheel=function(e){t.wheelDelta=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail)),e.preventDefault()},i.setElement(t,t.element),t},i.setElement=function(e,t){e.element=t,t.addEventListener("mousemove",e.mousemove),t.addEventListener("mousedown",e.mousedown),t.addEventListener("mouseup",e.mouseup),t.addEventListener("mousewheel",e.mousewheel),t.addEventListener("DOMMouseScroll",e.mousewheel),t.addEventListener("touchmove",e.mousemove),t.addEventListener("touchstart",e.mousedown),t.addEventListener("touchend",e.mouseup)},i.clearSourceEvents=function(e){e.sourceEvents.mousemove=null,e.sourceEvents.mousedown=null,e.sourceEvents.mouseup=null,e.sourceEvents.mousewheel=null,e.wheelDelta=0},i.setOffset=function(e,t){e.offset.x=t.x,e.offset.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i.setScale=function(e,t){e.scale.x=t.x,e.scale.y=t.y,e.position.x=e.absolute.x*e.scale.x+e.offset.x,e.position.y=e.absolute.y*e.scale.y+e.offset.y},i._getRelativeMousePosition=function(e,t,n){var i,o,r=t.getBoundingClientRect(),a=document.documentElement||document.body.parentNode||document.body,s=void 0!==window.pageXOffset?window.pageXOffset:a.scrollLeft,l=void 0!==window.pageYOffset?window.pageYOffset:a.scrollTop,c=e.changedTouches;return c?(i=c[0].pageX-r.left-s,o=c[0].pageY-r.top-l):(i=e.pageX-r.left-s,o=e.pageY-r.top-l),{x:i/(t.clientWidth/(t.width||t.clientWidth)*n),y:o/(t.clientHeight/(t.height||t.clientHeight)*n)}}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(8);i.create=function(e){return o.extend({bodies:[],pairs:null},e)},i.setBodies=function(e,t){e.bodies=t.slice(0)},i.clear=function(e){e.bodies=[]},i.collisions=function(e){var t,n,o=[],a=e.pairs,s=e.bodies,l=s.length,c=i.canCollide,u=r.collides;for(s.sort(i._compareBoundsX),t=0;tf)break;if(!(vB.max.y)&&(!m||!h.isStatic&&!h.isSleeping)&&c(d.collisionFilter,h.collisionFilter)){var b=h.parts.length;if(x&&1===b)(C=u(d,h,a))&&o.push(C);else for(var S=b>1?1:0,w=g>1?1:0;wB.max.x||p.max.xB.max.y||(C=u(A,M,a))&&o.push(C)}}}}return o},i.canCollide=function(e,t){return e.group===t.group&&0!==e.group?e.group>0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)},i._compareBoundsX=function(e,t){return e.bounds.min.x-t.bounds.min.x}},function(e,t,n){var i={};e.exports=i;var o=n(0);i._registry={},i.register=function(e){if(i.isPlugin(e)||o.warn("Plugin.register:",i.toString(e),"does not implement all required fields."),e.name in i._registry){var t=i._registry[e.name],n=i.versionParse(e.version).number,r=i.versionParse(t.version).number;n>r?(o.warn("Plugin.register:",i.toString(t),"was upgraded to",i.toString(e)),i._registry[e.name]=e):n-1},i.isFor=function(e,t){var n=e.for&&i.dependencyParse(e.for);return!e.for||t.name===n.name&&i.versionSatisfies(t.version,n.range)},i.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=i.dependencies(e),r=o.topologicalSort(n),a=[],s=0;s0&&o.info(a.join(" "))}else o.warn("Plugin.use:",i.toString(e),"does not specify any dependencies to install.")},i.dependencies=function(e,t){var n=i.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=i.resolve(e)||e,t[r]=o.map(e.uses||[],(function(t){i.isPlugin(t)&&i.register(t);var r=i.dependencyParse(t),a=i.resolve(t);return a&&!i.versionSatisfies(a.version,r.range)?(o.warn("Plugin.dependencies:",i.toString(a),"does not satisfy",i.toString(r),"used by",i.toString(n)+"."),a._warned=!0,e._warned=!0):a||(o.warn("Plugin.dependencies:",i.toString(t),"used by",i.toString(n),"could not be resolved."),e._warned=!0),r.name}));for(var a=0;a=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-+]+)?$/;t.test(e)||o.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=t.exec(e),i=Number(n[4]),r=Number(n[5]),a=Number(n[6]);return{isRange:Boolean(n[1]||n[2]),version:n[3],range:e,operator:n[1]||n[2]||"",major:i,minor:r,patch:a,parts:[i,r,a],prerelease:n[7],number:1e8*i+1e4*r+a}},i.versionSatisfies=function(e,t){t=t||"*";var n=i.versionParse(t),o=i.versionParse(e);if(n.isRange){if("*"===n.operator||"*"===e)return!0;if(">"===n.operator)return o.number>n.number;if(">="===n.operator)return o.number>=n.number;if("~"===n.operator)return o.major===n.major&&o.minor===n.minor&&o.patch>=n.patch;if("^"===n.operator)return n.major>0?o.major===n.major&&o.number>=n.number:n.minor>0?o.minor===n.minor&&o.patch>=n.patch:o.patch===n.patch}return e===t||"*"===e}},function(e,t,n){var i={};e.exports=i;var o=n(0),r=n(5),a=n(1),s=n(4),l=n(2),c=n(13);!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout((function(){e(o.now())}),1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),i._goodFps=30,i._goodDelta=1e3/60,i.create=function(e){var t={controller:i,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,timing:{historySize:60,delta:0,deltaHistory:[],lastTime:0,lastTimestamp:0,lastElapsed:0,timestampElapsed:0,timestampElapsedHistory:[],engineDeltaHistory:[],engineElapsedHistory:[],elapsedHistory:[]},options:{width:800,height:600,pixelRatio:1,background:"#14151f",wireframeBackground:"#14151f",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showStats:!1,showPerformance:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},n=o.extend(t,e);return n.canvas&&(n.canvas.width=n.options.width||n.canvas.width,n.canvas.height=n.options.height||n.canvas.height),n.mouse=e.mouse,n.engine=e.engine,n.canvas=n.canvas||d(n.options.width,n.options.height),n.context=n.canvas.getContext("2d"),n.textures={},n.bounds=n.bounds||{min:{x:0,y:0},max:{x:n.canvas.width,y:n.canvas.height}},n.options.showBroadphase=!1,1!==n.options.pixelRatio&&i.setPixelRatio(n,n.options.pixelRatio),o.isElement(n.element)?n.element.appendChild(n.canvas):n.canvas.parentNode||o.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),n},i.run=function(t){!function o(r){t.frameRequestId=e(o),n(t,r),i.world(t,r),(t.options.showStats||t.options.showDebug)&&i.stats(t,t.context,r),(t.options.showPerformance||t.options.showDebug)&&i.performance(t,t.context,r)}()},i.stop=function(e){t(e.frameRequestId)},i.setPixelRatio=function(e,t){var n=e.options,i=e.canvas;"auto"===t&&(t=p(i)),n.pixelRatio=t,i.setAttribute("data-pixel-ratio",t),i.width=n.width*t,i.height=n.height*t,i.style.width=n.width+"px",i.style.height=n.height+"px"},i.lookAt=function(e,t,n,i){i=void 0===i||i,t=o.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},a=0;ar.max.x&&(r.max.x=u.x),l.yr.max.y&&(r.max.y=u.y))}var d=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,f=e.canvas.height,v=e.canvas.width/f,y=d/p,m=1,g=1;y>v?g=y/v:m=v/y,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+d*m,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*g,i&&(e.bounds.min.x+=.5*d-d*m*.5,e.bounds.max.x+=.5*d-d*m*.5,e.bounds.min.y+=.5*p-p*g*.5,e.bounds.max.y+=.5*p-p*g*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(c.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}),c.setOffset(e.mouse,e.bounds.min))},i.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,i=t/e.options.width,o=n/e.options.height;e.context.setTransform(e.options.pixelRatio/i,0,0,e.options.pixelRatio/o,0,0),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},i.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},i.world=function(e,t){var n,u=o.now(),d=e.engine,p=d.world,f=e.canvas,y=e.context,m=e.options,g=e.timing,x=r.allBodies(p),h=r.allConstraints(p),b=m.wireframes?m.wireframeBackground:m.background,S=[],w=[],A={timestamp:d.timing.timestamp};if(s.trigger(e,"beforeRender",A),e.currentBackground!==b&&v(e,b),y.globalCompositeOperation="source-in",y.fillStyle="transparent",y.fillRect(0,0,f.width,f.height),y.globalCompositeOperation="source-over",m.hasBounds){for(n=0;n1?1:0;a1?1:0;s1?1:0;r1?1:0;s1?1:0;r1?1:0;r1?1:0;o0)){var u=i.activeContacts[0].vertex.x,d=i.activeContacts[0].vertex.y;2===i.activeContacts.length&&(u=(i.activeContacts[0].vertex.x+i.activeContacts[1].vertex.x)/2,d=(i.activeContacts[0].vertex.y+i.activeContacts[1].vertex.y)/2),o.bodyB===o.supports[0].body||!0===o.bodyA.isStatic?s.moveTo(u-8*o.normal.x,d-8*o.normal.y):s.moveTo(u+8*o.normal.x,d+8*o.normal.y),s.lineTo(u,d)}l.wireframes?s.strokeStyle="rgba(255,165,0,0.7)":s.strokeStyle="orange",s.lineWidth=1,s.stroke()},i.separations=function(e,t,n){var i,o,r,a,s,l=n,c=e.options;for(l.beginPath(),s=0;s0&&l.trigger(e,"collisionStart",{pairs:m.collisionStart}),r.preSolvePosition(m.list),f=0;f0&&l.trigger(e,"collisionActive",{pairs:m.collisionActive}),m.collisionEnd.length>0&&l.trigger(e,"collisionEnd",{pairs:m.collisionEnd}),i._bodiesClearForces(b),l.trigger(e,"afterUpdate",h),e.timing.lastElapsed=d.now()-p,e},i.merge=function(e,t){if(d.extend(e,t),t.world){e.world=t.world,i.clear(e);for(var n=c.allBodies(e.world),r=0;rW||-H>W?(o=H>0?H:-H,(n=f.friction*(H>0?1:-1)*s)<-o?n=-o:n>o&&(n=o)):(n=H,o=d);var G=I*b-T*h,N=R*b-E*h,U=C/(M+y.inverseInertia*G*G+m.inverseInertia*N*N),z=(1+f.restitution)*F*U;if(n*=U,F*F>l&&F<0)k.normalImpulse=0;else{var X=k.normalImpulse;k.normalImpulse+=z,k.normalImpulse=Math.min(k.normalImpulse,0),z=k.normalImpulse-X}if(H*H>u)k.tangentImpulse=0;else{var Q=k.tangentImpulse;k.tangentImpulse+=n,k.tangentImpulse<-o&&(k.tangentImpulse=-o),k.tangentImpulse>o&&(k.tangentImpulse=o),n=k.tangentImpulse-Q}var Y=h*z+S*n,Z=b*z+w*n;y.isStatic||y.isSleeping||(y.positionPrev.x+=Y*y.inverseMass,y.positionPrev.y+=Z*y.inverseMass,y.anglePrev+=(I*Z-T*Y)*y.inverseInertia),m.isStatic||m.isSleeping||(m.positionPrev.x-=Y*m.inverseMass,m.positionPrev.y-=Z*m.inverseMass,m.anglePrev-=(R*Z-E*Y)*m.inverseInertia)}}}}},function(e,t,n){var i={};e.exports=i;var o=n(9),r=n(0);i.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},i.update=function(e,t,n){var i,r,a,s,l=e.list,c=l.length,u=e.table,d=t.length,p=e.collisionStart,f=e.collisionEnd,v=e.collisionActive;for(p.length=0,f.length=0,v.length=0,s=0;sy&&(y=x),s.translate(g,{x:.5*h,y:.5*x}),d=g.bounds.max.x+r,o.addBody(u,g),c=g,f+=1}else d+=r}p+=y+a,d=e}return u},i.chain=function(e,t,n,i,s,l){for(var c=e.bodies,u=1;u0)for(c=0;c0&&(p=f[c-1+(l-1)*t],o.addConstraint(e,r.create(a.extend({bodyA:p,bodyB:d},s)))),i&&cp||a<(c=p-c)||a>n-1-c))return 1===d&&s.translate(u,{x:(a+(n%2==1?1:-1))*f,y:0}),l(e+(u?a*f:0)+a*r,i,a,c,u,d)}))},i.newtonsCradle=function(e,t,n,i,a){for(var s=o.create({label:"Newtons Cradle"}),c=0;cu.bounds.max.x||f.bounds.max.yu.bounds.max.y))){var v=i._getRegion(e,f);if(!f.region||v.id!==f.region.id||o){f.region&&!o||(f.region=v);var y=i._regionUnion(v,f.region);for(a=y.startCol;a<=y.endCol;a++)for(s=y.startRow;s<=y.endRow;s++){l=d[c=i._getBucketId(a,s)];var m=a>=v.startCol&&a<=v.endCol&&s>=v.startRow&&s<=v.endRow,g=a>=f.region.startCol&&a<=f.region.endCol&&s>=f.region.startRow&&s<=f.region.endRow;!m&&g&&g&&l&&i._bucketRemoveBody(e,l,f),(f.region===v||m&&!g||o)&&(l||(l=i._createBucket(d,c)),i._bucketAddBody(e,l,f))}f.region=v,p=!0}}}p&&(e.pairsList=i._createActivePairsList(e))},a(i,"update","Grid.update ➤ replaced by Matter.Detector"),i.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},a(i,"clear","Grid.clear ➤ replaced by Matter.Detector"),i._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),o=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),a=Math.max(e.endRow,t.endRow);return i._createRegion(n,o,r,a)},i._getRegion=function(e,t){var n=t.bounds,o=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),a=Math.floor(n.min.y/e.bucketHeight),s=Math.floor(n.max.y/e.bucketHeight);return i._createRegion(o,r,a,s)},i._createRegion=function(e,t,n,i){return{id:e+","+t+","+n+","+i,startCol:e,endCol:t,startRow:n,endRow:i}},i._getBucketId=function(e,t){return"C"+e+"R"+t},i._createBucket=function(e,t){return e[t]=[]},i._bucketAddBody=function(e,t,n){var i,r=e.pairs,a=o.id,s=t.length;for(i=0;i0?s.push(t):delete i[o[n]];return s}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(7),a=n(13),s=n(4),l=n(14),c=n(10),u=n(5),d=n(0),p=n(1);i.create=function(e,t){var n=(e?e.mouse:null)||(t?t.mouse:null);n||(e&&e.render&&e.render.canvas?n=a.create(e.render.canvas):t&&t.element?n=a.create(t.element):(n=a.create(),d.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));var o={type:"mouseConstraint",mouse:n,element:null,body:null,constraint:c.create({label:"Mouse Constraint",pointA:n.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1,render:{strokeStyle:"#90EE90",lineWidth:3}}),collisionFilter:{category:1,mask:4294967295,group:0}},r=d.extend(o,t);return s.on(e,"beforeUpdate",(function(){var t=u.allBodies(e.world);i.update(r,t),i._triggerEvents(r)})),r},i.update=function(e,t){var n=e.mouse,i=e.constraint,a=e.body;if(0===n.button){if(i.bodyB)r.set(i.bodyB,!1),i.pointA=n.position;else for(var c=0;c1?1:0;ue.deltaMax?e.deltaMax:i)/e.delta,e.delta=i),0!==e.timeScalePrev&&(s*=a.timeScale/e.timeScalePrev),0===a.timeScale&&(s=0),e.timeScalePrev=a.timeScale,e.correction=s,e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),o.trigger(e,"tick",l),o.trigger(e,"beforeUpdate",l),r.update(t,i,s),o.trigger(e,"afterUpdate",l),o.trigger(e,"afterTick",l)},i.stop=function(e){t(e.frameRequestId)},i.start=function(e,t){i.run(e,t)}}()},function(e,t,n){var i={};e.exports=i;var o=n(8),r=n(0).deprecated;i.collides=function(e,t){return o.collides(e,t)},r(i,"collides","SAT.collides ➤ replaced by Collision.collides")},function(e,t,n){var i={};e.exports=i;n(1);var o=n(0);i.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||o.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,a,s,l,c,u,d,p,f,v,y=[],m=0,g=0,x=0;t=t||15;var h=function(e,t,n){var i=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&i?(f=p.x,v=p.y):(f=0,v=0);var o={x:f+e,y:v+t};!i&&p||(p=o),y.push(o),g=f+e,x=v+t}},b=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":g=e.x,x=e.y;break;case"H":g=e.x;break;case"V":x=e.y}h(g,x,e.pathSegType)}};for(i._svgPathToAbsolute(e),a=e.getTotalLength(),c=[],n=0;n25% nail, needle, rivet size/damage -combined tech: flagella - spores move +50% faster - spores follow you if they can't find a target -shock wave stun also applies to sporangium - no longer reduces explosion size +tech: integrated circuit - if ON +7 power up choices if OFF -1 -JUNK tech: reincarnation - kill all mobs and spawn new ones - (also spawn a few extra mobs for fun) - -updated pause menu and fields descriptions to new wording style - -bug fixes +update matter.js engine 0.17.1 -> 0.18.0 + shouldn't change anything +big fixes *********************************************************** TODO ***************************************************** -Tech: florescence + +wormhole tech: entropic gravity - gain defense for each research + requires wormhole or negative mass field or pilot wave + +shrapnel: a new bullet type: a very small bullet with no targeting that has a high gravity arc + maybe 1 bounce or no bounce before it ends on map or mob collision + often spawns in groups + +testChamber2 + mechanics + companion cube + bring cube to the end and use it to unlock research + level draws on the block to show it's different + only this block can trigger a button + if cube no longer exists or is off the map spawn a new one + double portal fling chain + for player? + for cube + button that activates a laser beam that hits a target and opens a door + in order to enter the door you need to place the cube on the button to activate the laser + cube has to fly through a portal in oder to get to the button + you can't use your body + story: + you pick up the cube early on and have to get it to a button + you run through the level to get the cube, clearing the level of mobs + picking up the cube spawns the boss + maybe an extra hard boss that is designed for that level + blockBoss? + you must get the cube to a button near the start of the level + the button opens a door + normal blocks don't work + normal blocks spawn into mobs like blockBoss + or mobs don't spawn blocks + or just the code looks for the cube + or the cube is resting on a button, and when you take the cube off the button the laser fires + +mitosis: after needle,bullets or rivets hit a surface split off into two smaller less damaging versions that have their velocity reset -firerate + +tech: florescence Hitting a mob makes it emit lasers from its vertices all laser but pulse? should trigger a global cd so it can't occur more then once per cycle @@ -68,6 +103,9 @@ super balls do more damage after bouncing? how to check for bounce? maybe just increases damage after hitting a mob +Make environmental damages also damage mobs +So if a mob passes through laser, it gets damaged + dark mode: look at Tinyfolks, 20 minutes till dawn