From e0cd360d4c561254c72d82bcb284f169505cf97f Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Sun, 9 Jun 2024 21:40:47 -0400 Subject: [PATCH] Add the Roaming Glitch --- src/Myrian/Helper.tsx | 72 ++++++++++++++++++++++++++++++++- src/Myrian/formulas/glitches.ts | 2 + src/Myrian/ui/MyrianRoot.tsx | 2 +- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/Myrian/Helper.tsx b/src/Myrian/Helper.tsx index 9665d5175..6fe3af051 100644 --- a/src/Myrian/Helper.tsx +++ b/src/Myrian/Helper.tsx @@ -1,6 +1,8 @@ import { DeviceType, Component, Lock, Glitch } from "@nsdefs"; -import { Myrian, findDevice } from "./Myrian"; +import { Myrian, findDevice, inMyrianBounds } from "./Myrian"; import { getNextISocketRequest } from "./formulas/formulas"; +import { decodeBase64 } from "bcryptjs"; +import { roamingTime } from "./formulas/glitches"; export const myrianSize = 12; @@ -178,4 +180,72 @@ setInterval(() => { } }, 30000); +const clamp = (min: number, v: number, max: number) => Math.min(Math.max(v, min), max); +let globalOffset = 0; +const dirDiff = (v: number): number => { + globalOffset++; + const r = Math.random(); + const d = v - (myrianSize - 1) / 2; + const h = d > 0 ? -1 : 1; + + const dv = Math.floor(r * 3 + h * Math.random() * Math.sin(globalOffset * 0.05) * Math.abs(d)) - 1; + return clamp(-1, dv, 1); +}; + +const isEmpty = (x: number, y: number) => { + if (!inMyrianBounds(x, y)) return false; + return !findDevice([x, y]); +}; + +const dirs = [ + [0, 1], + [0, -1], + [1, 0], + [-1, 0], +]; + +const applyRoaming = () => { + const roaming = myrian.glitches[Glitch.Roaming]; + setTimeout(applyRoaming, roamingTime(roaming)); + if (roaming === 0) return; + myrian.devices.forEach((device) => { + if (device.type !== DeviceType.OSocket && device.type !== DeviceType.ISocket) return; + if (device.isBusy) return; + let canMove = false; + for (const dir of dirs) { + const [dx, dy] = dir; + if (isEmpty(device.x + dx, device.y + dy)) { + canMove = true; + break; + } + } + let x = -1; + let y = -1; + if (canMove) { + let dx = dirDiff(device.x); + let dy = dirDiff(device.y); + + if (dx !== 0 && dy !== 0) { + if (Math.random() > 0.5) { + dx = 0; + } else { + dy = 0; + } + } + x = device.x + dx; + y = device.y + dy; + } else { + x = Math.floor(Math.random() * myrianSize); + y = Math.floor(Math.random() * myrianSize); + } + + if (findDevice([x, y])) return; + if (!inMyrianBounds(x, y)) return; + device.x = x; + device.y = y; + }); +}; + +setTimeout(applyRoaming, 0); + resetMyrian(); diff --git a/src/Myrian/formulas/glitches.ts b/src/Myrian/formulas/glitches.ts index a71b8d5d9..bf85463ad 100644 --- a/src/Myrian/formulas/glitches.ts +++ b/src/Myrian/formulas/glitches.ts @@ -40,3 +40,5 @@ export const jammingMult = (lvl: number) => Math.pow(1.3, lvl); // energy loss export const magnetismLoss = (lvl: number) => lvl; + +export const roamingTime = (lvl: number) => 30000 * Math.pow(0.7, lvl); diff --git a/src/Myrian/ui/MyrianRoot.tsx b/src/Myrian/ui/MyrianRoot.tsx index 02f9402c4..37b5e60fb 100644 --- a/src/Myrian/ui/MyrianRoot.tsx +++ b/src/Myrian/ui/MyrianRoot.tsx @@ -79,7 +79,7 @@ const YHeader = () => { interface IProps {} export const MyrianRoot = (__props: IProps): React.ReactElement => { - useRerender(200); + useRerender(50); return ( Myrian OS