pigeonhole principle

tech: junk DNA - +53% spore/worm/flea damage per JUNK tech you have, +50% JUNK added to tech pool
tech: pigeonhole principle - +31% damage for each gun you have, while a chosen gun is active
  chosen gun cycles each level
  syncs well with generalist

heuristics 30->25% fire rate, and now spawns a gun
arsenal gives 13->22% damage per gun, but no longer counts your current gun
active cooling gives 18->28% fire rate per gun, but no longer counts your current gun
supply chain adds 4% JUNK
dead reckoning 36->50% damage
alternator harpoon 60->80% energy cost reduction
quickly releasing the fire button retracts harpoon early

JUNK tech - circular symmetry - ship gets 200% damage, ship only faces forward but you can rotate the universe

several bug fixes
  coupling for molecular assembler 5->8 energy per second
    but also fixed a bug where coupling was giving 10x regen
This commit is contained in:
landgreen
2022-10-23 19:07:07 -07:00
parent 3a9cc28b76
commit de6d910aca
9 changed files with 314 additions and 128 deletions

View File

@@ -284,7 +284,7 @@ const b = {
b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage
if (m.fieldMode === 6) b.fireCDscale *= 0.75
if (tech.isFastTime) b.fireCDscale *= 0.5
if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, b.inventory.length)
if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, Math.max(0, b.inventory.length - 1))
if (tech.isFireMoveLock) b.fireCDscale *= 0.55
},
fireAttributes(dir, rotate = true) {
@@ -1441,7 +1441,7 @@ const b = {
minDmgSpeed: 4,
lookFrequency: Math.floor(7 + Math.random() * 3),
density: tech.harpoonDensity, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
drain: tech.isRailEnergy ? 0.002 : 0.006,
drain: tech.isRailEnergy ? 0.001 : 0.006,
beforeDmg(who) {
if (tech.isShieldPierce && who.isShielded) { //disable shields
who.isShielded = false
@@ -1697,7 +1697,7 @@ const b = {
friction: 1,
frictionAir: 0.4,
thrustMag: 0.1,
drain: tech.isRailEnergy ? 0.002 : 0.006,
drain: tech.isRailEnergy ? 0.001 : 0.006,
turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
@@ -1862,7 +1862,7 @@ const b = {
this.cycle++
if (isReturn || target) {
if (isReturn) {
if (this.cycle > totalCycles || m.energy < 0.05) { //return to player
if (this.cycle > totalCycles || m.energy < 0.05 || !input.fire) { //return to player
this.do = this.returnToPlayer
if (this.angularSpeed < 0.5) this.torque += this.inertia * 0.001 * (Math.random() - 0.5) //(Math.round(Math.random()) ? 1 : -1)
Matter.Sleeping.set(this, false)
@@ -2698,7 +2698,7 @@ const b = {
thrust: (tech.isSporeFollow ? 0.0012 : 0.00055) * (1 + 0.5 * (Math.random() - 0.5)),
wormSize: wormSize,
wormTail: 1 + Math.max(4, Math.min(wormSize - 2 * tech.wormSize, 30)),
dmg: (tech.isMutualism ? 8 : 3.2) * wormSize, //bonus damage from tech.isMutualism //2.5 is extra damage as worm
dmg: (tech.isMutualism ? 8 : 3.2) * wormSize * (tech.isJunkDNA ? 1 + 0.53 * tech.junkCount : 1), //bonus damage from tech.isMutualism //2.5 is extra damage as worm
lookFrequency: 100 + Math.floor(37 * Math.random()),
classType: "bullet",
collisionFilter: {
@@ -2814,7 +2814,7 @@ const b = {
friction: 0,
frictionAir: 0.025,
thrust: (tech.isSporeFollow ? 0.0011 : 0.0005) * (1 + 0.3 * (Math.random() - 0.5)),
dmg: tech.isMutualism ? 16.8 : 7, //bonus damage from tech.isMutualism
dmg: (tech.isMutualism ? 16.8 : 7) * (tech.isJunkDNA ? 1 + 0.53 * tech.junkCount : 1), //bonus damage from tech.isMutualism
lookFrequency: 100 + Math.floor(117 * Math.random()),
classType: "bullet",
isSpore: true,
@@ -3031,7 +3031,7 @@ const b = {
cd: simulation.cycle + 10,
dmg: 0, //radius * (tech.isMutualism ? 2.5 : 1),
setDamage() { //dmg is set to zero after doing damage once, and set back to normal after jumping
this.dmg = radius * (tech.isMutualism ? 2.5 : 1) //damage done in addition to the damage from momentum //spores do 7 dmg, worms do 18
this.dmg = radius * (tech.isMutualism ? 2.5 : 1) * (tech.isJunkDNA ? 1 + 0.53 * tech.junkCount : 1) //damage done in addition to the damage from momentum //spores do 7 dmg, worms do 18
},
beforeDmg(who) {
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), 10 + 10 * Math.random())); //push away from target
@@ -6777,7 +6777,7 @@ const b = {
charge: 0,
railDo() {
if (this.charge > 0) {
const DRAIN = (tech.isRailEnergy ? 0.0005 : 0.002)
const DRAIN = (tech.isRailEnergy ? 0.00025 : 0.002)
//exit railgun charging without firing
if (m.energy < DRAIN) {
// m.energy += 0.025 + this.charge * 22 * this.drain
@@ -7051,7 +7051,7 @@ const b = {
}
}
if (input.down && m.onGround) {
b.harpoon(where, null, m.angle, harpoonSize, true, 1.5 * totalCycles, (input.down && tech.crouchAmmoCount && (tech.crouchAmmoCount - 1) % 2) ? false : true)
b.harpoon(where, null, m.angle, harpoonSize, true, 1.5 * totalCycles, (input.down && tech.crouchAmmoCount && (tech.crouchAmmoCount - 1) % 2) ? false : true) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true) {
} else {
b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles)
}

View File

@@ -28,19 +28,20 @@ const level = {
// m.setField("time dilation") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave
// simulation.molecularMode = 2
// m.damage(0.1);
// b.giveGuns("missiles") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[0].ammo = 10000
// tech.giveTech("arsenal")
// for (let i = 0; i < 1; ++i) tech.giveTech("compound lens")
// b.guns[9].ammo = 10000
// tech.giveTech("ship")
// for (let i = 0; i < 1; ++i) tech.giveTech("junk DNA")
// tech.giveTech("dye laser")
// for (let i = 0; i < 1; ++i) tech.giveTech("CPT symmetry")
// for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook")
// for (let i = 0; i < 5; i++) tech.giveTech("laser-bot")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// canvas.requestPointerLock()
// level.testing();
// spawn.starter(1900, -500, 200)
// spawn.starter(1900, -500)
@@ -94,6 +95,14 @@ const level = {
m.resetHistory();
spawn.quantumEraserCheck(); //remove mobs from tech: quantum eraser
//used for generalist and pigeonhole principle
tech.buffedGun++
if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0;
if (tech.isGunCycle) {
b.inventoryGun = tech.buffedGun;
simulation.switchGun();
}
if (tech.isForeverDrones) {
if (tech.isDroneRadioactive) {
for (let i = 0; i < tech.isForeverDrones * 0.25; i++) {
@@ -111,11 +120,6 @@ const level = {
tech.healMaxEnergyBonus += 0.1 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51)
m.setMaxEnergy();
}
if (tech.isGunCycle) {
b.inventoryGun++;
if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0;
simulation.switchGun();
}
if (tech.isSwitchReality && powerUps.research.count > 0) {
powerUps.research.changeRerolls(-1);
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
@@ -162,7 +166,7 @@ const level = {
if (m.plasmaBall) m.plasmaBall.reset()
if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) {
const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1
powerUps.spawn(flip * localSettings.entanglement.position.x, localSettings.entanglement.position.y, "entanglement", false);
powerUps.directSpawn(flip * localSettings.entanglement.position.x, localSettings.entanglement.position.y, "entanglement", false);
}
},
trainingText(say) {

View File

@@ -362,6 +362,7 @@ const m = {
tech.cancelCount = 0;
tech.extraMaxHealth = 0;
tech.totalCount = 0;
tech.countJunkTech();
const randomBotCount = b.totalBots()
b.zeroBotCount()
//remove all bullets, respawn bots
@@ -1066,7 +1067,8 @@ const m = {
} else {
m.fieldRegen = 0.001 //6 energy per second
}
if (m.fieldMode === 0 || m.fieldMode === 4) m.fieldRegen += 0.008333 * m.coupling
if (m.fieldMode === 0 || m.fieldMode === 4) m.fieldRegen += 0.00133 * m.coupling //return `generate <strong>${(6*couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong> per second`
if (tech.isTimeCrystals) {
m.fieldRegen *= 3
} else if (tech.isGroundState) {
@@ -1589,7 +1591,7 @@ const m = {
case 3: //negative mass
return `<strong>+${((1-0.73 ** couple)*100).toFixed(1)}%</strong> <strong class='color-defense'>defense</strong>`
case 4: //assembler
return `generate <strong>${(5*couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong> per second`
return `generate <strong>${(8*couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong> per second`
case 5: //plasma
return `<strong>+${(15*couple).toFixed(0)}%</strong> <strong class='color-d'>damage</strong>`
case 6: //time dilation

View File

@@ -332,7 +332,7 @@ const powerUps = {
},
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
if (isCanceled) {
if (tech.isCancelTech && Math.random() < 0.88) {
if (tech.isCancelTech && Math.random() < 0.85) {
// powerUps.research.use('tech')
powerUps[type].effect();
return
@@ -356,7 +356,7 @@ const powerUps = {
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), spawnType, false);
}
}
if (tech.isCancelCouple) powerUps.coupling.spawnDelay(5)
if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 5)
// if (tech.isCancelTech && Math.random() < 0.3) {
// powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "tech", false);
// simulation.makeTextLog(`<strong>options exchange</strong>: returns 1 <strong class='color-m'>tech</strong>`)
@@ -401,20 +401,20 @@ const powerUps = {
effect() {
m.couplingChange(0.1)
},
spawnDelay(num) {
let count = num
let respawnDrones = () => {
if (count > 0) {
requestAnimationFrame(respawnDrones);
if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
count--
const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
powerUps.spawn(where.x, where.y, "coupling");
}
}
}
requestAnimationFrame(respawnDrones);
}
// spawnDelay(num) {
// let count = num
// let respawnDrones = () => {
// if (count > 0) {
// requestAnimationFrame(respawnDrones);
// if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
// count--
// const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
// powerUps.spawn(where.x, where.y, "coupling");
// }
// }
// }
// requestAnimationFrame(respawnDrones);
// }
},
boost: {
name: "boost",
@@ -1149,8 +1149,8 @@ const powerUps = {
let count = num
let cycle = () => {
if (count > 0) {
requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing && m.alive) { //&& !(simulation.cycle % 2)
if (m.alive) requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
count--
const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
powerUps.spawn(where.x, where.y, type);

View File

@@ -531,6 +531,15 @@ const simulation = {
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
},
cameraNoLook() {
ctx.save();
ctx.translate(canvas.width2, canvas.height2); //center
// ctx.scale(simulation.zoom / simulation.edgeZoomOutSmooth, simulation.zoom / simulation.edgeZoomOutSmooth); //zoom in once centered
ctx.translate(-canvas.width2 + m.transX, -canvas.height2 + m.transY); //translate
//calculate in game mouse position by undoing the zoom and translations
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
},
restoreCamera() {
ctx.restore();
},

View File

@@ -31,6 +31,7 @@ const tech = {
// tech.addLoreTechToPool();
tech.extraMaxHealth = 0;
tech.totalCount = 0;
tech.junkCount = 0 //tech.countJunkTech();
simulation.updateTechHUD();
},
removeTech(index = 'random') {
@@ -61,6 +62,7 @@ const tech = {
tech.tech[index].remove();
tech.tech[index].count = 0;
tech.totalCount -= totalRemoved
tech.countJunkTech();
simulation.updateTechHUD();
tech.tech[index].isLost = true
simulation.updateTechHUD();
@@ -90,7 +92,7 @@ const tech = {
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) countNonJunk += tech.tech[i].frequency
}
const num = percent * countNonJunk //scale number added
const num = Math.ceil(percent * countNonJunk) //scale number added
for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++ //add random array options to tech pool
simulation.makeTextLog(`<span class='color-var'>tech</span>.tech.push(${num.toFixed(0)} <span class='color-text'>JUNK</span>)`)
return num
@@ -154,9 +156,17 @@ const tech = {
tech.tech[index].effect(); //give specific tech
tech.tech[index].count++
tech.totalCount++ //used in power up randomization
tech.countJunkTech();
simulation.updateTechHUD();
}
},
junkCount: 0,
countJunkTech() {
tech.junkCount = 0
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count > 0 && tech.tech[i].isJunk) tech.junkCount++
}
},
// setTechoNonRefundable(name) {
// for (let i = 0; i < tech.tech.length; i++) {
// if (tech.tech.name === name) {
@@ -210,6 +220,7 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
let dmg = tech.damage //m.fieldDamage
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling
if (m.isSneakAttack && m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.33 * (1 + 0.33 * m.coupling)
@@ -218,7 +229,7 @@ const tech = {
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isDamageForGuns) dmg *= 1 + 0.13 * b.inventory.length
if (tech.isDamageForGuns) dmg *= 1 + 0.22 * Math.max(0, b.inventory.length - 1)
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25
if (tech.isAcidDmg && m.health > 1) dmg *= 1.35;
if (tech.isRerollDamage) dmg *= 1 + 0.038 * powerUps.research.count
@@ -288,7 +299,7 @@ const tech = {
},
tech: [{
name: "ordnance",
description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-g'>gun</strong><strong class='color-m'>tech</strong><br>spawn a <strong class='color-g'>gun</strong> and <strong>+5%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
description: "</strong>double</strong> the <strong class='flicker'>frequency</strong> of finding <strong class='color-g'>gun</strong><strong class='color-m'>tech</strong><br>spawn a <strong class='color-g'>gun</strong> and <strong>+7%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -302,7 +313,7 @@ const tech = {
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isGunTech) tech.tech[i].frequency *= 2
}
this.refundAmount += tech.addJunkTechToPool(0.05)
this.refundAmount += tech.addJunkTechToPool(0.07)
},
refundAmount: 0,
remove() {
@@ -315,7 +326,7 @@ const tech = {
{
name: "ad hoc",
descriptionFunction() {
return `spawn a ${powerUps.orb.heal()}, ${powerUps.orb.research(1)}, <strong class='color-f'>field</strong>, ${powerUps.orb.ammo(1)}, or <strong class='color-m'>tech</strong><br>for each of your <strong class='color-g'>guns</strong>`
return `spawn a ${powerUps.orb.heal()}, ${powerUps.orb.research(1)}, ${powerUps.orb.ammo(1)}, <strong class='color-f'>field</strong>, <strong class='color-g'>gun</strong>, or <strong class='color-m'>tech</strong><br>for each of your <strong class='color-g'>guns</strong>`
},
maxCount: 1, //random power up
count: 0,
@@ -325,10 +336,12 @@ const tech = {
allowed() {
return b.inventory.length > 1
},
requires: "NOT EXPERIMENT MODE, at least 2 guns",
requires: "at least 2 guns",
effect() {
for (let i = 0; i < b.inventory.length; i++) {
if (Math.random() < 1 / 5) {
if (Math.random() < 1 / 6) {
powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
} else if (Math.random() < 1 / 5) {
powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "tech");
} else if (Math.random() < 1 / 4) {
powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "field");
@@ -354,9 +367,9 @@ const tech = {
allowed() {
return b.inventory.length > 1
},
requires: "NOT EXPERIMENT MODE, at least 2 guns",
requires: "at least 2 guns",
effect() {
for (let i = b.inventory.length - 1; i > -1; i--) {
for (let i = b.inventory.length - 1; i > -1; i--) { //backwards because some tech can remove or add guns
const gunTechPool = [] //find gun tech for this gun
for (let j = 0, len = tech.tech.length; j < len; j++) {
// console.log(j, tech.tech[j].isGunTech, tech.tech[j].allowed(), !tech.tech[j].isJunk, !tech.tech[j].isBadRandomOption, tech.tech[j].count < tech.tech[j].maxCount)
@@ -382,13 +395,13 @@ const tech = {
},
{
name: "arsenal",
descriptionFunction() { return `<strong>+13%</strong> <strong class='color-d'>damage</strong> per <strong class='color-g'>gun</strong> <em>(${(13 * b.inventory.length).toFixed(0)}%)</em>` },
descriptionFunction() { return `<strong>+22%</strong> <strong class='color-d'>damage</strong> per unequipped <strong class='color-g'>gun</strong> <em>(${(22 * Math.max(0, b.inventory.length-1)).toFixed(0)}%)</em>` },
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed: () => true,
requires: "",
allowed: () => b.inventory.length > 1,
requires: "at least 2 guns",
effect() {
tech.isDamageForGuns = true;
},
@@ -398,13 +411,13 @@ const tech = {
},
{
name: "active cooling",
descriptionFunction() { return `<strong>+18%</strong> <em>fire rate</em> per <strong class='color-g'>gun</strong> <em>(${(18 * b.inventory.length).toFixed(0)}%)</em>` },
descriptionFunction() { return `<strong>+28%</strong> <em>fire rate</em> per unequipped <strong class='color-g'>gun</strong> <em>(${(28 * Math.max(0, b.inventory.length-1)).toFixed(0)}%)</em>` }, //<br>but not including your equipped <strong class='color-g'>gun</strong>` },
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed: () => true,
requires: "",
allowed: () => b.inventory.length > 1,
requires: "at least 2 guns",
effect() {
tech.isFireRateForGuns = true;
b.setFireCD();
@@ -414,6 +427,67 @@ const tech = {
b.setFireCD();
}
},
{
name: "pigeonhole principle",
descriptionFunction() {
var info = ""
if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
var gun = b.guns[b.inventory[tech.buffedGun]].name
var info = `<br>this level: <strong>+${(31 * Math.max(0, b.inventory.length)).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`
}
// return `
// a <strong class='color-g'>gun</strong> is <strong>chosen</strong> to be improved each <strong>level</strong>
// <br><strong>+${(31*b.inventory.length).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for ${gun}
// <br><strong class='color-d'>damage</strong> scales by 31% per unequipped <strong class='color-g'>gun</strong>`
return `
a new <strong class='color-g'>gun</strong> is <strong>chosen</strong> to be improved each <strong>level</strong>
<br><strong>+31%</strong> <strong class='color-d'>damage</strong> per <strong class='color-g'>gun</strong> for the <strong>chosen</strong> <strong class='color-g'>gun</strong>${info}`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return b.inventory.length > 1
},
requires: "at least 2 guns",
effect() {
tech.isGunChoice = true
//switches gun on new level
//generalist uses the same chosen gun so they match
},
remove() {
tech.isGunChoice = false;
}
},
{
name: "generalist",
description: "spawn <strong>7</strong> <strong class='color-g'>guns</strong>, but you can't <strong>switch</strong> <strong class='color-g'>guns</strong><br>your equipped <strong class='color-g'>gun</strong> cycles after each level",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return b.inventory.length < b.guns.length - 5 && b.inventory.length > 1
},
requires: "at least 2 guns, at least 5 unclaimed guns",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
},
remove() {
if (!this.count) tech.isGunCycle = false; // only set to false if you don't have this tech
// if (tech.isGunCycle) {
// for (let i = 0; i < 8; i++) {
// if (b.inventory.length) b.removeGun(b.guns[b.inventory[b.inventory.length - 1]].name) //remove your last gun
// }
// tech.isGunCycle = false;
// }
}
},
{
name: "first derivative",
descriptionFunction() { return `while your <strong>first</strong> <strong class='color-g'>gun</strong> is equipped<br><strong>+15%</strong> <strong class='color-defense'>defense</strong> per <strong class='color-g'>gun</strong> <em>(${(100*(1-0.85 ** b.inventory.length)).toFixed(0)}%)</em>` },
@@ -449,37 +523,9 @@ const tech = {
tech.isOneGun = false;
}
},
{
name: "generalist",
description: "spawn <strong>7</strong> <strong class='color-g'>guns</strong>, but you can't <strong>switch</strong> <strong class='color-g'>guns</strong><br><strong class='color-g'>guns</strong> cycle automatically with each new level",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return b.inventory.length < b.guns.length - 5 && b.inventory.length > 1 //(tech.isDamageForGuns || tech.isFireRateForGuns) &&
},
requires: "at least 2 guns, at least 5 unclaimed guns",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
},
remove() {
if (!this.count) tech.isGunCycle = false; // only set to false if you don't have this tech
// if (tech.isGunCycle) {
// for (let i = 0; i < 8; i++) {
// if (b.inventory.length) b.removeGun(b.guns[b.inventory[b.inventory.length - 1]].name) //remove your last gun
// }
// tech.isGunCycle = false;
// }
}
},
{
name: "supply chain",
junk: 0.05,
descriptionFunction() { return `for each <strong class='color-g'>gun</strong> in your inventory<br>double its <strong class='color-ammo'>ammo</strong>` },
descriptionFunction() { return `double your current <strong class='color-ammo'>ammo</strong><br><strong>+4%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool` },
maxCount: 9,
count: 0,
frequency: 1,
@@ -491,7 +537,7 @@ const tech = {
if (b.guns[i].have) b.guns[i].ammo = Math.floor(2 * b.guns[i].ammo)
}
simulation.makeGunHUD();
// this.refundAmount += tech.addJunkTechToPool(this.junk)
this.refundAmount += tech.addJunkTechToPool(0.04)
},
refundAmount: 0,
remove() {
@@ -501,10 +547,10 @@ const tech = {
}
}
simulation.makeGunHUD();
// if (this.count > 0 && this.refundAmount > 0) {
// tech.removeJunkTechFromPool(this.refundAmount)
// this.refundAmount = 0
// }
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
{
@@ -622,7 +668,7 @@ const tech = {
},
{
name: "dead reckoning",
description: "if your <strong>speed</strong> is 0<br><strong>+36%</strong> <strong class='color-d'>damage</strong>",
description: "if your <strong>speed</strong> is 0<br><strong>+50%</strong> <strong class='color-d'>damage</strong>",
maxCount: 9,
count: 0,
frequency: 1,
@@ -630,7 +676,7 @@ const tech = {
allowed() { return true },
requires: "",
effect() {
tech.restDamage += 0.36
tech.restDamage += 0.5
},
remove() {
tech.restDamage = 1;
@@ -811,7 +857,7 @@ const tech = {
},
{
name: "heuristics",
description: "<strong>+30%</strong> <strong><em>fire rate</em></strong>",
description: "<strong>+25%</strong> <strong><em>fire rate</em></strong><br>spawn a <strong class='color-g'>gun</strong>",
maxCount: 9,
count: 0,
frequency: 1,
@@ -819,8 +865,9 @@ const tech = {
allowed() { return true },
requires: "",
effect() {
tech.fireRate *= 0.7
tech.fireRate *= 0.75
b.setFireCD();
powerUps.spawn(m.pos.x, m.pos.y, "gun");
},
remove() {
tech.fireRate = 1;
@@ -2871,7 +2918,7 @@ const tech = {
isNonRefundable: true,
isBadRandomOption: true,
allowed() { return true },
requires: "NOT EXPERIMENT MODE",
requires: "",
effect() {
for (let i = 0; i < 13; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "heal");
for (let i = 0, len = tech.tech.length; i < len; i++) {
@@ -3251,7 +3298,7 @@ const tech = {
allowed() {
return !tech.extraChoices && !tech.isExtraGunField && !tech.isFlipFlopChoices
},
requires: "NOT EXPERIMENT MODE, not emergence, cross disciplinary, integrated circuit",
requires: "not emergence, cross disciplinary, integrated circuit",
effect() {
tech.isDeterminism = true;
//if you change the number spawned also change it in Born rule
@@ -3327,8 +3374,8 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
allowed() { return tech.junkCount > 0 },
requires: "some JUNK tech",
effect() {
tech.isMetaAnalysis = true
},
@@ -3611,7 +3658,7 @@ const tech = {
{
name: "options exchange",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Option_(finance)' class="link">options exchange</a>`,
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>88%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
description: `clicking <strong style = 'font-size:150%;'>×</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong> has a <strong>85%</strong><br>chance to randomize <strong>choices</strong> and not <strong>cancel</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3700,7 +3747,7 @@ const tech = {
},
{
name: "metastability",
description: "<strong>+11%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong class='color-dup'>duplicates</strong> <strong class='color-e'>explode</strong> with a <strong>3</strong> second <strong>half-life</strong>",
description: "<strong>+12%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong class='color-dup'>duplicates</strong> <strong class='color-e'>explode</strong> with a <strong>3</strong> second <strong>half-life</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -4773,9 +4820,11 @@ const tech = {
},
remove() {
tech.infiniteWaveAmmo = 1
if (this.count > 1 && b.guns[3].savedAmmo !== undefined) {
b.guns[3].ammo = b.guns[3].savedAmmo
simulation.updateGunHUD();
}
}
},
{
name: "phonon", //longitudinal //gravitational wave?
@@ -4858,7 +4907,7 @@ const tech = {
},
{
name: "sympathetic resonance",
description: "after a <strong>mob</strong> gets vibrated by a <strong>phonon</strong><br>a new <strong>resonance wave</strong> expands from their location",
description: "after a <strong>mob</strong> gets vibrated by a <strong>phonon</strong><br>a new <strong>resonance wave</strong> expands",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5538,6 +5587,57 @@ const tech = {
tech.isSporeFollow = false
}
},
{
name: "junk DNA",
descriptionFunction() { return `<strong>+53%</strong> ${b.guns[6].nameString()} <strong class='color-d'>damage</strong> per <strong class='color-j'>JUNK</strong><strong class='color-m'>tech</strong> <em>(${(53*tech.junkCount).toFixed(0)}%)</em><br><strong>+50%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool` },
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 0) || tech.isSporeWorm || tech.isSporeFlea
},
requires: "spores",
effect() {
tech.isJunkDNA = true
this.refundAmount += tech.addJunkTechToPool(0.5)
},
refundAmount: 0,
remove() {
tech.isJunkDNA = false
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
// {
// name: "junk DNA",
// //increase damage by 10% for each JUNK tech percent in the tech pool, remove all JUNK tech,
// descriptionFunction() { return `<strong>+50%</strong> ${b.guns[6].nameString()} <strong class='color-d'>damage</strong><br><strong>+15%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool` },
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 0) || tech.isSporeWorm || tech.isSporeFlea
// },
// requires: "spores",
// effect() {
// tech.isSporeWorm = true
// this.refundAmount += tech.addJunkTechToPool(0.15)
// },
// refundAmount: 0,
// remove() {
// tech.isSporeWorm = false
// if (this.count > 0 && this.refundAmount > 0) {
// tech.removeJunkTechFromPool(this.refundAmount)
// this.refundAmount = 0
// }
// }
// },
{
name: "mutualism",
descriptionFunction() { return `<strong>+150%</strong> ${b.guns[6].nameString()} <strong class='color-d'>damage</strong><br>${b.guns[6].nameString('s')} borrow <strong>0.5</strong> <strong class='color-h'>health</strong> until they <strong>die</strong>` },
@@ -5603,8 +5703,8 @@ const tech = {
isGunTech: true,
maxCount: 3,
count: 0,
frequency: 3,
frequencyDefault: 3,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isSporeWorm || tech.isSporeFlea
},
@@ -6159,7 +6259,7 @@ const tech = {
},
{
name: "alternator",
description: "<strong>+60%</strong> <strong>harpoon</strong> <strong class='color-f'>energy</strong> efficiency",
description: "<strong>+80%</strong> <strong>harpoon</strong> <strong class='color-f'>energy</strong> efficiency",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -8184,7 +8284,9 @@ const tech = {
isJunk: true,
allowed: () => true,
requires: "",
effect() {},
effect() {
if (Math.random() < 0.1) tech.damage *= 7.77
},
remove() {}
},
{
@@ -9899,6 +10001,38 @@ const tech = {
effect() {
m.shipMode()
level.difficultyDecrease(simulation.difficultyMode)
//unlock relativistic rotation
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].name === "relativistic rotation") tech.tech[i].frequency = 10
}
},
remove() {}
},
{
name: "circular symmetry",
description: "turning the ship rotates the universe instead<br><strong>+200%</strong> <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isJunk: true,
allowed() { return m.isShipMode },
requires: "",
effect() {
tech.damage *= 2
m.look = () => {
// const scale = 0;
m.transSmoothX = canvas.width2 - m.pos.x // - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y // - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * m.lookSmoothing;
m.transY += (m.transSmoothY - m.transY) * m.lookSmoothing;
ctx.restore();
ctx.save();
ctx.translate(canvas.width2, canvas.height2); //center
ctx.rotate(-m.angle)
ctx.translate(-canvas.width2, -canvas.height2); //center
}
},
remove() {}
},
@@ -10799,5 +10933,8 @@ const tech = {
isBoostPowerUps: null,
isBoostReplaceAmmo: null,
isFlipFlopCoupling: null,
infiniteWaveAmmo: null
infiniteWaveAmmo: null,
isJunkDNA: null,
buffedGun: 0,
isGunChoice: null,
}

View File

@@ -1,3 +1,4 @@
// https://ncase.me/sight-and-light/
// redblobgames.com/articles/visibility
// https://github.com/Silverwolf90/2d-visibility/tree/master/src
// could apply to explosions, neutron bomb, player LOS

View File

@@ -557,6 +557,11 @@ summary {
color: hsl(218, 100%, 58%);
}
.highlight {
border-radius: 6px;
background-color: #ff0;
padding: 3px;
}
/* colors for pause, selection and experiment */
/* #text-log {

View File

@@ -1,25 +1,62 @@
******************************************************** NEXT PATCH **************************************************
entanglement - your death leaves a power up for next run
renamed entanglement
also stores your gun and field
improved graphics for incompatible tech
tech: junk DNA - +53% spore/worm/flea damage per JUNK tech you have, +50% JUNK added to tech pool
tech: pigeonhole principle - +31% damage for each gun you have, while a chosen gun is active
chosen gun cycles each level
syncs well with generalist
heuristics 30->25% fire rate, and now spawns a gun
arsenal gives 13->22% damage per gun, but no longer counts your current gun
active cooling gives 18->28% fire rate per gun, but no longer counts your current gun
supply chain adds 4% JUNK
dead reckoning 36->50% damage
alternator harpoon 60->80% energy cost reduction
quickly releasing the fire button retracts harpoon early
JUNK tech - circular symmetry - ship gets 200% damage, ship only faces forward but you can rotate the universe
several bug fixes
coupling for molecular assembler 5->8 energy per second
but also fixed a bug where coupling was giving 10x regen
*********************************************************** TODO *****************************************************
lock mouse to the window until you press escape
https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API
canvas.requestPointerLock()
exitPointerLock
toggle off and on when:
you die and start a game
when choosing?
If this doesn't work it could at least be a fun JUNK tech
run canvas direct pixel editing while game is paused
just update once every second?
if it uses too much processing have a setting to toggle it off
this might help get players to spend more time relaxing on the power up selection
increase the click delay?
try again - line of sight https://ncase.me/sight-and-light/
for tech power ups no tech options are displayed until you research once
or display only JUNK until you research once
increase the number of options after each research
tech increase max energy and energy to 5000, but you can no longer regen energy through any process
it would be nice if there was incentive to go slow when choosing tech so n-gon is more relaxing
add some css based visual effects for opening up a tech,gun,field
make freeze and __ not cause death at health health, but just 600% extra damage for that bullet
make freeze and __ not cause death at 50% health, but just 600% extra damage for that bullet
new mob attibute - phosphorescence - mobs fire lasers for a few seconds after being hit with lasers
new mob status effect - phosphorescence - mobs fire lasers for a few seconds after being hit with lasers
make a new coupling effect for perfect diamagnetism or standing wave
make a faster smaller version of cell boss that also has map collisions
laserMines need a copy of laser-bot method
this is a very rare bug, so not a priority
@@ -53,13 +90,6 @@ JUNK tech description that changes similar to cards in inscription
that changes based on mouse position
can you tell if mouse is over card?
tech that encourages gun swapping
a field tech: molecular assembler, pilot wave, negative mass?
something similar to applied science, but also spawn a gun?
a bonus for each time a mob dies with a different active gun each level
+damage on that level
ammo, heals, research?
tech - buff MACHO range, effect, move speed?
while you are inside MACHO it will damage mobs?
@@ -1021,7 +1051,6 @@ possible names for tech
Gödel's incompleteness
quantum zeno effect (perturbation of a system prevents some systems from evolving because it scrambles coherence) (apply to lasers, fields)
counterfactual - something false
Pigeonhole principle - if there are several things that are matched up
regression to the mean
phlogiston theory is a superseded scientific theory that postulated the existence of a fire-like element called phlogiston
Laplace's demon was a notable published articulation of causal determinism on a scientific basis by Pierre-Simon Laplace in 1814.[1] According to determinism, if someone (the demon) knows the precise location and momentum of every atom in the universe, their past and future values for any given time are entailed; they can be calculated from the laws of classical mechanics.
@@ -1043,7 +1072,6 @@ possible names for tech
https://en.wikipedia.org/wiki/High-entropy_alloys
https://en.wikipedia.org/wiki/Refractory_metals
https://en.wikipedia.org/wiki/Upper-atmospheric_lightning#Elves
entanglement
prion quine - self replicating protein
Unitarity - https://en.wikipedia.org/wiki/Unitarity_(physics) - all probabilities add up to 1, calculations work the same forward and backwards in time
this is violated by expansion of the universe