summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-11-10 12:06:35 -0600
committersanine <sanine.not@pm.me>2023-11-10 12:06:35 -0600
commite3716be01e57e5a4eec591d606917c1bf1066b05 (patch)
tree308cfb830469653cffbb58ad513710c209d1482e
parent428062dccb362627b4251945632c75d9db8f93f7 (diff)
implement hearing
-rw-r--r--src/simulation/senses.js37
-rw-r--r--src/simulation/senses.test.js90
2 files changed, 121 insertions, 6 deletions
diff --git a/src/simulation/senses.js b/src/simulation/senses.js
index 4fc96d6..0a882c9 100644
--- a/src/simulation/senses.js
+++ b/src/simulation/senses.js
@@ -3,7 +3,7 @@
const frozen = {
size: 1,
- read: (lattice, agent) => {
+ read: (world, agent) => {
if (agent.flags.frozen === true) {
return [ 1 ];
} else {
@@ -13,6 +13,39 @@ const frozen = {
};
+// add two arrays together element-wise with a scaling factor
+function array_scalesum(a, s, b) {
+ return a.map((x, i) => x + (s*b[i]));
+}
+// determine the square of the distance between two cells
+function lattice_dist2(x0, y0, x1, y1) {
+ if (x0 === x1 && y0 === y1) { return 1; } // not proper distance but avoids divide-by-zero errors c:
+ return ((x0-x1)**2) + ((y0-y1)**2);
+}
+const hear = {
+ size: 8,
+ read: (world, agent) => {
+ const {x, y} = agent;
+ const lattice_sounds = world.lattice
+ .map((row, cy) => row.map((cell, cx) => [ 1/lattice_dist2(x, y, cx, cy), cell ]))
+ .flat()
+ .filter(([scale, cell]) => cell.flags.emit !== undefined)
+ .reduce(
+ (acc, [scale, cell]) => array_scalesum(acc, scale, cell.flags.emit),
+ [0, 0, 0, 0, 0, 0, 0, 0]
+ );
+ const agent_sounds = world.agents
+ .filter(a => a.flags.emit !== undefined)
+ .reduce(
+ (acc, a) => array_scalesum(acc, 1/lattice_dist2(x, y, a.x, a.y), a.flags.emit),
+ [0, 0, 0, 0, 0, 0, 0, 0]
+ );
+
+ return array_scalesum(lattice_sounds, 1, agent_sounds).map(ch => Math.tanh(ch));
+ },
+};
+
+
export const senses = [
- frozen,
+ frozen, hear,
];
diff --git a/src/simulation/senses.test.js b/src/simulation/senses.test.js
index 1caed52..b54ada2 100644
--- a/src/simulation/senses.test.js
+++ b/src/simulation/senses.test.js
@@ -2,7 +2,7 @@
import { senses } from './senses.js';
-const [ frozen, ...rest ] = senses;
+const [ frozen, hear, ...rest ] = senses;
test("frozen sense", () => {
@@ -10,9 +10,91 @@ test("frozen sense", () => {
id: 0, x: 0, y: 0,
flags: { frozen: true, },
};
- const lattice = null;
- expect(frozen.read(lattice, agent)).toEqual([1]);
+ expect(frozen.read(null, agent)).toEqual([1]);
agent.flags.frozen = false;
- expect(frozen.read(lattice, agent)).toEqual([0]);
+ expect(frozen.read(null, agent)).toEqual([0]);
+});
+
+
+test("hear nothing", () => {
+ const agent = { id: 4, x: 1, y: 1, flags: {} };
+ const o = { type: 'empty', flags: {} };
+ const world = {
+ lattice: [
+ [ o, o, o ],
+ [ o, o, o ],
+ [ o, o, o ],
+ ],
+ agents: [agent],
+ };
+
+ expect(hear.read(world, agent)).toEqual([
+ Math.tanh(0), Math.tanh(0), Math.tanh(0), Math.tanh(0),
+ Math.tanh(0), Math.tanh(0), Math.tanh(0), Math.tanh(0),
+ ]);
+});
+
+
+test("hear self", () => {
+ const agent = { id: 4, x: 1, y: 1, flags: { emit: [1, 0, 0.5, 0, 0, 0, 0, 1] } };
+ const o = { type: 'empty', flags: {} };
+ const world = {
+ lattice: [
+ [ o, o, o ],
+ [ o, o, o ],
+ [ o, o, o ],
+ ],
+ agents: [agent],
+ };
+
+ expect(hear.read(world, agent)).toEqual([
+ Math.tanh(1), Math.tanh(0), Math.tanh(0.5), Math.tanh(0),
+ Math.tanh(0), Math.tanh(0), Math.tanh(0), Math.tanh(1),
+ ]);
+});
+
+
+test("hear cells", () => {
+ const agent = { id: 4, x: 2, y: 2, flags: {} };
+ const o = { type: 'empty', flags: {} };
+ const s = { type: 'empty', flags: { emit: [1, 0.5, 0.25, 0.125, 0, 0, 0, 0] } };
+ const world = {
+ lattice: [
+ [ o, o, s, o, o ],
+ [ o, o, o, o, o ],
+ [ o, s, o, o, o ],
+ [ o, o, o, o, o ],
+ [ o, o, o, o, o ],
+ ],
+ agents: [agent],
+ };
+
+ expect(hear.read(world, agent)).toEqual([
+ Math.tanh(1.25), Math.tanh(0.625), Math.tanh(0.3125), Math.tanh(0.15625),
+ Math.tanh(0), Math.tanh(0), Math.tanh(0), Math.tanh(0),
+ ]);
+});
+
+
+test("hear cells & agents", () => {
+ const agent = { id: 4, x: 2, y: 2, flags: {} };
+ const agent2 = { id: 0, x: 2, y: 4, flags: { emit: [0, 0, 0, 0, 1, 1, 1, 1] } };
+ const o = { type: 'empty', flags: {} };
+ const s = { type: 'empty', flags: { emit: [1, 0.5, 0.25, 0.125, 0, 0, 0, 0] } };
+ const world = {
+ lattice: [
+ [ o, o, s, o, o ],
+ [ o, o, o, o, o ],
+ [ o, s, o, o, o ],
+ [ o, o, o, o, o ],
+ [ o, o, o, o, o ],
+ ],
+ agents: [agent, agent2],
+ };
+
+ expect(hear.read(world, agent)).toEqual([
+ Math.tanh(1.25), Math.tanh(0.625), Math.tanh(0.3125), Math.tanh(0.15625),
+ Math.tanh(0.25), Math.tanh(0.25), Math.tanh(0.25), Math.tanh(0.25),
+ ]);
});