├── .gitignore
├── mfm-js
├── renderers
│ └── pixi
│ │ ├── element.png
│ │ └── renderer.ts
├── tsconfig.json
├── dist
│ ├── src
│ │ ├── elements
│ │ │ ├── core
│ │ │ │ ├── Builder.d.ts
│ │ │ │ ├── DReg.d.ts
│ │ │ │ ├── Res.d.ts
│ │ │ │ ├── ForkBomb.d.ts
│ │ │ │ ├── AntiForkBomb.d.ts
│ │ │ │ ├── Empty.d.ts
│ │ │ │ ├── Water.d.ts
│ │ │ │ ├── Goop.d.ts
│ │ │ │ ├── Wall.d.ts
│ │ │ │ ├── Sand.d.ts
│ │ │ │ └── SwapLine.d.ts
│ │ │ ├── agents
│ │ │ │ ├── ofswamp
│ │ │ │ │ ├── Swampling.d.ts
│ │ │ │ │ ├── SwampWorker.d.ts
│ │ │ │ │ └── Swamp.d.ts
│ │ │ │ ├── Bein.d.ts
│ │ │ │ ├── Sentry.d.ts
│ │ │ │ ├── DirectorWall.d.ts
│ │ │ │ ├── MeshNet.d.ts
│ │ │ │ ├── DirectionalDirector.d.ts
│ │ │ │ ├── LivingWall.d.ts
│ │ │ │ ├── Looper.d.ts
│ │ │ │ ├── Signal.d.ts
│ │ │ │ ├── SwapWorm.d.ts
│ │ │ │ ├── HardCell3.d.ts
│ │ │ │ ├── Wanderer.d.ts
│ │ │ │ └── Director.d.ts
│ │ │ └── components
│ │ │ │ └── WormTrap.d.ts
│ │ ├── mfm
│ │ │ ├── ElementRegistry.d.ts
│ │ │ ├── Capability.d.ts
│ │ │ ├── Site.d.ts
│ │ │ ├── TileCoordinate.d.ts
│ │ │ ├── Tile.d.ts
│ │ │ ├── Element.d.ts
│ │ │ ├── VirtualEventWindow.d.ts
│ │ │ ├── EventWindow.d.ts
│ │ │ └── Wayfinder.d.ts
│ │ ├── capabilities
│ │ │ ├── Decay.d.ts
│ │ │ ├── Build.d.ts
│ │ │ ├── Swap.d.ts
│ │ │ ├── Perception.d.ts
│ │ │ ├── Repel.d.ts
│ │ │ └── Wayfinding.d.ts
│ │ └── main.d.ts
│ └── renderers
│ │ └── pixi
│ │ └── renderer.d.ts
├── vite.config.js
├── src
│ ├── elements
│ │ ├── agents
│ │ │ ├── Bein.ts
│ │ │ ├── Sentry.ts
│ │ │ ├── ofswamp
│ │ │ │ ├── Swampling.ts
│ │ │ │ ├── SwampWorker.ts
│ │ │ │ └── Swamp.ts
│ │ │ ├── LivingWall.ts
│ │ │ ├── DirectorWall.ts
│ │ │ ├── DirectionalDirector.ts
│ │ │ ├── Signal.ts
│ │ │ ├── MeshNet.ts
│ │ │ ├── Looper.ts
│ │ │ ├── Director.ts
│ │ │ ├── SwapWorm.ts
│ │ │ └── HardCell3.ts
│ │ ├── core
│ │ │ ├── Res.ts
│ │ │ ├── Empty.ts
│ │ │ ├── ForkBomb.ts
│ │ │ ├── AntiForkBomb.ts
│ │ │ ├── DReg.ts
│ │ │ ├── Builder.ts
│ │ │ ├── Water.ts
│ │ │ ├── Wall.ts
│ │ │ ├── Sand.ts
│ │ │ ├── Goop.ts
│ │ │ └── SwapLine.ts
│ │ └── components
│ │ │ └── WormTrap.ts
│ ├── mfm
│ │ ├── Capability.ts
│ │ ├── ElementRegistry.ts
│ │ ├── TileCoordinate.ts
│ │ ├── Site.ts
│ │ ├── Element.ts
│ │ └── Tile.ts
│ ├── capabilities
│ │ ├── Decay.ts
│ │ ├── Swap.ts
│ │ ├── Build.ts
│ │ ├── Perception.ts
│ │ ├── Wayfinding.ts
│ │ └── Repel.ts
│ └── main.ts
└── package.json
├── mfmrocks
├── src
│ ├── env.d.ts
│ ├── scripts
│ │ └── renderers
│ │ │ └── pixi
│ │ │ └── element.png
│ ├── pages
│ │ ├── lemmings
│ │ │ ├── _game
│ │ │ │ ├── renderer
│ │ │ │ │ ├── element.png
│ │ │ │ │ ├── sprites
│ │ │ │ │ │ ├── CIRCLE.png
│ │ │ │ │ │ ├── DIRT.png
│ │ │ │ │ │ ├── LEMM.png
│ │ │ │ │ │ ├── POWER.png
│ │ │ │ │ │ ├── ROCK.png
│ │ │ │ │ │ ├── SOLID.png
│ │ │ │ │ │ ├── lemmings.png
│ │ │ │ │ │ ├── LEMM_HEAD.png
│ │ │ │ │ │ ├── lemm-test.png
│ │ │ │ │ │ ├── lemm-test.json
│ │ │ │ │ │ └── lemmings.json
│ │ │ │ │ └── sprites.ts
│ │ │ │ ├── elements
│ │ │ │ │ ├── LemmingEmitter.ts
│ │ │ │ │ ├── Dirt.ts
│ │ │ │ │ ├── Power.ts
│ │ │ │ │ ├── Exit.ts
│ │ │ │ │ └── Lemming.ts
│ │ │ │ ├── useGameState.js
│ │ │ │ └── LemmingsGame.vue
│ │ │ └── index.astro
│ │ └── index.astro
│ ├── styles
│ │ └── main.scss
│ └── components
│ │ └── mfms.vue
├── public
│ ├── v1
│ │ ├── gameFiles
│ │ │ ├── ding.wav
│ │ │ ├── qblip.wav
│ │ │ ├── tick.wav
│ │ │ ├── Dreaming.ogg
│ │ │ ├── levelend.mp3
│ │ │ ├── turnblip.wav
│ │ │ └── VoicesFromHeaven.ogg
│ │ ├── resources
│ │ │ ├── element.png
│ │ │ ├── mfmrocks-logo.png
│ │ │ └── art
│ │ │ │ ├── mfm-mason-web.jpg
│ │ │ │ ├── mfm-compute-web.jpg
│ │ │ │ ├── mfm-compute2-web.jpg
│ │ │ │ ├── mfm-dregres-web.jpg
│ │ │ │ ├── mfm-forkbomb-web.jpg
│ │ │ │ └── mfm-carpeeventwindow-web.jpg
│ │ ├── eventwindow.html
│ │ ├── webpack.config.js.map
│ │ ├── webpack.config.js
│ │ ├── TileConnector.js
│ │ └── p2p.html
│ ├── images
│ │ ├── mfm-lemmings.png
│ │ └── mfmrocks-logo.png
│ └── favicon.svg
├── tsconfig.json
├── .vscode
│ ├── extensions.json
│ └── launch.json
├── .gitignore
├── astro.config.mjs
├── package.json
└── README.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | package-lock.json
4 | .vercel
5 | env.d.ts
--------------------------------------------------------------------------------
/mfm-js/renderers/pixi/element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfm-js/renderers/pixi/element.png
--------------------------------------------------------------------------------
/mfmrocks/src/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/ding.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/ding.wav
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/qblip.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/qblip.wav
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/tick.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/tick.wav
--------------------------------------------------------------------------------
/mfmrocks/public/images/mfm-lemmings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/images/mfm-lemmings.png
--------------------------------------------------------------------------------
/mfmrocks/public/images/mfmrocks-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/images/mfmrocks-logo.png
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/Dreaming.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/Dreaming.ogg
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/levelend.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/levelend.mp3
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/turnblip.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/turnblip.wav
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/element.png
--------------------------------------------------------------------------------
/mfmrocks/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "astro/tsconfigs/base",
3 | "compilerOptions": {
4 | "jsx": "preserve"
5 | }
6 | }
--------------------------------------------------------------------------------
/mfmrocks/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["astro-build.astro-vscode"],
3 | "unwantedRecommendations": []
4 | }
5 |
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/mfmrocks-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/mfmrocks-logo.png
--------------------------------------------------------------------------------
/mfmrocks/src/scripts/renderers/pixi/element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/scripts/renderers/pixi/element.png
--------------------------------------------------------------------------------
/mfmrocks/public/v1/gameFiles/VoicesFromHeaven.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/gameFiles/VoicesFromHeaven.ogg
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/art/mfm-mason-web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/art/mfm-mason-web.jpg
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/art/mfm-compute-web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/art/mfm-compute-web.jpg
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/art/mfm-compute2-web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/art/mfm-compute2-web.jpg
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/art/mfm-dregres-web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/art/mfm-dregres-web.jpg
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/art/mfm-forkbomb-web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/art/mfm-forkbomb-web.jpg
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/element.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/element.png
--------------------------------------------------------------------------------
/mfmrocks/public/v1/resources/art/mfm-carpeeventwindow-web.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/public/v1/resources/art/mfm-carpeeventwindow-web.jpg
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/CIRCLE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/CIRCLE.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/DIRT.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/DIRT.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/LEMM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/LEMM.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/POWER.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/POWER.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/ROCK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/ROCK.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/SOLID.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/SOLID.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/lemmings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/lemmings.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/LEMM_HEAD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/LEMM_HEAD.png
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/lemm-test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/walpolea/MFM-JS/HEAD/mfmrocks/src/pages/lemmings/_game/renderer/sprites/lemm-test.png
--------------------------------------------------------------------------------
/mfm-js/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib":["ES2019"],
4 | "emitDeclarationOnly": true,
5 | "declaration": true,
6 | "esModuleInterop": true,
7 | "moduleResolution": "nodenext"
8 | }
9 | }
--------------------------------------------------------------------------------
/mfmrocks/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "command": "./node_modules/.bin/astro dev",
6 | "name": "Development server",
7 | "request": "launch",
8 | "type": "node-terminal"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/mfmrocks/public/v1/eventwindow.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MFM.ROCKS - Event Window
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Builder.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Builder extends Element {
5 | constructor(type: IElementType, state?: any);
6 | init(): void;
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfmrocks/.gitignore:
--------------------------------------------------------------------------------
1 | # build output
2 | dist/
3 | # generated types
4 | .astro/
5 |
6 | # dependencies
7 | node_modules/
8 |
9 | # logs
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | pnpm-debug.log*
14 |
15 |
16 | # environment variables
17 | .env
18 | .env.production
19 |
20 | # macOS-specific files
21 | .DS_Store
22 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/ElementRegistry.d.ts:
--------------------------------------------------------------------------------
1 | import { IElementType } from './Element';
2 |
3 | export declare class ElementRegistry {
4 | static TYPES: Map;
5 | static GROUPS: Map;
6 | static registerType(type: IElementType): void;
7 | static getType(type: string | IElementType): IElementType;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/Capability.d.ts:
--------------------------------------------------------------------------------
1 | export interface ICapability {
2 | name: string;
3 | do: Function;
4 | }
5 | export declare class CapabilityRegistry {
6 | static CAPABILITIES: Map;
7 | static registerCapability(cap: ICapability): void;
8 | static getCapability(cap: string | ICapability): ICapability;
9 | }
10 |
--------------------------------------------------------------------------------
/mfmrocks/astro.config.mjs:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'astro/config';
2 | import vue from "@astrojs/vue";
3 |
4 | // https://astro.build/config
5 | export default defineConfig({
6 | redirects: {
7 | // '/v1': '/v1/index.html',
8 | // '/v1/game': '/v1/game/index.html',
9 | // '/v1/game/maker': '/v1/game/maker.html'
10 | },
11 | integrations: [vue()]
12 | });
--------------------------------------------------------------------------------
/mfm-js/dist/src/capabilities/Decay.d.ts:
--------------------------------------------------------------------------------
1 | import { Element } from '../mfm/Element';
2 | import { EventWindow } from '../mfm/EventWindow';
3 |
4 | export declare class Decay {
5 | static MAKE_DECAY(lifeSpan: number, deathChance?: number): (ew: EventWindow, self: Element) => void;
6 | static DECAY(ew: EventWindow, self: Element, lifeSpan: number, deathChance?: number): boolean;
7 | }
8 |
--------------------------------------------------------------------------------
/mfm-js/vite.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { defineConfig } = require('vite');
3 | import dts from 'vite-plugin-dts';
4 |
5 | module.exports = defineConfig({
6 | build: {
7 | lib: {
8 | entry: path.resolve(__dirname, 'src/main.ts'),
9 | name: 'MFM-JS',
10 | fileName: (format) => `mfm.${format}.js`
11 | },
12 | },
13 | plugins: [dts()],
14 | });
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/DReg.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class DReg extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Res.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Res extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/ForkBomb.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class ForkBomb extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/AntiForkBomb.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class AntiForkBomb extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/ofswamp/Swampling.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../../mfm/Element';
2 | import { EventWindow } from '../../../mfm/EventWindow';
3 |
4 | export declare class Swampling extends Element {
5 | static CREATE: (_typeDefinition?: import('../../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/Bein.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Bein extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | init(): void;
8 | behave(ew: EventWindow): void;
9 | }
10 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/ofswamp/SwampWorker.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../../mfm/Element';
2 | import { EventWindow } from '../../../mfm/EventWindow';
3 |
4 | export declare class SwampWorker extends Element {
5 | static CREATE: (_typeDefinition?: import('../../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | behave(ew: EventWindow): void;
8 | }
9 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Empty.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Empty extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | init(): void;
8 | behave(ew: EventWindow): void;
9 | }
10 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/Sentry.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Sentry extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | init(): void;
8 | behave(ew: EventWindow): void;
9 | }
10 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/DirectorWall.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class DirectorWall extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | constructor(type: IElementType, state?: any);
7 | init(): void;
8 | behave(ew: EventWindow): void;
9 | }
10 |
--------------------------------------------------------------------------------
/mfmrocks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "type": "module",
4 | "version": "0.0.1",
5 | "scripts": {
6 | "dev": "astro dev",
7 | "start": "astro dev",
8 | "build": "astro build",
9 | "preview": "astro preview",
10 | "astro": "astro"
11 | },
12 | "dependencies": {
13 | "@astrojs/vue": "^4.0.8",
14 | "astro": "^4.4.15",
15 | "mfm-js": "file:../mfm-js",
16 | "pixi.js": "^8.0.4",
17 | "sass": "^1.71.1",
18 | "vue": "^3.4.21"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/lemm-test.json:
--------------------------------------------------------------------------------
1 | {"frames":{"DIRT.png":{"frame":{"x":0,"y":0,"w":32,"h":32},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":32,"h":32},"sourceSize":{"w":32,"h":32}},"ROCK.png":{"frame":{"x":0,"y":32,"w":32,"h":32},"rotated":false,"trimmed":false,"spriteSourceSize":{"x":0,"y":0,"w":32,"h":32},"sourceSize":{"w":32,"h":32}}},"meta":{"app":"https://github.com/piskelapp/piskel/","version":"1.0","image":"./renderer/sprites/lemm-test.png","format":"RGBA8888","size":{"w":32,"h":64}}}
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/Site.d.ts:
--------------------------------------------------------------------------------
1 | import { Element } from './Element';
2 | import { EventWindow } from './EventWindow';
3 | import { TileCoordinate } from './TileCoordinate';
4 |
5 | export declare class Site {
6 | location: TileCoordinate;
7 | id: string;
8 | atom: Element;
9 | baseAtom: Element;
10 | ew: EventWindow;
11 | constructor(_loc: TileCoordinate);
12 | create(): void;
13 | swapAtoms(targetSite: Site): boolean;
14 | mutate(atom: Element): void;
15 | mutateBase(atom: Element): void;
16 | }
17 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/agents/Bein.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow } from "../../mfm/EventWindow";
3 |
4 | export class Bein extends Element {
5 | static CREATE = Bein.CREATOR({ name: "BEIN", symbol: "BNG", class: Bein, color: 0xbe146f, groups: ["MFM"] });
6 |
7 | constructor(type: IElementType, state: any = {}) {
8 | super(type, state);
9 |
10 | this.init();
11 | }
12 |
13 | init() {}
14 |
15 | behave(ew: EventWindow) {
16 | super.behave(ew);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/Res.ts:
--------------------------------------------------------------------------------
1 | import { Swap } from "../../capabilities/Swap";
2 | import { Element, IElementType } from "../../mfm/Element";
3 | import { EventWindow } from "../../mfm/EventWindow";
4 |
5 | export class Res extends Element {
6 | static CREATE = Res.CREATOR({ name: "RES", class: Res, color: 0x0e5100, groups: ["MFM"] });
7 |
8 | constructor(type: IElementType, state: any = {}) {
9 | super(type, state);
10 | }
11 |
12 | behave(ew: EventWindow) {
13 | super.behave(ew);
14 |
15 | Swap.PATROL(ew);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/TileCoordinate.d.ts:
--------------------------------------------------------------------------------
1 | export interface ICoordinate {
2 | x: number;
3 | y: number;
4 | }
5 | export interface ITileCoordinate {
6 | id: string;
7 | coordinate: ICoordinate;
8 | }
9 | export declare class TileCoordinate {
10 | static CoordinateToId(c: ICoordinate): string;
11 | static IdToCoordinate(id: string): ICoordinate;
12 | static fromCoordinate(c: ICoordinate): TileCoordinate;
13 | static fromId(id: string): TileCoordinate;
14 | id: string;
15 | coordinate: ICoordinate;
16 | constructor(id: string);
17 | }
18 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/Empty.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow } from "../../mfm/EventWindow";
3 |
4 | export class Empty extends Element {
5 | static CREATE = Empty.CREATOR({ name: "EMPTY", symbol: "EMT", class: Empty, color: 0x2a2a2a, groups: ["MFM"] });
6 |
7 | constructor(type: IElementType, state: any = {}) {
8 | super(type, state);
9 |
10 | this.init();
11 | }
12 |
13 | init() {
14 | this.classifyAs("EMPTY");
15 | }
16 |
17 | behave(ew: EventWindow) {
18 | super.behave(ew);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/mfm-js/src/mfm/Capability.ts:
--------------------------------------------------------------------------------
1 | export interface ICapability {
2 | name: string;
3 | do: Function;
4 | }
5 |
6 | export class CapabilityRegistry {
7 | static CAPABILITIES: Map = new Map();
8 |
9 | static registerCapability(cap: ICapability) {
10 | this.CAPABILITIES.set(cap.name.toUpperCase(), cap);
11 | }
12 |
13 | static getCapability(cap: string | ICapability): ICapability {
14 | return typeof cap === "string" ? this.CAPABILITIES.get(cap.toUpperCase()) : this.CAPABILITIES.get(cap.name.toUpperCase());
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/MeshNet.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class MeshNet extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static ATTRACT: (ew: EventWindow, self: Element) => boolean;
7 | static AVOID: (ew: EventWindow, self: Element) => boolean;
8 | constructor(type: IElementType, state?: any);
9 | init(): void;
10 | behave(ew: EventWindow): void;
11 | }
12 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/DirectionalDirector.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class DirectionalDirector extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static DDIR_ONCE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | constructor(type: IElementType, state?: any);
8 | init(): void;
9 | behave(ew: EventWindow): void;
10 | }
11 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/ofswamp/Swamp.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../../mfm/Element';
2 | import { EventWindow } from '../../../mfm/EventWindow';
3 |
4 | export declare class Swamp extends Element {
5 | static CREATE: (_typeDefinition?: import('../../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static BOG: (_typeDefinition?: import('../../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | constructor(type: IElementType, state?: any);
8 | init(): void;
9 | behave(ew: EventWindow): void;
10 | grow(ew: EventWindow): void;
11 | }
12 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/components/WormTrap.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class WormTrap extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static BUILDER: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | constructor(type: IElementType, state?: any);
8 | init(): void;
9 | behave(ew: EventWindow): void;
10 | captureWorm(ew: EventWindow): Boolean;
11 | }
12 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/ForkBomb.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow } from "../../mfm/EventWindow";
3 |
4 | export class ForkBomb extends Element {
5 | static CREATE = ForkBomb.CREATOR({ name: "FORKBOMB", symbol: "FKB", class: ForkBomb, color: 0xdd0000, groups: ["MFM"] });
6 |
7 | constructor(type: IElementType, state: any = {}) {
8 | super(type, state);
9 | }
10 |
11 | behave(ew: EventWindow) {
12 | super.behave(ew);
13 | ew.replace(EventWindow.RANDOM(EventWindow.ADJACENT4WAY), ForkBomb.CREATE({ color: (this.rd("color") + 512) % 0xffffff }));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/capabilities/Build.d.ts:
--------------------------------------------------------------------------------
1 | import { EventWindow, EWIndex } from '../mfm/EventWindow';
2 |
3 | export declare class Build {
4 | static GRID: (ew: EventWindow, multiplier: Function, creator: Function) => boolean;
5 | static SMALL_GRID: (ew: EventWindow, multiplier: Function, creator: Function) => boolean;
6 | static H_LINE: (ew: EventWindow, multiplier: Function, creator: Function) => boolean;
7 | static V_LINE: (ew: EventWindow, multiplier: Function, creator: Function) => boolean;
8 | static MAKE_REPEATER(destinations: EWIndex[], steps?: number): (ew: EventWindow, multiplier: Function, creator: Function) => boolean;
9 | }
10 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/LivingWall.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class LivingWall extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static MOVABLE_LIVING_WALL: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | constructor(type: IElementType, state?: any);
8 | init(): void;
9 | behave(ew: EventWindow): void;
10 | populateRegenMap(ew: EventWindow): void;
11 | regen(ew: EventWindow): void;
12 | }
13 |
--------------------------------------------------------------------------------
/mfmrocks/public/v1/webpack.config.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"webpack.config.js","sourceRoot":"","sources":["../webpack.config.js"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAE7B,MAAM,CAAC,OAAO,GAAG;IACf,KAAK,EAAE,gBAAgB;IACvB,OAAO,EAAE,mBAAmB;IAC5B,MAAM,EAAE;QACN,KAAK,EAAE;YACL;gBACE,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,iCAAiC;gBAC1C,GAAG,EAAE;oBACH,MAAM,EAAE,cAAc;oBACtB,OAAO,EAAE;wBACP,OAAO,EAAE,CAAC,mBAAmB,CAAC;qBAC/B;iBACF;aACF;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,GAAG,EAAE,WAAW;gBAChB,OAAO,EAAE,cAAc;aACxB;SACF;KACF;IACD,OAAO,EAAE;QACP,UAAU,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC;KACnC;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;KACtC;CACF,CAAC"}
--------------------------------------------------------------------------------
/mfm-js/dist/src/capabilities/Swap.d.ts:
--------------------------------------------------------------------------------
1 | import { IElementType } from '../mfm/Element';
2 | import { EventWindow, EWIndex } from '../mfm/EventWindow';
3 |
4 | export declare class Swap {
5 | static DOWN: (ew: EventWindow, chance?: number) => boolean;
6 | static SIDE: (ew: EventWindow, chance?: number) => boolean;
7 | static SLIP: (ew: EventWindow, chance?: number) => boolean;
8 | static SINK: (ew: EventWindow, chance?: number) => boolean;
9 | static FLOAT: (ew: EventWindow, chance?: number) => boolean;
10 | static PATROL: (ew: EventWindow, chance?: number) => boolean;
11 | static PATROL_8: (ew: EventWindow, chance?: number) => boolean;
12 | static CREATE(direction: EWIndex[], type?: string | IElementType): (ew: EventWindow, chance?: number) => boolean;
13 | }
14 |
--------------------------------------------------------------------------------
/mfmrocks/public/favicon.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/mfmrocks/src/styles/main.scss:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | margin: 0;
7 | padding: 10px;
8 | background: #222;
9 | display: grid;
10 | justify-items: center;
11 | color: white;
12 | min-height: 100vh;
13 | font-family: sans-serif;
14 | }
15 |
16 | header {
17 | padding: 50px;
18 | }
19 |
20 | h3 {
21 | margin-block: 0px 5px;
22 | }
23 |
24 | ul {
25 | padding: 0;
26 | }
27 |
28 |
29 |
30 | nav ul {
31 | display: flex;
32 | flex-wrap: wrap;
33 | justify-content: center;
34 | list-style-type: none;
35 | margin: 0;
36 | padding: 0;
37 | gap: 1rem;
38 | }
39 |
40 | nav ul li {
41 | margin-inline: 20px;
42 | text-align: center;
43 | }
44 |
45 | nav ul li a, footer a {
46 | color: #e1325e;
47 |
48 | &:visited {
49 | color: lightsalmon;
50 | }
51 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MFM-JS (v2)
2 |
3 | ## Movable Feast Machine simulator built in JavaScript
4 |
5 | ---
6 |
7 | ### The idea here is not to port MFM to JavaScript, but instead simulate it enough and provide an environment that is easy to quickly get hands-on with robust-first programming.
8 |
9 | ---
10 |
11 | Prerequisites
12 |
13 | - nodejs 18+ (_I use nvm to easily manage and upgrade node versions_) (https://nodejs.org)
14 | - an IDE like VS Code (https://code.visualstudio.com/)
15 |
16 | Install
17 |
18 | - git clone https://github.com/walpolea/MFM-JS.git
19 | - `cd MFM-JS/mfm-js`
20 | - `npm install`
21 | - `npm run build`
22 | - the library builds to `/mfm-js/dist`
23 | - also serve up `index.html` with `npm run dev` to watch chaanges as you build things.
24 | - note that the renderers are no longer bundled with the main library
25 |
--------------------------------------------------------------------------------
/mfm-js/src/capabilities/Decay.ts:
--------------------------------------------------------------------------------
1 | import { Element } from "../mfm/Element";
2 | import { EventWindow } from "../mfm/EventWindow";
3 |
4 | export class Decay {
5 | static MAKE_DECAY(lifeSpan: number, deathChance: number = 1) {
6 | return (ew: EventWindow, self: Element) => {
7 | const { age } = self.state;
8 |
9 | if (age > lifeSpan) {
10 | if (EventWindow.oneIn(deathChance)) {
11 | ew.destroy();
12 | }
13 | }
14 | };
15 | }
16 |
17 | static DECAY(ew: EventWindow, self: Element, lifeSpan: number, deathChance: number = 1): boolean {
18 | const { age } = self.state;
19 |
20 |
21 | if (age > lifeSpan) {
22 | if (EventWindow.oneIn(deathChance)) {
23 | ew.destroy();
24 | return true;
25 | }
26 | }
27 | return false;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/capabilities/Perception.d.ts:
--------------------------------------------------------------------------------
1 | import { IElementType } from '../mfm/Element';
2 | import { EventWindow, EWIndex } from '../mfm/EventWindow';
3 | import { Direction } from '../mfm/Wayfinder';
4 |
5 | export type SignalType = "WARN" | "INFORM" | "BECKON";
6 | export type Message = {
7 | senderId: string;
8 | senderType: IElementType | string;
9 | signalType: SignalType;
10 | message: string;
11 | signalDirection?: Direction;
12 | };
13 | export declare class Perception {
14 | static SENSE(ew: EventWindow, type: IElementType | string, withinSet?: EWIndex[], minQuantity?: number, maxQuantity?: number): boolean;
15 | static SIGNAL(ew: EventWindow, signalType: SignalType, message: Message): void;
16 | static RECEIVE_SIGNAL(ew: EventWindow, self: Element, indexes?: EWIndex[]): Message | null;
17 | }
18 |
--------------------------------------------------------------------------------
/mfm-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mfm-js",
3 | "version": "2.0.0",
4 | "description": "A movable feast machine simulator in JavaScript",
5 | "files": [
6 | "dist"
7 | ],
8 | "main": "./dist/mfm.umd.js",
9 | "module": "./dist/mfm.es.js",
10 | "exports": {
11 | ".": {
12 | "import": "./dist/mfm.es.js",
13 | "require": "./dist/mfm.umd.js"
14 | }
15 | },
16 | "scripts": {
17 | "dev": "vite",
18 | "build": "vite build",
19 | "preview": "vite preview"
20 | },
21 | "keywords": [],
22 | "author": "",
23 | "license": "ISC",
24 | "dependencies": {
25 | "pixi.js": "^8.0.0",
26 | "typescript": "^5.4.2"
27 | },
28 | "devDependencies": {
29 | "@types/node": "^20.11.25",
30 | "pixi.js": "^8.0.0",
31 | "vite": "^5.2.7",
32 | "vite-plugin-dts": "^3.7.3"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/Tile.d.ts:
--------------------------------------------------------------------------------
1 | import { Site } from './Site';
2 | import { ICoordinate } from './TileCoordinate';
3 |
4 | export declare class Tile {
5 | width: number;
6 | height: number;
7 | sites: Map;
8 | sitesArray: Site[];
9 | rands: Array;
10 | cur: number;
11 | isRunning: boolean;
12 | constructor(_width?: number, _height?: number);
13 | seedRandoms(): void;
14 | getSiteByCoordinate(c: ICoordinate): Site;
15 | getSiteById(id: string): Site;
16 | getRandomSite(): Site;
17 | getRandomSiteSeeded(): Site;
18 | getRandomSiteInRange(range: number[]): Site;
19 | getRandomSiteInRangeSeeded(range: number[]): Site;
20 | create(): void;
21 | add(atomizer: any, x?: number, y?: number): void;
22 | exportAtoms(): unknown[];
23 | clear(t?: string): void;
24 | }
25 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Water.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Water extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static BUBBLY_WATER: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static WATER_GRID: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static WATER_LINE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static DO_BUBBLE: (ew: EventWindow) => boolean;
10 | constructor(type: IElementType, state?: any);
11 | init(): void;
12 | behave(ew: EventWindow): void;
13 | }
14 |
--------------------------------------------------------------------------------
/mfm-js/src/mfm/ElementRegistry.ts:
--------------------------------------------------------------------------------
1 | import { IElementType } from "./Element";
2 |
3 | export class ElementRegistry {
4 | static TYPES: Map = new Map();
5 | static GROUPS: Map = new Map();
6 |
7 | static registerType(type: IElementType) {
8 | this.TYPES.set(type.name.toUpperCase(), type);
9 |
10 | const groups = type.groups ?? ["Misc"];
11 |
12 | groups.forEach((g) => {
13 | if (!this.GROUPS.has(g)) {
14 | this.GROUPS.set(g, []);
15 | }
16 |
17 | const group = this.GROUPS.get(g);
18 | this.GROUPS.set(g, [...group, type]);
19 | });
20 | }
21 |
22 | static getType(type: string | IElementType): IElementType {
23 | return typeof type === "string" ? this.TYPES.get(type.toUpperCase()) : this.TYPES.get(type.name.toUpperCase());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/capabilities/Repel.d.ts:
--------------------------------------------------------------------------------
1 | import { Element } from '../mfm/Element';
2 | import { EventWindow, EWIndex } from '../mfm/EventWindow';
3 |
4 | export declare class Repel {
5 | static NAME: string;
6 | static CREATE(repelType: string, repelSites: EWIndex[], escapeType: string, escapeSites: EWIndex[]): (ew: EventWindow) => boolean;
7 | static FAR_NORTH(ew: EventWindow, repelType: string | string[], escapeType?: string | string[]): boolean;
8 | static MAKE_REPELLER(_repelTypes: string | string[], fromIndexes?: EWIndex[], toIndexes?: EWIndex[]): (ew: EventWindow, self: Element) => boolean;
9 | static MAKE_AVOIDER(_repelTypes: string | string[], fromIndexes?: EWIndex[], toIndexes?: EWIndex[]): (ew: EventWindow, self: Element) => boolean;
10 | static MAKE_ATTRACTOR(_attractTypes: string | string[], view?: EWIndex[]): (ew: EventWindow, self: Element) => boolean;
11 | }
12 |
--------------------------------------------------------------------------------
/mfm-js/src/mfm/TileCoordinate.ts:
--------------------------------------------------------------------------------
1 | export interface ICoordinate {
2 | x: number;
3 | y: number;
4 | }
5 |
6 | export interface ITileCoordinate {
7 | id: string;
8 | coordinate: ICoordinate;
9 | }
10 |
11 | export class TileCoordinate {
12 | static CoordinateToId(c: ICoordinate): string {
13 | return `${c.y}:${c.x}`;
14 | }
15 |
16 | static IdToCoordinate(id: string): ICoordinate {
17 | const [y, x] = id.split(":");
18 | return { y: +y, x: +x };
19 | }
20 |
21 | static fromCoordinate(c: ICoordinate): TileCoordinate {
22 | return new TileCoordinate(TileCoordinate.CoordinateToId(c));
23 | }
24 |
25 | static fromId(id: string): TileCoordinate {
26 | return new TileCoordinate(id);
27 | }
28 |
29 | id: string;
30 | coordinate: ICoordinate;
31 |
32 | constructor(id: string) {
33 | this.id = id;
34 | this.coordinate = TileCoordinate.IdToCoordinate(this.id);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/Looper.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Looper extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static WONKY: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static LOOP_WALL: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static LOOP_DIRECTOR: (heading: any) => any;
9 | static REPEL_DIRECTIONAL: (ew: EventWindow, self: Element) => boolean;
10 | constructor(type: IElementType, state?: any);
11 | init(): void;
12 | makeBigTail(ew: EventWindow): void;
13 | behave(ew: EventWindow): void;
14 | behaveAsLooper(ew: EventWindow): void;
15 | behaveAsWonky(ew: EventWindow): void;
16 | }
17 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/elements/LemmingEmitter.ts:
--------------------------------------------------------------------------------
1 | import { Element } from "mfm-js";
2 | import { EventWindow } from "mfm-js";
3 | import { Lemming } from "./Lemming";
4 |
5 | export class LemmingEmitter extends Element {
6 | static CREATE = LemmingEmitter.CREATOR({ name: "LEMIT", symbol: "LME", class: LemmingEmitter, color: 0x89f24e, groups: ["LEMMINGS"] }, { emitCount: 10});
7 |
8 | constructor(type, state = {}) {
9 | super(type, state);
10 |
11 | this.init();
12 | }
13 |
14 | init() {
15 |
16 | if(!this.state.emitCount) {
17 | this.state.emitCount = 100;
18 | }
19 | }
20 |
21 | behave(ew: EventWindow) {
22 | super.behave(ew);
23 |
24 | if(this.state.emitCount <= 0) {
25 | ew.destroy();
26 | return;
27 | }
28 |
29 | if(this.state.emitCount > 0 && ew.is(3, "EMPTY")) {
30 | ew.mutate(3, Lemming.CREATE);
31 | this.state.emitCount--;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/mfmrocks/public/v1/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | module.exports = {
3 | mode: "development",
4 | entry: "./src/index.ts",
5 | devtool: "inline-source-map",
6 | module: {
7 | rules: [
8 | {
9 | test: /\.m?js$/,
10 | exclude: /(node_modules|bower_components)/,
11 | use: {
12 | loader: "babel-loader",
13 | options: {
14 | presets: ["@babel/preset-env"]
15 | }
16 | }
17 | },
18 | {
19 | test: /\.tsx?$/,
20 | use: "ts-loader",
21 | exclude: /node_modules/
22 | }
23 | ]
24 | },
25 | resolve: {
26 | extensions: [".tsx", ".ts", ".js"]
27 | },
28 | output: {
29 | filename: "mfm.js",
30 | path: path.resolve(__dirname, "dist")
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/mfm-js/src/capabilities/Swap.ts:
--------------------------------------------------------------------------------
1 | import { IElementType } from "../mfm/Element";
2 | import { EventWindow, EWIndex } from "../mfm/EventWindow";
3 |
4 | export class Swap {
5 | static DOWN = Swap.CREATE(EventWindow.S);
6 | static SIDE = Swap.CREATE([6, 8]);
7 | static SLIP = Swap.CREATE(EventWindow.EQUATOR);
8 |
9 | static SINK = Swap.CREATE([...EventWindow.S, 6, 8], "WATER");
10 | static FLOAT = Swap.CREATE([...EventWindow.N, 5, 7], "WATER");
11 |
12 | static PATROL = Swap.CREATE(EventWindow.ADJACENT4WAY);
13 | static PATROL_8 = Swap.CREATE(EventWindow.ADJACENT8WAY);
14 |
15 | static CREATE(direction: EWIndex[], type: string | IElementType = "EMPTY") {
16 | return (ew: EventWindow, chance: number = 1): boolean => {
17 | if (EventWindow.oneIn(chance) && ew.any(direction, type)) {
18 | const to: EWIndex = ew.filter(direction, type, true)?.[0];
19 | return ew.swap(to);
20 | }
21 |
22 | return false;
23 | };
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/mfm-js/src/mfm/Site.ts:
--------------------------------------------------------------------------------
1 | import { Empty } from "../elements/core/Empty";
2 | import { Element } from "./Element";
3 | import { EventWindow } from "./EventWindow";
4 | import { TileCoordinate } from "./TileCoordinate";
5 |
6 | export class Site {
7 | location: TileCoordinate;
8 | id: string;
9 |
10 | atom: Element;
11 | baseAtom: Element;
12 | //the tile needs to seed the EventWindow
13 | ew: EventWindow;
14 |
15 | constructor(_loc: TileCoordinate) {
16 | this.location = _loc;
17 | this.id = this.location.id;
18 | this.create();
19 | }
20 |
21 | create() {
22 | this.atom = Empty.CREATE();
23 | this.baseAtom = Empty.CREATE();
24 | }
25 |
26 | swapAtoms(targetSite: Site): boolean {
27 | [this.atom, targetSite.atom] = [targetSite.atom, this.atom];
28 | return true;
29 | }
30 |
31 | mutate(atom: Element) {
32 | this.atom = atom;
33 | }
34 |
35 | mutateBase(atom: Element) {
36 | this.baseAtom = atom;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Goop.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Goop extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static WALL_GOOP: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static LIFE_GOOP: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static HC3_GOOP: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static GOOP_GRID: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
10 | static ATTRACT: (ew: EventWindow, self: Element) => boolean;
11 | static AVOID: (ew: EventWindow, self: Element) => boolean;
12 | constructor(type: IElementType, state?: any);
13 | init(): void;
14 | behave(ew: EventWindow): void;
15 | }
16 |
--------------------------------------------------------------------------------
/mfm-js/src/capabilities/Build.ts:
--------------------------------------------------------------------------------
1 | import { EventWindow, EWIndex } from "../mfm/EventWindow";
2 |
3 | export class Build {
4 | static GRID = Build.MAKE_REPEATER(EventWindow.DIAGONAL4WAY);
5 | static SMALL_GRID = Build.MAKE_REPEATER(EventWindow.DIAGONAL4WAY, 4);
6 | static H_LINE = Build.MAKE_REPEATER([1, 4]);
7 | static V_LINE = Build.MAKE_REPEATER([2, 3]);
8 |
9 | static MAKE_REPEATER(destinations: EWIndex[], steps?: number) {
10 | return (ew: EventWindow, multiplier: Function, creator: Function): boolean => {
11 | const empties = ew.filterByType(destinations, "EMPTY");
12 | //PROPAGATE
13 | if (steps) {
14 | let step = ew.origin.atom.rd("buildStep") ?? 1;
15 | ew.origin.atom.wr("buildStep", step);
16 |
17 | if (step < steps) {
18 | ew.mutateMany(empties, multiplier, [{}, { buildStep: step + 1 }]);
19 | }
20 | } else {
21 | ew.mutateMany(empties, multiplier);
22 | }
23 |
24 | ew.mutate(0, creator);
25 |
26 | return true;
27 | };
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/AntiForkBomb.ts:
--------------------------------------------------------------------------------
1 | import { Decay } from "../../capabilities/Decay";
2 | import { Element, IElementType } from "../../mfm/Element";
3 | import { EventWindow } from "../../mfm/EventWindow";
4 |
5 | export class AntiForkBomb extends Element {
6 | static CREATE = AntiForkBomb.CREATOR({ name: "ANTIFORKBOMB", symbol: "AFK", class: AntiForkBomb, color: 0x00aadd, groups: ["MFM"] });
7 |
8 | constructor(type: IElementType, state: any = {}) {
9 | super(type, state);
10 | }
11 |
12 | behave(ew: EventWindow) {
13 | super.behave(ew);
14 |
15 | const forkbombs = ew.filterByType(EventWindow.ADJACENT8WAY, "FORKBOMB");
16 |
17 | if (forkbombs.length) {
18 | ew.mutateMany(forkbombs, AntiForkBomb.CREATE, [{ color: (this.rd("color") + 2048) % 0xffffff }, {}]);
19 | }
20 |
21 | Decay.DECAY(ew, this, 40);
22 |
23 | const afks = ew.filterByType(EventWindow.ADJACENT8WAY, "ANTIFORKBOMB");
24 |
25 | if (afks.length && EventWindow.oneIn(2)) {
26 | ew.mutateMany(afks, AntiForkBomb.CREATE, [{ color: (this.rd("color") + 1024) % 0xaaffff }, { age: this.state.age - 1 }]);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Wall.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Wall extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static MOVABLE_WALL: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static DECAY_WALL: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static DECAY_WALL_10: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static DECAY_WALL_25: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
10 | static DECAY_WALL_50: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
11 | static MOVABLE_WALL_GRID: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
12 | constructor(type: IElementType, state?: any);
13 | init(): void;
14 | behave(ew: EventWindow): void;
15 | }
16 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/agents/Sentry.ts:
--------------------------------------------------------------------------------
1 | import { Wayfinding } from "../../capabilities/Wayfinding";
2 | import { Element, IElementType } from "../../mfm/Element";
3 | import { EventWindow } from "../../mfm/EventWindow";
4 | import { Wayfinder } from "../../mfm/Wayfinder";
5 | import { AntiForkBomb } from "../core/AntiForkBomb";
6 |
7 | export class Sentry extends Element {
8 | //VARIANTS
9 | static CREATE = Sentry.CREATOR({ name: "SENTRY", class: Sentry, color: 0xa414ff, classifications: ["DIRECTIONAL", "DIRECTABLE"], groups: ["MFM"] });
10 |
11 | constructor(type: IElementType, state: any = {}) {
12 | super(type, state);
13 | this.init();
14 | }
15 |
16 | init() {}
17 |
18 | behave(ew: EventWindow) {
19 | super.behave(ew);
20 |
21 | if (!this.state.heading) {
22 | Wayfinding.SET_DIRECTION(this, Wayfinder.RANDOM());
23 | } else {
24 | Wayfinding.MOVE_DIRECTIONALLY(ew, this);
25 | Wayfinding.SLIGHT_RANDOMLY(this);
26 | }
27 |
28 | const forkbombs = ew.filter(EventWindow.ALLADJACENT, "FORKBOMB", true);
29 |
30 | if (forkbombs.length) {
31 | ew.mutate(forkbombs[0], AntiForkBomb.CREATE);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/Sand.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Sand extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static RED_SAND: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static PINK_SAND: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static FLOATY_SAND: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static GREEN_SAND: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
10 | static BLUE_SAND: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
11 | static PURPLE_SAND: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
12 | static SAND_GRID: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
13 | static BUBBLE: (ew: EventWindow) => boolean;
14 | constructor(type: IElementType, state?: any);
15 | init(): void;
16 | behave(ew: EventWindow): void;
17 | }
18 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/Signal.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Signal extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static N: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static NE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static E: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static SE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
10 | static S: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
11 | static SW: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
12 | static W: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
13 | static NW: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
14 | constructor(type: IElementType, state?: any);
15 | init(): void;
16 | behave(ew: EventWindow): void;
17 | }
18 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/index.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import '../../styles/main.scss';
3 |
4 | import LemmingsGame from './_game/LemmingsGame.vue';
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | MFM Lemmings
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/SwapWorm.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow, EWIndex } from '../../mfm/EventWindow';
3 |
4 | export declare class SwapWorm extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static SMOLSW: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static BIGSW: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | constructor(type: IElementType, state?: any);
9 | init(): void;
10 | behave(ew: EventWindow): boolean;
11 | establishType(ew: EventWindow): string;
12 | isHead(): boolean;
13 | isTail(): boolean;
14 | isMiddle(): boolean;
15 | isTemp(): boolean;
16 | confirmBehind(ew: EventWindow): boolean;
17 | confirmAhead(ew: EventWindow): boolean;
18 | isBehindTemp(ew: EventWindow): boolean;
19 | isAheadTemp(ew: EventWindow): boolean;
20 | makeGrowSegment(a: EWIndex): Element;
21 | makeGrowTemp(a: EWIndex): Element;
22 | getSegment(ew: EventWindow, segIndex: EWIndex): Element;
23 | swapSegments(ew: EventWindow, segIndex: EWIndex): boolean;
24 | grow(ew: EventWindow): boolean;
25 | move(ew: EventWindow): boolean;
26 | }
27 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/core/SwapLine.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class SwapLine extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static NORTH: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static SOUTH: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static EAST: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static WEST: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
10 | static NW: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
11 | static NE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
12 | static SW: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
13 | static SE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
14 | constructor(type: IElementType, state?: any);
15 | init(): void;
16 | behave(ew: EventWindow): void;
17 | }
18 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/DReg.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow, EWIndex } from "../../mfm/EventWindow";
3 | import { Res } from "./Res";
4 |
5 | export class DReg extends Element {
6 | static CREATE = DReg.CREATOR(
7 | { name: "DREG", class: DReg, color: 0xff2020, groups: ["MFM"] },
8 | {
9 | pDREG_CREATE: 1000,
10 | pRES_CREATE: 200,
11 | pDREG_DESTROY: 10,
12 | pANY_DESTROY: 100,
13 | }
14 | );
15 |
16 | constructor(type: IElementType, state: any = {}) {
17 | super(type, state);
18 | }
19 |
20 | behave(ew: EventWindow) {
21 | super.behave(ew);
22 |
23 | const neighbor: EWIndex = ew.filter(EventWindow.ADJACENT4WAY, null, true)[0];
24 |
25 | if (ew.is(neighbor, "EMPTY")) {
26 | const createDReg: boolean = EventWindow.oneIn(this.state.pDREG_CREATE);
27 | const createRes: boolean = EventWindow.oneIn(this.state.pRES_CREATE);
28 |
29 | if (createDReg) {
30 | ew.move(neighbor, DReg.CREATE());
31 | } else if (createRes) {
32 | ew.move(neighbor, Res.CREATE());
33 | } else {
34 | ew.swap(neighbor);
35 | }
36 | } else if ((ew.is(neighbor, "DREG") && EventWindow.oneIn(this.state.pDREG_DESTROY)) || EventWindow.oneIn(this.state.pANY_DESTROY)) {
37 | ew.move(neighbor);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/elements/Dirt.ts:
--------------------------------------------------------------------------------
1 | import { Element, EventWindow, Sand } from "mfm-js";
2 |
3 | export class Dirt extends Element {
4 | static CREATE = Dirt.CREATOR({ name: "DIRT", class: Dirt, color: 0xcf932b, classifications: ["DIGGABLE"], groups: ["LEMMINGS"] });
5 | static ROCK = Dirt.CREATOR({ name: "ROCK", class: Dirt, color: 0xa14e06, classifications: ["SOLID"], groups: ["LEMMINGS"] });
6 | static MOSS = Dirt.CREATOR({ name: "MOSS", class: Dirt, color: 0x0ac765, classifications: ["SOLID"], groups: ["LEMMINGS"] });
7 |
8 | static TODE_RED = Dirt.CREATOR({ name: "TODE_RED", class: Dirt, color: 0xfe4646, classifications: ["SOLID"], groups: ["LEMMINGS"] });
9 | static TODE_GREEN = Dirt.CREATOR({ name: "TODE_GREEN", class: Dirt, color: 0x00fe81, classifications: ["SOLID"], groups: ["LEMMINGS"] });
10 | static TODE_BLACK = Dirt.CREATOR({ name: "TODE_BLACK", class: Dirt, color: 0x161c28, classifications: ["SOLID"], groups: ["LEMMINGS"] });
11 |
12 | static SAND = Sand.CREATOR({ name: "SAND", symbol: "SND", class: Sand, color: 0xffdd00, classifications: ["SAND", "MOVABLE"], groups: ["LEMMINGS"] });
13 |
14 |
15 |
16 | constructor(type: IElementType, state: any = {}) {
17 | super(type, state);
18 |
19 | this.init();
20 | }
21 |
22 | init() {}
23 |
24 | behave(ew: EventWindow) {
25 | super.behave(ew);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/capabilities/Wayfinding.d.ts:
--------------------------------------------------------------------------------
1 | import { Element } from '../mfm/Element';
2 | import { EventWindow, EWIndex } from '../mfm/EventWindow';
3 | import { Direction } from '../mfm/Wayfinder';
4 |
5 | export declare class Wayfinding {
6 | static NAME: string;
7 | static REVERSE(self: Element): void;
8 | static SLIGHT_LEFT(self: Element): void;
9 | static VEER_LEFT(self: Element): void;
10 | static TURN_LEFT(self: Element): void;
11 | static SLIGHT_RIGHT(self: Element): void;
12 | static VEER_RIGHT(self: Element): void;
13 | static TURN_RIGHT(self: Element): void;
14 | static SLIGHT_RANDOMLY(self: Element): void;
15 | static VEER_RANDOMLY(self: Element): void;
16 | static TURN_RANDOMLY(self: Element): void;
17 | static SET_DIRECTION(self: Element, d: Direction): void;
18 | static MOVE_IN_DIRECTION(ew: EventWindow, self: Element, direction: Direction | Direction[], types?: string | string[], leavingAtom?: Element): boolean;
19 | static MOVE_DIRECTIONALLY(ew: EventWindow, self: Element, types?: string | string[], leavingAtom?: Element): boolean;
20 | static SWAP_IN_DIRECTION(ew: EventWindow, self: Element, direction: Direction | Direction[], types?: string | string[]): boolean;
21 | static SWAP_DIRECTIONALLY(ew: EventWindow, self: Element, types?: string | string[]): boolean;
22 | static DIRECT(ew: EventWindow, s: EWIndex, heading: Direction): boolean;
23 | }
24 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/Element.d.ts:
--------------------------------------------------------------------------------
1 | import { EventWindow } from './EventWindow';
2 |
3 | export interface IElementType {
4 | name: string;
5 | class: any;
6 | symbol?: string;
7 | color?: number;
8 | CREATE?: Function;
9 | classifications?: string[];
10 | groups?: string[];
11 | }
12 | export interface IElementTypePartial {
13 | symbol?: string;
14 | name?: string;
15 | class?: any;
16 | color?: number;
17 | CREATE?: Function;
18 | classifications?: string[];
19 | groups?: string[];
20 | }
21 | export interface IElement {
22 | TYPE: IElementType;
23 | behave: Function;
24 | state?: any;
25 | }
26 | export declare abstract class Element implements IElement {
27 | static CREATOR(typeDefinition: IElementType, state?: any): (_typeDefinition?: IElementTypePartial, _state?: any) => Element;
28 | static UID: (length?: number) => string;
29 | TYPE: IElementType;
30 | state: any;
31 | classes: Set;
32 | constructor(_type: IElementType, initialState?: any);
33 | initializeState(state?: any): void;
34 | behave(ew: EventWindow): void;
35 | rd(key: string): any;
36 | wr(key: string, value: any): any;
37 | classifyAs(c: string | IElementType): void;
38 | declassify(c: string | IElementType): void;
39 | is(type: string | IElementType | string[] | IElementType[]): boolean;
40 | isCore(type: string | IElementType): boolean;
41 | }
42 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/Builder.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow } from "../../mfm/EventWindow";
3 | import { Sand } from "./Sand";
4 |
5 | export class Builder extends Element {
6 | // static CREATE = Builder.CREATOR({ name: "BUILDER", symbol: "BLD", class: Builder, color: 0x121112 });
7 |
8 | constructor(type: IElementType, state: any = {}) {
9 | super(type, state);
10 |
11 | this.init();
12 | }
13 |
14 | init() {
15 | this.classifyAs("BUILDER");
16 |
17 | if( !this.state.transitionAge) {
18 | this.state.transitionAge = 10;
19 | }
20 | }
21 |
22 | behave(ew: EventWindow) {
23 | super.behave(ew);
24 |
25 | const { buildPath, atomizer, totalSteps, transitionAge, age } = this.state;
26 |
27 |
28 |
29 | const currentStep = this.state.currentStep ?? 0;
30 | const didSpread = this.state.didSpread ?? false;
31 |
32 | const empties = ew.filterByType(buildPath, "EMPTY");
33 |
34 | if (!didSpread && empties.length) {
35 | if (totalSteps) {
36 | if (currentStep < totalSteps) {
37 | ew.mutateMany(empties, this.TYPE.CREATE, [{}, { currentStep: currentStep + 1 }]);
38 | this.state.totalSteps--;
39 | }
40 | } else {
41 | ew.mutateMany(empties, this.TYPE.CREATE);
42 | }
43 | }
44 |
45 | this.state.didSpread = true;
46 | if (age > transitionAge) ew.mutate(0, atomizer);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/agents/ofswamp/Swampling.ts:
--------------------------------------------------------------------------------
1 | import { Wayfinding } from "../../../capabilities/Wayfinding";
2 | import { Element, IElementType } from "../../../mfm/Element";
3 | import { EventWindow } from "../../../mfm/EventWindow";
4 | import { Wayfinder } from "../../../mfm/Wayfinder";
5 | import { Swamp } from "./Swamp";
6 |
7 | export class Swampling extends Element {
8 | //VARIANTS
9 | static CREATE = Swampling.CREATOR({
10 | name: "SWAMPLING",
11 | class: Swampling,
12 | color: 0x22cc88,
13 | // color: 0x3d5b31,
14 | classifications: ["OFSWAMP", "DIRECTIONAL", "DIRECTABLE"],
15 | groups: ["Swamp"],
16 | });
17 |
18 | //SYSTEM ELEMENTS
19 |
20 | constructor(type: IElementType, state: any = {}) {
21 | super(type, state);
22 | }
23 |
24 | behave(ew: EventWindow) {
25 | super.behave(ew);
26 |
27 | if (!this.state.heading) {
28 | Wayfinding.SET_DIRECTION(this, Wayfinder.RANDOM());
29 | const empties = ew.filterByType(EventWindow.ADJACENT8WAY, "EMPTY");
30 | if (empties.length) {
31 | ew.mutateMany(empties, Swamp.CREATE);
32 | }
33 | } else {
34 | const empties = ew.filterByType(EventWindow.ADJACENT8WAY, "EMPTY");
35 | if (empties.length > 1) {
36 | Wayfinding.SLIGHT_RIGHT(this);
37 | // Wayfinding.REVERSE(this);
38 | }
39 | Wayfinding.SWAP_DIRECTIONALLY(ew, this, "SWAMP");
40 | if (EventWindow.oneIn(1.5)) {
41 | Wayfinding.SLIGHT_RIGHT(this);
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/HardCell3.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow, EWIndex } from '../../mfm/EventWindow';
3 | import { Direction } from '../../mfm/Wayfinder';
4 |
5 | export declare class HardCell3 extends Element {
6 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static HC3x8: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static HC3x4: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static CELL_SITES: EWIndex[];
10 | static CELL_WANDER_MAP: Map;
11 | static CELL_DIRECTION_MAP: Map;
12 | static COLORS: number[];
13 | constructor(type: IElementType, state?: any);
14 | init(): void;
15 | behave(ew: EventWindow): void;
16 | hasStasis(ew: EventWindow): Boolean;
17 | hasBadStructure(ew: EventWindow): Boolean;
18 | figureHops(ew: EventWindow): void;
19 | setColor(): void;
20 | canMove(ew: EventWindow): Boolean;
21 | shouldRegrow(ew: EventWindow): Boolean;
22 | shouldMove(ew: EventWindow): Direction | false;
23 | localType(): string;
24 | isRoot(): Boolean;
25 | isEnd(): Boolean;
26 | upstreams(ew: EventWindow): EWIndex[];
27 | downstreams(ew: EventWindow): EWIndex[];
28 | neighbors(ew: EventWindow): EWIndex[];
29 | getDirectionFromWanderMap(ew: EventWindow, site: EWIndex): Direction;
30 | }
31 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/agents/LivingWall.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow } from "../../mfm/EventWindow";
3 |
4 | export class LivingWall extends Element {
5 | static CREATE = LivingWall.CREATOR({ name: "LIVING WALL", class: LivingWall, color: 0x2255aa, groups: ["Structural", "MFM"] });
6 | static MOVABLE_LIVING_WALL = LivingWall.CREATOR({
7 | name: "MOVABLE LIVING WALL",
8 | class: LivingWall,
9 | color: 0x2255aa,
10 | classifications: ["MOVABLE", "LIVING WALL"],
11 | groups: ["Structural", "MFM"],
12 | });
13 |
14 | constructor(type: IElementType, state: any = {}) {
15 | super(type, state);
16 |
17 | this.init();
18 | }
19 |
20 | init() {}
21 |
22 | behave(ew: EventWindow) {
23 | super.behave(ew);
24 |
25 | this.regen(ew);
26 | this.populateRegenMap(ew);
27 | }
28 |
29 | populateRegenMap(ew: EventWindow) {
30 | const otherLivingWalls = ew.filterByType(EventWindow.ALLADJACENT, "LIVING WALL");
31 | if (otherLivingWalls.length > (this.state.regenMap?.length ?? 0)) {
32 | this.state.regenMap = otherLivingWalls.map((i) => {
33 | return [i, ew.getSite(i).atom.TYPE.CREATE];
34 | });
35 |
36 | this.state.color = this.TYPE.color - this.state.regenMap.length * 6;
37 | }
38 | }
39 |
40 | regen(ew: EventWindow) {
41 | if (this.state.regenMap?.length) {
42 | this.state.regenMap.forEach((w) => {
43 | if (ew.is(w[0], "EMPTY")) {
44 | ew.mutate(w[0], w[1]);
45 | }
46 | });
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/Water.ts:
--------------------------------------------------------------------------------
1 | import { Build } from "../../capabilities/Build";
2 | import { Swap } from "../../capabilities/Swap";
3 | import { Repel } from "../../capabilities/Repel";
4 | import { Element, IElementType } from "../../mfm/Element";
5 | import { EventWindow } from "../../mfm/EventWindow";
6 | import { Builder } from "./Builder";
7 |
8 | export class Water extends Element {
9 | static CREATE = Water.CREATOR({ name: "WATER", symbol: "SND", class: Water, color: 0x0011ee, groups: ["Environment"] });
10 | static BUBBLY_WATER = Water.CREATOR({ name: "BUBBLY WATER", class: Water, color: 0x0011ee, classifications: ["WATER", "BUBBLY"], groups: ["Environment"] });
11 |
12 | static WATER_GRID = Builder.CREATOR(
13 | { name: "WATER GRID", class: Builder, color: 0x121112, groups: ["Environment"] },
14 | { buildPath: EventWindow.DIAGONAL4WAY, atomizer: Water.CREATE, totalSteps: 40 }
15 | );
16 |
17 | static WATER_LINE = Builder.CREATOR(
18 | { name: "WATER LINE", class: Builder, color: 0x121112, groups: ["Environment"] },
19 | { buildPath: [1, 4], atomizer: Water.CREATE }
20 | );
21 |
22 | static DO_BUBBLE = Repel.CREATE("WATER", EventWindow.S_QUADRANT, "EMPTY", EventWindow.N_QUADRANT);
23 |
24 | constructor(type: IElementType, state: any = {}) {
25 | super(type, state);
26 |
27 | this.init();
28 | }
29 |
30 | init() {
31 | this.classifyAs("WATER");
32 | }
33 |
34 | behave(ew: EventWindow) {
35 | super.behave(ew);
36 |
37 | Swap.DOWN(ew) || Swap.SLIP(ew);
38 | if (ew.selfIs("BUBBLY")) Water.DO_BUBBLE(ew);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/agents/ofswamp/SwampWorker.ts:
--------------------------------------------------------------------------------
1 | import { Wayfinding } from "../../../capabilities/Wayfinding";
2 | import { Element, IElementType } from "../../../mfm/Element";
3 | import { EventWindow } from "../../../mfm/EventWindow";
4 | import { Wayfinder } from "../../../mfm/Wayfinder";
5 | import { Swamp } from "./Swamp";
6 |
7 | export class SwampWorker extends Element {
8 | static CREATE = SwampWorker.CREATOR({
9 | name: "SWAMP WORKER",
10 | symbol: "SWK",
11 | class: SwampWorker,
12 | color: 0x03460f,
13 | // color: 0x3d5b31,
14 | // color: 0x3d6242,
15 | classifications: ["OFSWAMP", "DIRECTIONAL", "SWAMPLING"],
16 | groups: ["Swamp"],
17 | });
18 |
19 | constructor(type: IElementType, state: any = {}) {
20 | super(type, state);
21 | }
22 |
23 | behave(ew: EventWindow) {
24 | super.behave(ew);
25 |
26 | const swampworkers = ew.filterByType(EventWindow.ADJACENT8WAY, "SWAMP WORKER");
27 | const ofswamps = ew.filterByType(EventWindow.ALLADJACENT, "OFSWAMP");
28 |
29 | if (ofswamps.length < EventWindow.ALLADJACENT.length * 0.4) {
30 | ew.mutate(0, Swamp.CREATE);
31 | return;
32 | }
33 |
34 | if (swampworkers.length) {
35 | ew.mutate(0, Swamp.CREATE);
36 | return;
37 | }
38 |
39 | if (!this.state.heading) {
40 | Wayfinding.SET_DIRECTION(this, Wayfinder.RANDOM(Wayfinder.DIRECTIONS_PRIMARY));
41 | } else {
42 | if (Wayfinding.SWAP_DIRECTIONALLY(ew, this, "SWAMP")) {
43 | Wayfinding.VEER_RIGHT(this);
44 | } else {
45 | Wayfinding.SLIGHT_RIGHT(this);
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/mfm-js/src/elements/agents/DirectorWall.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from "../../mfm/Element";
2 | import { EventWindow } from "../../mfm/EventWindow";
3 | import { Wayfinder } from "../../mfm/Wayfinder";
4 | import { Director } from "./Director";
5 | import { Wall } from "../core/Wall";
6 |
7 |
8 | export class DirectorWall extends Element {
9 | static CREATE = DirectorWall.CREATOR({ name: "DIRECTOR WALL", symbol: "DRWL", class: DirectorWall, color: 0xbe146f, groups: ["Structural"] });
10 |
11 | constructor(type: IElementType, state: any = {}) {
12 | super(type, state);
13 |
14 | this.init();
15 | }
16 |
17 | init() {}
18 |
19 | behave(ew: EventWindow) {
20 | super.behave(ew);
21 |
22 | const emptyWallNeighbors = ew.filterByType([...EventWindow.LAYER1, ...EventWindow.LAYER2, ...EventWindow.LAYER3], ["EMPTY", "DIRECTOR"]);
23 |
24 | if (emptyWallNeighbors.length > 0) {
25 | ew.mutateMany( emptyWallNeighbors, Wall.CREATE );
26 | }
27 |
28 | const emptyDirectorNeighbors = ew.filterByType(EventWindow.LAYER4, "EMPTY");
29 |
30 | if( emptyDirectorNeighbors.length > 0 ) {
31 | emptyDirectorNeighbors.forEach( (i) => {
32 | let pointingDirection = Wayfinder.indexToDirection(i);
33 | const directorDirection = Wayfinder.turnLeft(pointingDirection);
34 | ew.mutate( i, Director.DIRECTORS_MAP.get(directorDirection) );
35 | });
36 | }
37 |
38 | if( EventWindow.oneIn(1000) ) {
39 | const directorNeighbors = ew.filterByType(EventWindow.LAYER4, "DIRECTOR");
40 | ew.destroy(ew.random(directorNeighbors));
41 | }
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/elements/agents/Wanderer.d.ts:
--------------------------------------------------------------------------------
1 | import { Element, IElementType } from '../../mfm/Element';
2 | import { EventWindow } from '../../mfm/EventWindow';
3 |
4 | export declare class Wanderer extends Element {
5 | static CREATE: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
6 | static FLY: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
7 | static MOSQUITO: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
8 | static BIRD: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
9 | static FLOCKER: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
10 | static SWAMPDATA: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
11 | static BIRD_WING: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
12 | static FLY_TAIL: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
13 | static MOSQUITO_TAIL: (_typeDefinition?: import('../../mfm/Element').IElementTypePartial, _state?: any) => Element;
14 | constructor(type: IElementType, state?: any);
15 | init(): void;
16 | behave(ew: EventWindow): void;
17 | behaveAsFly(ew: EventWindow): void;
18 | behaveAsMosquito(ew: EventWindow): void;
19 | behaveAsBird(ew: EventWindow): void;
20 | behaveAsFlocker(ew: EventWindow): void;
21 | behaveAsSwampData(ew: EventWindow): void;
22 | blazeTrail(ew: EventWindow): void;
23 | }
24 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/elements/Power.ts:
--------------------------------------------------------------------------------
1 | import { Element, EventWindow, Empty } from "mfm-js";
2 |
3 | export class Power extends Element {
4 | static CREATE = Power.CREATOR({ name: "POWER", symbol: "POW", class: Power, color: 0x2390aa, groups: ["LEMMINGS"] });
5 | static DIGGER = Power.CREATOR({ name: "DIGGER", symbol: "DIG", class: Power, color: 0xffffff, groups: ["LEMMINGS"] }, { power: "DIGGER", charges: 1});
6 | static BLOCKER = Power.CREATOR({ name: "BLOCKER", symbol: "BLK", class: Power, color: 0x2390aa, groups: ["LEMMINGS"] }, { power: "BLOCKER", charges: 1});
7 | static MINER = Power.CREATOR({ name: "MINER", symbol: "MNR", class: Power, color: 0x2390aa, groups: ["LEMMINGS"] }, { power: "MINER", charges: 1});
8 | static BUILDER = Power.CREATOR({ name: "BUILDER", symbol: "MNR", class: Power, color: 0x2390aa, groups: ["LEMMINGS"] }, { power: "BUILDER", charges: 1});
9 |
10 |
11 | constructor(type, state = {}) {
12 | super(type, state);
13 |
14 | this.init();
15 | }
16 |
17 | init() {
18 | this.state.power = this.state.power ?? "WALKER";
19 | this.state.charges = this.state.charges ?? 1;
20 | }
21 |
22 | behave(ew: EventWindow) {
23 | super.behave(ew);
24 |
25 | if( !ew.exists( 3 ) ) {
26 | ew.destroy();
27 | }
28 |
29 |
30 | if(this.state.charges <= 0) {
31 | ew.destroy();
32 | return;
33 | }
34 |
35 | const nearbyLemming = ew.randomOfType( EventWindow.ADJACENT8WAY, "WALKER" );
36 |
37 | if( nearbyLemming ) {
38 | (ew.getSite(nearbyLemming).atom as Lemming)?.setRole(this.state.power);
39 | this.state.charges--;
40 | }
41 | }
42 |
43 |
44 |
45 |
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/mfm-js/src/capabilities/Perception.ts:
--------------------------------------------------------------------------------
1 | import { IElementType } from "../mfm/Element";
2 | import { EventWindow, EWIndex } from "../mfm/EventWindow";
3 | import { Signal } from "../elements/agents/Signal";
4 | import { Wayfinder } from "../main";
5 | import { Direction } from "../mfm/Wayfinder";
6 |
7 | export type SignalType = "WARN" | "INFORM" | "BECKON";
8 | export type Message = {
9 | senderId: string;
10 | senderType: IElementType | string;
11 | signalType: SignalType;
12 | message: string;
13 | signalDirection?: Direction;
14 | };
15 |
16 | export class Perception {
17 |
18 | static SENSE(ew: EventWindow, type: IElementType | string, withinSet: EWIndex[] = EventWindow.ALLADJACENT, minQuantity: number = 1, maxQuantity: number = 1): boolean {
19 | const count = ew.howMany(withinSet, type);
20 | if (count < minQuantity || count > maxQuantity) {
21 | return false;
22 | }
23 | return true;
24 | }
25 |
26 | static SIGNAL(ew: EventWindow, signalType: SignalType, message: Message): void {
27 | const d = EventWindow.RANDOM(EventWindow.LAYER3);
28 | if( ew.is(d, "EMPTY") ) {
29 | ew.mutate(d, Signal.CREATE, [{}, { heading: Wayfinder.indexToDirection(d), signalType, message }]);
30 | }
31 | }
32 |
33 | static RECEIVE_SIGNAL(ew:EventWindow, self: Element, indexes: EWIndex[] = EventWindow.ALLADJACENT): Message | null {
34 | const signalIndex = ew.filter(indexes, "SIGNAL", true)?.[0];
35 | if (!signalIndex) return null;
36 |
37 | const signal = ew.getSite(signalIndex)?.atom;
38 | const message = signal.state.message;
39 | if( message.senderId === self.state.uid ) return null;
40 | const signalDirection = Wayfinder.reverse( signal.state.heading );
41 |
42 | ew.destroy(signalIndex);
43 | return { ...message, signalDirection };
44 | }
45 | }
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites/lemmings.json:
--------------------------------------------------------------------------------
1 | {
2 | "frames": {
3 | "CIRCLE.png": {
4 | "frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
5 | "rotated": false,
6 | "trimmed": false,
7 | "spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
8 | "sourceSize": { "w": 32, "h": 32 }
9 | },
10 | "DEFAULT.png": {
11 | "frame": { "x": 32, "y": 0, "w": 32, "h": 32 },
12 | "rotated": false,
13 | "trimmed": false,
14 | "spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
15 | "sourceSize": { "w": 32, "h": 32 }
16 | },
17 | "DIRT.png": {
18 | "frame": { "x": 0, "y": 32, "w": 32, "h": 32 },
19 | "rotated": false,
20 | "trimmed": false,
21 | "spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
22 | "sourceSize": { "w": 32, "h": 32 }
23 | },
24 | "ROCK.png": {
25 | "frame": { "x": 32, "y": 32, "w": 32, "h": 32 },
26 | "rotated": false,
27 | "trimmed": false,
28 | "spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
29 | "sourceSize": { "w": 32, "h": 32 }
30 | },
31 | "LEMM_HEAD.png": {
32 | "frame": { "x": 0, "y": 64, "w": 32, "h": 32 },
33 | "rotated": false,
34 | "trimmed": false,
35 | "spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
36 | "sourceSize": { "w": 32, "h": 32 }
37 | },
38 | "LEMM.png": {
39 | "frame": { "x": 32, "y": 64, "w": 32, "h": 32 },
40 | "rotated": false,
41 | "trimmed": false,
42 | "spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
43 | "sourceSize": { "w": 32, "h": 32 }
44 | }
45 | },
46 | "meta": { "app": "https://github.com/piskelapp/piskel/", "version": "1.0", "image": "lemmings.png", "format": "RGBA8888", "size": { "w": 64, "h": 96 } }
47 | }
48 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/index.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import '../styles/main.scss'
3 | import MFMS from '../components/mfms.vue'
4 | ---
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | MFM.ROCKS
13 |
14 |
15 |
16 |
17 | A Movable Feast Machine Simulator written in JavaScript
18 |
40 |
41 |
42 |
45 |
46 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/mfmrocks/src/pages/lemmings/_game/renderer/sprites.ts:
--------------------------------------------------------------------------------
1 | import { Sprite, Assets, Texture, Spritesheet } from "pixi.js";
2 |
3 | import DEFAULT from "./sprites/CIRCLE.png";
4 | // import SOLID from "./sprites/SOLID.png";
5 | // import LEMM from "./sprites/LEMM.png";
6 | // import LEMM_HEAD from "./sprites/LEMM_HEAD.png";
7 | // import DIRT from "./sprites/DIRT.png";
8 | // import ROCK from "./sprites/ROCK.png";
9 | // import POWER from "./sprites/POWER.png";
10 |
11 | import SPRITESHEET_DATA from './sprites/lemmings.json';
12 | import SPRITESHEET from './sprites/lemmings.png';
13 |
14 | export const DEFAULT_TEXTURE = await Assets.load( DEFAULT );
15 |
16 | const SPRITE_MAP = {
17 | // "EMPTY": "DEFAULT",
18 | "LEMM": "LEMM",
19 | "LEMM_HEAD": "LEMM_HEAD",
20 | // "DIRT": "DIRT",
21 | // "ROCK": "ROCK",
22 | // "TODE_RED": "CIRCLE",
23 | // "TODE_GREEN": "CIRCLE",
24 | // "TODE_BLACK": "CIRCLE",
25 | // "SAND": "DIRT",
26 | // "MOSS": "DIRT",
27 | // "SOLID": "CIRCLE",
28 | // "EXIT_FRAME": "ROCK",
29 | // "EMPTY_EXIT": "ROCK",
30 | // "EXIT": "ROCK",
31 | }
32 |
33 | const SPRITE_SHEET_TEXTURE = await Assets.load( SPRITESHEET );
34 | export const SPRITES = new Spritesheet(
35 | SPRITE_SHEET_TEXTURE,
36 | SPRITESHEET_DATA
37 | );
38 |
39 | await SPRITES.parse();
40 |
41 | console.log( SPRITES );
42 |
43 | export const LEMMING_TEXTURES = {}
44 |
45 |
46 | export function getTexture( name, rotate ) {
47 |
48 | // rotate = [0,2,4,6,8][~~(Math.random() * 4)];
49 |
50 | const t = SPRITES.textures[`${SPRITE_MAP[name]}.png`] || LEMMING_TEXTURES[name] || DEFAULT_TEXTURE;
51 |
52 | if( rotate ) {
53 | return rotateTexture( t, rotate );
54 | }
55 | return t;
56 | }
57 |
58 | function rotateTexture( texture, rotation ) {
59 | return new Texture( {
60 | source: texture.baseTexture,
61 | frame: texture.frame,
62 | orig: texture.orig,
63 | trim:texture.trim,
64 | rotate: rotation ?? 0
65 | });
66 | }
--------------------------------------------------------------------------------
/mfm-js/src/elements/core/Wall.ts:
--------------------------------------------------------------------------------
1 | import { Decay } from "../../capabilities/Decay";
2 | import { Repel } from "../../capabilities/Repel";
3 | import { Element, IElementType } from "../../mfm/Element";
4 | import { EventWindow } from "../../mfm/EventWindow";
5 | import { Builder } from "./Builder";
6 |
7 | export class Wall extends Element {
8 | static CREATE = Wall.CREATOR({ name: "WALL", class: Wall, color: 0x3311cc, groups: ["Structural", "MFM"] });
9 | static MOVABLE_WALL = Wall.CREATOR({ name: "MOVABLE WALL", class: Wall, color: 0x8811cc, classifications: ["MOVABLE"], groups: ["Structural", "MFM"] });
10 | static DECAY_WALL = Wall.CREATOR({ name: "DECAY WALL", class: Wall, color: 0x0000ee, classifications: ["DECAYABLE", "WALL"], groups: ["Structural"] });
11 | static DECAY_WALL_10 = Wall.CREATOR(
12 | { name: "DECAY WALL 10", class: Wall, color: 0x0000ee, classifications: ["DECAYABLE", "WALL", "DECAY WALL"], groups: ["Structural"] },
13 | { lifeSpan: 10 }
14 | );
15 | static DECAY_WALL_25 = Wall.CREATOR(
16 | { name: "DECAY WALL 25", class: Wall, color: 0x0000ee, classifications: ["DECAYABLE", "WALL", "DECAY WALL"], groups: ["Structural"] },
17 | { lifeSpan: 25 }
18 | );
19 | static DECAY_WALL_50 = Wall.CREATOR(
20 | { name: "DECAY WALL 50", class: Wall, color: 0x0000ee, classifications: ["DECAYABLE", "WALL", "DECAY WALL"], groups: ["Structural"] },
21 | { lifeSpan: 50 }
22 | );
23 |
24 | static MOVABLE_WALL_GRID = Builder.CREATOR(
25 | { name: "MOVABLE WALL GRID", class: Builder, color: 0x121112, groups: ["Structural"] },
26 | { buildPath: EventWindow.DIAGONAL4WAY, atomizer: Wall.MOVABLE_WALL }
27 | );
28 |
29 | constructor(type: IElementType, state: any = {}) {
30 | super(type, state);
31 |
32 | this.init();
33 | }
34 |
35 | init() {}
36 |
37 | behave(ew: EventWindow) {
38 | super.behave(ew);
39 |
40 | if (ew.selfIs("DECAYABLE")) {
41 | Decay.DECAY(ew, this, this.state.lifeSpan ?? 100, 2);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/mfm-js/dist/renderers/pixi/renderer.d.ts:
--------------------------------------------------------------------------------
1 | import { Sprite, Container, Application, Texture, FederatedPointerEvent } from 'pixi.js';
2 | import { Site } from '../../src/mfm/Site.js';
3 | import { Tile } from '../../src/mfm/Tile.js';
4 |
5 | export interface IRenderer {
6 | tile: Tile;
7 | render: Function;
8 | view: any;
9 | }
10 | export interface ISiteRenderer {
11 | }
12 | export declare class PixiRenderer implements IRenderer {
13 | rendererWidth: number;
14 | rendererHeight: number;
15 | tile: Tile;
16 | tileWidth: number;
17 | tileHeight: number;
18 | totalSites: number;
19 | siteSize: number;
20 | siteTexture: Texture;
21 | particleContainer: Container;
22 | pixiApplication: Application;
23 | siteVisuals: Map;
24 | subdivisions: number;
25 | gridDivisions: number[][];
26 | gridDivisionTotal: number;
27 | siteArray: Site[];
28 | renderSpeed: number;
29 | fixedRenderSpeed: number;
30 | renderMultiplier: number;
31 | view: any;
32 | clickArea: Container;
33 | pointerDown: boolean;
34 | curSelectedElementFunction: Function;
35 | selectedSite: Site;
36 | mouseEnabled: boolean;
37 | brushSize: number;
38 | constructor(t: Tile, rendererW: number, rendererH: number);
39 | init(): Promise;
40 | calculateSubdivisions(): number;
41 | setSubdivisions(subs: number): void;
42 | setRenderMultiplier(mult: number): void;
43 | initializePIXI(): Promise;
44 | initializeVisuals(): Promise;
45 | createSubdivisions(subdivisions: any): void;
46 | startRendering(): void;
47 | deconstruct(): void;
48 | render(): void;
49 | initializeClickArea(): void;
50 | getSitesFromCanvasXY(x: number, y: number, size?: number): Site[];
51 | getSiteFromCanvasXY(x: number, y: number): Site;
52 | handleClick(e: FederatedPointerEvent): void;
53 | addAtom(site: Site): void;
54 | minValue(v1: any, v2: any): any;
55 | maxValue(v1: any, v2: any): any;
56 | clear(): void;
57 | }
58 |
--------------------------------------------------------------------------------
/mfm-js/dist/src/mfm/VirtualEventWindow.d.ts:
--------------------------------------------------------------------------------
1 | import { EWIndex, EventWindow } from './EventWindow';
2 | import { Site } from './Site';
3 | import { ICoordinate } from './TileCoordinate';
4 |
5 | export type VirtualEWIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144;
6 | export declare class VirtualEventWindow {
7 | static VIRTUAL_WINDOW_OFFSETS: Array;
8 | static VIRTUAL_WINDOW_OFFSETS_MAP: Map;
9 | static ORIENTATIONS: Array