summaryrefslogtreecommitdiff
path: root/src/simulation/senses.js
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-11-10 15:43:49 -0600
committersanine <sanine.not@pm.me>2023-11-10 15:43:49 -0600
commit27c786d440b66a0e2e7a168a15396185392a755b (patch)
treedd43ee99898471c59c5d56f1fa0b4cf56c5555e5 /src/simulation/senses.js
parente3716be01e57e5a4eec591d606917c1bf1066b05 (diff)
add non-passing vision test
Diffstat (limited to 'src/simulation/senses.js')
-rw-r--r--src/simulation/senses.js125
1 files changed, 124 insertions, 1 deletions
diff --git a/src/simulation/senses.js b/src/simulation/senses.js
index 0a882c9..87115db 100644
--- a/src/simulation/senses.js
+++ b/src/simulation/senses.js
@@ -46,6 +46,129 @@ const hear = {
};
+const [VIS_WIDTH, VIS_HEIGHT] = [31, 31];
+const [VIS_HWIDTH, VIS_HHEIGHT] = [Math.floor(VIS_WIDTH/2), Math.floor(VIS_HEIGHT/2)];
+function identity_mod(n, p) {
+ const mod = (n % (2*p)) - p + 1;
+ return mod/p;
+}
+
+function world_pos_to_vision_pos(world, agent, x, y) {
+ const dx = x - agent.x;
+ const dy = y - agent.y;
+ const orientation = agent.flags.orientation || 'n';
+ switch (orientation) {
+ case 'n':
+ return [VIS_HWIDTH+dx, VIS_HEIGHT+dy-1];
+ case 's':
+ return [VIS_HWIDTH-dx, VIS_HEIGHT-dy-1];
+ case 'e':
+ return [VIS_HWIDTH+dy, VIS_HEIGHT-dx-1];
+ case 'w':
+ return [VIS_HWIDTH-dy, VIS_HEIGHT+dx-1];
+ }
+}
+
+function vision_pos_to_world_pos(world, agent, x, y) {
+ const dx = x-VIS_HWIDTH;
+ const dy = y-VIS_HEIGHT+1;
+ const orientation = agent.flags.orientation || 'n';
+ switch (orientation) {
+ case 'n':
+ return [agent.x + dx, agent.y + dy];
+ case 's':
+ return [agent.x - dx, agent.y - dy];
+ case 'e':
+ return [agent.x + dy, agent.y - dx];
+ case 'w':
+ return [agent.x - dy, agent.y + dx];
+ }
+}
+
+function world_pos_to_vision_idx(world, agent, x, y) {
+ const [vx, vy] = world_pos_to_vision_pos(world, agent, x, y);
+ console.log('vision pos', vx, vy);
+ return (VIS_WIDTH * vy) + vx;
+}
+function vision_idx_to_world_pos(world, agent, idx) {
+ const vx = idx % VIS_WIDTH;
+ const vy = Math.floor(idx / VIS_WIDTH);
+ return vision_pos_to_world_pos(world, agent, vx, vy);
+}
+
+function see_cell(world, x, y) {
+ const team = 0;
+ const orientation = 0;
+ const type = {
+ active: -0.8,
+ mutable: -0.4,
+ empty: 0.0,
+ immutable: 0.4,
+ flag: 0.8,
+ }[world.lattice[y][x].type];
+ return [team, orientation, type];
+}
+
+
+function relative_orientation(viewer, agent) {
+ switch(viewer.flags.orientation) {
+ case 'n': return { n: -0.8, e: -0.4, s: 0.4, w: 0.8 }[agent.flags.orientation];
+ case 'e': return { e: -0.8, s: -0.4, w: 0.4, n: 0.8 }[agent.flags.orientation];
+ case 's': return { s: -0.8, w: -0.4, n: 0.4, e: 0.8 }[agent.flags.orientation];
+ case 'w': return { w: -0.8, n: -0.4, e: 0.4, s: 0.8 }[agent.flags.orientation];
+ }
+}
+
+
+function see_agent(viewer, agent) {
+ const team = {
+ 0: -0.8,
+ 1: -0.4,
+ 2: 0.4,
+ 3: 0.8,
+ }[agent.flags.team] + (identity_mod(agent.id, 11)/16);
+ const orientation = relative_orientation(viewer, agent) + (identity_mod(agent.id, 37)/16);
+ const type = (() => {
+ if (agent.flags.frozen && agent.flags.flag) {
+ return -0.4;
+ } else if (agent.flags.frozen) {
+ return -0.8;
+ } else if (agent.flags.flag) {
+ return 0.8;
+ } else {
+ return 0.0;
+ }
+ })() + (identity_mod(agent.id, 499)/16);
+
+ return [team, orientation, type];
+}
+
+
+const see = {
+ size: VIS_WIDTH * VIS_HEIGHT,
+ read: (world, agent) => {
+ const vision = [...Array(VIS_WIDTH*VIS_HEIGHT).keys()]
+ .map(idx => {
+ const [x, y] = vision_idx_to_world_pos(world, agent, idx);
+ console.log(x, y, idx);
+ return see_cell(world, x, y);
+ });
+ return world.agents.reduce(
+ (acc, a) => {
+ const idx = world_pos_to_vision_idx(world, agent, a.x, a.y);
+ if (idx < 0 || idx > VIS_WIDTH*VIS_HEIGHT) {
+ return acc;
+ } else {
+ return acc.toSpliced(idx, 1, see_agent(agent, a));
+ }
+ },
+ vision
+ );
+ },
+};
+
+
+
export const senses = [
- frozen, hear,
+ frozen, hear, see,
];