diff options
Diffstat (limited to 'src/simulation')
-rw-r--r-- | src/simulation/actions.js | 260 | ||||
-rw-r--r-- | src/simulation/actions.test.js | 294 | ||||
-rw-r--r-- | src/simulation/game.js | 255 | ||||
-rw-r--r-- | src/simulation/game.test.js | 59 | ||||
-rw-r--r-- | src/simulation/lattice_rules.js | 77 | ||||
-rw-r--r-- | src/simulation/lattice_rules.test.js | 147 | ||||
-rw-r--r-- | src/simulation/postprocess.js | 18 | ||||
-rw-r--r-- | src/simulation/postprocess.test.js | 37 | ||||
-rw-r--r-- | src/simulation/senses.js | 182 | ||||
-rw-r--r-- | src/simulation/senses.test.js | 499 | ||||
-rw-r--r-- | src/simulation/trial.js | 12 | ||||
-rw-r--r-- | src/simulation/validity.js | 14 | ||||
-rw-r--r-- | src/simulation/validity.test.js | 43 |
13 files changed, 0 insertions, 1897 deletions
diff --git a/src/simulation/actions.js b/src/simulation/actions.js deleted file mode 100644 index ad08572..0000000 --- a/src/simulation/actions.js +++ /dev/null @@ -1,260 +0,0 @@ -'use strict'; - -const threshold = 0.5; - - -const move_forward = { - size: 1, - propose: (world, agent, head) => { - if (agent.flags.frozen === true) { return []; } - if (head[0] > threshold) { - console.log('move forward'); - console.log(agent.id, agent.x, agent.y); - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - return [{ - agent_changes: [{ - agent_id: agent.id, - x: agent.x + dx, - y: agent.y + dy, - }], - }]; - } else { - return []; - } - }, -}; - - -const move_backward = { - size: 1, - propose: (world, agent, head) => { - if (agent.flags.frozen === true) { return []; } - if (head[0] > threshold) { - console.log('move backward'); - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - return [{ - agent_changes: [{ - agent_id: agent.id, - x: agent.x - dx, - y: agent.y - dy, - }], - }]; - } else { - return []; - } - }, -}; - - -const turn_left = { - size: 1, - propose: (world, agent, head) => { - if (agent.flags.frozen === true) { return []; } - if (head[0] > threshold) { - console.log('turn left'); - const orientation = { n: 'w', e: 'n', s: 'e', w: 's' }[agent.flags.orientation]; - return [{ - agent_changes: [{ - agent_id: agent.id, - flags: { orientation }, - }], - }]; - } else { - return []; - } - }, -}; - - -const turn_right = { - size: 1, - propose: (world, agent, head) => { - if (agent.flags.frozen === true) { return []; } - if (head[0] > threshold) { - console.log('turn right'); - const orientation = { n: 'e', e: 's', s: 'w', w: 'n' }[agent.flags.orientation]; - return [{ - agent_changes: [{ - agent_id: agent.id, - flags: { orientation }, - }], - }]; - } else { - return []; - } - }, -}; - - -const place = { - size: 1, - propose: (world, agent, head) => { - if (head[0] < threshold) { return []; } - else { - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - return [ - { lattice_changes: [{ - x: agent.x + dx, y: agent.y + dy, - from: 'empty', to: 'mutable', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] }, - }]} - ]; - } - }, -}; - - -const trigger = { - size: 1, - propose: (world, agent, head) => { - if (head[0] < threshold) { return []; } - else { - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - return [ - { lattice_changes: [{ - x: agent.x + dx, y: agent.y + dy, - from: 'mutable', to: 'active', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] }, - }]} - ]; - } - }, -}; - - -const pretend_frozen = { - size: 1, - propose: (world, agent, head) => { - if (head[0] < threshold) { return [{ - agent_changes: [{ - agent_id: agent.id, - flags: { pretend_frozen: false }, - }], - }]; } - else { - return [{ - agent_changes: [{ - agent_id: agent.id, - flags: { pretend_frozen: true }, - }] - }]; - } - }, -}; - - -const unfreeze = { - size: 1, - propose: (world, agent, head) => { - if (head[0] < threshold) { return []; } - else { - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - const target = world.agents.filter( - a => a.x === agent.x+dx && a.y === agent.y+dy - )[0]; - if (target === undefined) { return []; } - return [ - { agent_changes: [{ - agent_id: target.id, - flags: { frozen: false, emit: [0, 1, 0, 0, 0, 0, 0, 0] }, - }]} - ]; - } - }, -}; - - -const take_flag = { - size: 1, - propose: (world, agent, head) => { - if (head[0] < threshold) { return []; } - else { - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - const target = world.agents.filter( - a => a.x === agent.x+dx && a.y === agent.y+dy - )[0]; - if (target === undefined || !target.flags.flag) { - return [ - { - lattice_changes: [{ - x: agent.x + dx, y: agent.y + dy, - from: 'flag', to: 'empty', - flags: { emit: [ 0, 0, 1, 0, 0, 0, 0, 0 ] }, - }], - agent_changes: [{ - agent_id: agent.id, - flags: { flag: true }, - }], - } - ]; - } else { - return [{ - agent_changes: [ - { - agent_id: target.id, - flags: { flag: false }, - }, - { - agent_id: agent.id, - flags: { flag: true }, - }, - ], - }]; - } - } - }, -}; - - -const drop_flag = { - size: 1, - propose: (world, agent, head) => { - if (head[0] < threshold) { return []; } - else if (!agent.flags.flag) { return []; } - else { - const dx = { n: 0, e: 1, s: 0, w: -1 }[agent.flags.orientation]; - const dy = { n: -1, e: 0, s: 1, w: 0 }[agent.flags.orientation]; - return [ - { - lattice_changes: [{ - x: agent.x + dx, y: agent.y + dy, - from: 'empty', to: 'flag', - flags: { emit: [ 0, 0, -1, 0, 0, 0, 0, 0 ] }, - }], - agent_changes: [{ - agent_id: agent.id, - flags: { flag: false }, - }], - } - ]; - } - }, -}; - - -const speak = { - size: 8, - propose: (world, agent, head) => { - return [ - { - agent_changes: [{ - agent_id: agent.id, - flags: { emit: head }, - }], - }, - ]; - }, -}; - - -export const actions = [ - move_forward, /*move_backward, */turn_left, turn_right, - place, trigger, pretend_frozen, unfreeze, take_flag, drop_flag, - speak, -]; diff --git a/src/simulation/actions.test.js b/src/simulation/actions.test.js deleted file mode 100644 index e8406bc..0000000 --- a/src/simulation/actions.test.js +++ /dev/null @@ -1,294 +0,0 @@ -'use strict'; - -import { actions } from './actions.js'; - - -const [ - move_forward, move_backward, - turn_left, turn_right, - place, trigger, - pretend_frozen, unfreeze, - take_flag, - ...rest -] = actions; - - -test("move forward", () => { - const n = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const s = { id: 0, x: 0, y: 0, flags: { orientation: 's' } }; - const e = { id: 0, x: 0, y: 0, flags: { orientation: 'e' } }; - const w = { id: 0, x: 0, y: 0, flags: { orientation: 'w' } }; - - expect(move_forward.propose(null, n, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: 0, y: -1 }] }, - ]); - expect(move_forward.propose(null, s, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: 0, y: 1 }] }, - ]); - expect(move_forward.propose(null, e, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: 1, y: 0 }] }, - ]); - expect(move_forward.propose(null, w, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: -1, y: 0 }] }, - ]); - - expect(move_forward.propose(null, n, [0])).toEqual([]); - expect(move_forward.propose(null, s, [-1])).toEqual([]); - expect(move_forward.propose(null, e, [0])).toEqual([]); - expect(move_forward.propose(null, w, [-1])).toEqual([]); -}); - - -test("move backward", () => { - const n = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const s = { id: 0, x: 0, y: 0, flags: { orientation: 's' } }; - const e = { id: 0, x: 0, y: 0, flags: { orientation: 'e' } }; - const w = { id: 0, x: 0, y: 0, flags: { orientation: 'w' } }; - - expect(move_backward.propose(null, n, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: 0, y: 1 }] }, - ]); - expect(move_backward.propose(null, s, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: 0, y: -1 }] }, - ]); - expect(move_backward.propose(null, e, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: -1, y: 0 }] }, - ]); - expect(move_backward.propose(null, w, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, x: 1, y: 0 }] }, - ]); - - expect(move_backward.propose(null, n, [0])).toEqual([]); - expect(move_backward.propose(null, s, [-1])).toEqual([]); - expect(move_backward.propose(null, e, [0])).toEqual([]); - expect(move_backward.propose(null, w, [-1])).toEqual([]); -}); - - -test("turn_left", () => { - const n = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const s = { id: 0, x: 0, y: 0, flags: { orientation: 's' } }; - const e = { id: 0, x: 0, y: 0, flags: { orientation: 'e' } }; - const w = { id: 0, x: 0, y: 0, flags: { orientation: 'w' } }; - - expect(turn_left.propose(null, n, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 'w' } }] }, - ]); - expect(turn_left.propose(null, s, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 'e' } }] }, - ]); - expect(turn_left.propose(null, e, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 'n' } }] }, - ]); - expect(turn_left.propose(null, w, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 's' } }] }, - ]); - - expect(turn_left.propose(null, n, [0])).toEqual([]); - expect(turn_left.propose(null, s, [-1])).toEqual([]); - expect(turn_left.propose(null, e, [0])).toEqual([]); - expect(turn_left.propose(null, w, [-1])).toEqual([]); -}); - - -test("turn_right", () => { - const n = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const s = { id: 0, x: 0, y: 0, flags: { orientation: 's' } }; - const e = { id: 0, x: 0, y: 0, flags: { orientation: 'e' } }; - const w = { id: 0, x: 0, y: 0, flags: { orientation: 'w' } }; - - expect(turn_right.propose(null, n, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 'e' } }] }, - ]); - expect(turn_right.propose(null, s, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 'w' } }] }, - ]); - expect(turn_right.propose(null, e, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 's' } }] }, - ]); - expect(turn_right.propose(null, w, [1])).toEqual([ - { agent_changes: [{ agent_id: 0, flags: { orientation: 'n' } }] }, - ]); - - expect(turn_right.propose(null, n, [0])).toEqual([]); - expect(turn_right.propose(null, s, [-1])).toEqual([]); - expect(turn_right.propose(null, e, [0])).toEqual([]); - expect(turn_right.propose(null, w, [-1])).toEqual([]); -}); - - -test("place", () => { - const n = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const s = { id: 0, x: 0, y: 0, flags: { orientation: 's' } }; - const e = { id: 0, x: 0, y: 0, flags: { orientation: 'e' } }; - const w = { id: 0, x: 0, y: 0, flags: { orientation: 'w' } }; - - expect(place.propose(null, n, [1])).toEqual([ - { lattice_changes: [ - { - x: 0, y: -1, from: 'empty', to: 'mutable', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] } - } - ]} - ]); - expect(place.propose(null, s, [1])).toEqual([ - { lattice_changes: [ - { - x: 0, y: 1, from: 'empty', to: 'mutable', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] } - } - ]} - ]); - expect(place.propose(null, e, [1])).toEqual([ - { lattice_changes: [ - { - x: 1, y: 0, from: 'empty', to: 'mutable', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] } - } - ]} - ]); - expect(place.propose(null, w, [1])).toEqual([ - { lattice_changes: [ - { - x: -1, y: 0, from: 'empty', to: 'mutable', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] } - } - ]} - ]); - - expect(place.propose(null, n, [0])).toEqual([]); - expect(place.propose(null, s, [-1])).toEqual([]); - expect(place.propose(null, e, [0])).toEqual([]); - expect(place.propose(null, w, [-1])).toEqual([]); -}); - - -test("trigger", () => { - const n = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const s = { id: 0, x: 0, y: 0, flags: { orientation: 's' } }; - const e = { id: 0, x: 0, y: 0, flags: { orientation: 'e' } }; - const w = { id: 0, x: 0, y: 0, flags: { orientation: 'w' } }; - - expect(trigger.propose(null, n, [1])).toEqual([ - { lattice_changes: [{ - x: 0, y: -1, from: 'mutable', to: 'active', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] }, - }]}, - ]); - expect(trigger.propose(null, s, [1])).toEqual([ - { lattice_changes: [{ - x: 0, y: 1, from: 'mutable', to: 'active', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] }, - }]}, - ]); - expect(trigger.propose(null, e, [1])).toEqual([ - { lattice_changes: [{ - x: 1, y: 0, from: 'mutable', to: 'active', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] }, - }]}, - ]); - expect(trigger.propose(null, w, [1])).toEqual([ - { lattice_changes: [{ - x: -1, y: 0, from: 'mutable', to: 'active', - flags: { emit: [1, 0, 0, 0, 0, 0, 0, 0] }, - }]}, - ]); - - expect(trigger.propose(null, n, [0])).toEqual([]); - expect(trigger.propose(null, s, [-1])).toEqual([]); - expect(trigger.propose(null, e, [0])).toEqual([]); - expect(trigger.propose(null, w, [-1])).toEqual([]); - }); - - -test("pretend frozen", () => { - const agent = { id: 2, x: 0, y: 0, flags: { orientation: 'n' } }; - - expect(pretend_frozen.propose(null, agent, [1])).toEqual([{ - agent_changes: [{ - agent_id: 2, - flags: { pretend_frozen: true }, - }] - }]); - - expect(pretend_frozen.propose(null, agent, [0])).toEqual([{ - agent_changes: [{ - agent_id: 2, - flags: { pretend_frozen: false }, - }] - }]); -}); - - -test("unfreeze", () => { - const agent1 = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const agent2 = { id: 1, x: 0, y: -1 }; - const agent3 = { id: 10, x: -1, y: 0 }; - const agents = [ agent1, agent2, agent3 ]; - - expect(unfreeze.propose({agents}, agent1, [1])).toEqual([{ - agent_changes: [{ - agent_id: 1, - flags: { frozen: false, emit: [ 0, 1, 0, 0, 0, 0, 0, 0 ] }, - }] - }]); - - agent1.flags.orientation = 'w'; - - expect(unfreeze.propose({agents}, agent1, [1])).toEqual([{ - agent_changes: [{ - agent_id: 10, - flags: { frozen: false, emit: [ 0, 1, 0, 0, 0, 0, 0, 0 ] }, - }] - }]); - - agent1.flags.orientation = 's'; - expect(unfreeze.propose({agents}, agent1, [1])).toEqual([]); - - expect(unfreeze.propose({agents}, agent1, [0])).toEqual([]); -}); - - -test("take flag", () => { - const agent = { id: 0, x: 0, y: 0, flags: { orientation: 'n' } }; - const other1 = { id: 1, x: 0, y: -1, flags: { flag: true } }; - const other2 = { id: 2, x: 0, y: 1, flags: { flag: false } }; - - const world = { agents: [ agent, other1, other2 ] }; - - expect(take_flag.propose(world, agent, [1])).toEqual([ - { agent_changes: [ - { agent_id: 1, flags: { flag: false } }, - { agent_id: 0, flags: { flag: true } }, - ]}, - ]); - - agent.flags.orientation = 's'; - expect(take_flag.propose(world, agent, [1])).toEqual([ - { - lattice_changes: [ - { - x: 0, y: 1, from: 'flag', to: 'empty', - flags: { emit: [ 0, 0, 1, 0, 0, 0, 0, 0 ] }, - }, - ], - agent_changes: [ - { agent_id: 0, flags: { flag: true } }, - ] - }, - ]); - - expect(take_flag.propose(world, agent, [0])).toEqual([]); -}); - - -test("frozen agents cannot move", () => { - const agent = { id: 0, x: 0, y: 0, flags: { orientation: 'n', frozen: true } }; - - const world = { agents: [agent] }; - - expect(move_forward.propose(world, agent, [1])).toEqual([]); - expect(move_backward.propose(world, agent, [1])).toEqual([]); - expect(turn_left.propose(world, agent, [1])).toEqual([]); - expect(turn_right.propose(world, agent, [1])).toEqual([]); -}); diff --git a/src/simulation/game.js b/src/simulation/game.js deleted file mode 100644 index 978289d..0000000 --- a/src/simulation/game.js +++ /dev/null @@ -1,255 +0,0 @@ -'use strict'; - - -import { random_choice, apply, shuffle } from '../util.js'; -import { mut_genome_insert, parse_genome } from '../genome/genome.js'; -import { world_update } from '../world/world.js'; -import { senses } from './senses.js'; -import { actions } from './actions.js'; -import { lattice_rules } from './lattice_rules.js'; -import { validity } from './validity.js'; -import { postprocess } from './postprocess.js'; - - -function is_wall(size, x, y) { - return ( - x === 0 || x === size-1 || - y === 0 || y === size-1 - ); -} -function is_corner(size, x, y) { - const subsize = Math.floor(size/3); - return ( - (x < subsize || x >= 2*subsize) && - (y < subsize || y >= 2*subsize) - ); -} -export function get_team(size, x, y) { - const subsize = Math.floor(size/3); - if (y < subsize) { - return 0; - } else if (x >= 2*subsize) { - return 1; - } else if (y >= 2*subsize) { - return 2; - } else if (x < subsize) { - return 3; - } else { - return undefined; - } -} - -export function setup_board(size) { - const lattice = [...Array(size)] - .map(() => [...Array(size)]) - .map((row, y) => row.map((_, x) => { - if (is_wall(size, x, y)) { - return { type: 'immutable', flags: {} }; - } else if (is_corner(size, x, y)) { - return { type: 'immutable', flags: {} }; - } else { - const team = get_team(size, x, y); - if (Math.random() > 0.95 && get_team(size, x, y) === undefined) { - return { type: 'flag', flags: { team } }; - } else { - return { type: 'empty', flags: { team } }; - } - } - })); - return lattice; -} - - -export function create_world(size, teams) { - const lattice = setup_board(size); - - const agents = teams.reduce( - (agents, team, team_num) => { - const team_cells = lattice.map((row, y) => row.map((cell, x) => [x, y, cell])).flat() - // only check cells with the right team - .filter(([x, y, cell]) => cell.type === 'empty' && cell.flags.team === team_num) - return agents.concat(team.reduce( - (acc, agent) => { - const available_cells = team_cells.filter(([x, y, cell]) => acc.reduce( - (occupied, a) => occupied && ((a.x !== x) || (a.y !== y)), - true - )) - const [x, y, ..._] = random_choice(available_cells); - const orientation = random_choice([ 'n', 'e', 's', 'w' ]); - return [...acc, {...agent, x, y, flags: { ...agent.flags, team: team_num, orientation } }]; - }, - [] - )); - }, - [] - ).flat(); - - return { lattice, lattice_rules, agents, actions, senses, validity }; -}; - - -// team structure: -// { -// agents -// genome -// score -// games -// } - -const N_INPUT = senses.reduce((acc, sense) => acc + sense.size, 0); -const N_OUTPUT = actions.reduce((acc, action) => acc + action.size, 0); -const MAX_MUTATIONS = 15; - - -let agent_id = 0; - -export function create_agent(genome, n_internal) { - return { - id: agent_id++, // !!!! side effect !!!! - net: parse_genome(genome), - state: [...Array(n_internal)].map(_ => (2*Math.random()) - 1), - } -} - - - -export function create_team(size, genome_size, n_internal) { - const genome = apply( - s => mut_genome_insert(s, 4), - genome_size, - {n_input: N_INPUT, n_internal, n_output: N_OUTPUT, genes: []}, - ); - console.log(N_INPUT, N_OUTPUT, genome); - - const agents = [...Array(size)].map(_ => create_agent(genome, n_internal)); - return { agents, genome, score: 0, games: 0 }; -} - - -export function child_team(team, keep=Math.floor(team.size/2)) { - const n_internal = get_size(team.genome) - N_INPUT - N_OUTPUT; - const genome = apply( - s => mutate_genome(s, 4), - Math.floor(MAX_MUTATIONS * Math.random()), - [N_INPUT, n_internal, N_OUTPUT, team.genome] - ); - - const old_agents = [...Array(team.agents.length - keep)].reduce( - (acc, _) => { - const idx = Math.floor(Math.random() * acc.length); - acc.splice(idx, 1); - return acc; - }, - ); - const new_agents = [...Array(team.agents.length - keep)].map(_ => create_agent(genome, n_internal)); - const agents = [old_agents, new_agents].flat(); - - return { agents, genome, score: 0, games: 0 }; -} - - -// game structure: -// { -// world: world -// team_indices: number[] -// time: number -// } - - -export function create_game(size, teams, team_indices) { - const world = create_world(size, team_indices.map(i => teams[i].agents)); - return { world, team_indices, time: 0 }; -} - - -export function step_game(game) { - return { - ...game, - world: world_update(game.world, postprocess), - time: game.time + 1, - }; -} - - -function score(lattice, team_num) { - const size = lattice.length; - - // count number of flags in the team's area - return lattice - .map((row, y) => row.map((cell, x) => [x, y, cell])) - .flat() - .filter(([x, y, cell]) => get_team(size, x, y) === team_num && cell.type === 'flag') - .length; -} - -export function finish_game(teams, game) { - const scores = [0, 1, 2, 3].map(t => score(game.world.lattice, t)); - return game.team_indices.reduce( - (acc, idx, i) => { - const team = teams[idx]; - acc.splice(idx, 1, {...team, score: team.score + scores[i], games: team.games+1}); - return acc; - }, - teams, - ); -} - - - -// epoch structure -// { -// game -// time -// teams -// } - -function random_indices(teams) { - return [...Array(teams.length - 4)].reduce( - (acc) => { - const idx = Math.floor(Math.random() * acc.length); - acc.splice(idx, 1); - return acc; - }, - [...teams.keys()] - ); -} - -let epoch_num = 0; -export function create_epoch(size, teams) { - return { - game: create_game(size, teams, random_indices(teams)), - time: 0, - epoch: epoch_num++, // !!!! side effects !!!! - size, - teams, - } -} - - -const GAME_STEPS = 10000 -const EPOCH_STEPS = 200 - -export function update_epoch(epoch) { - if (epoch.game.time < GAME_STEPS) { - return { ...epoch, game: step_game(epoch.game) }; - } else if (epoch.time < EPOCH_STEPS) { - return { - ...epoch, - teams: finish_game(epoch.teams, epoch.game), - game: create_game(size, epoch.teams, random_indices(epoch.teams)), - time: epoch.time+1 - }; - } else { - // epoch complete!! - const source_teams = epoch.teams - .map(team => { - const normalized_score = team.score/team.games; - const count = Math.ceil(16*normalized_score); - return [...Array(count > 0 ? count : 1)].map(x => team) - }) - .flat(); - const new_teams = [...Array(epoch.teams.length)] - .reduce((acc) => child_team(random_choice(source_teams)), []); - return create_epoch(epoch.size, new_teams); - } -} diff --git a/src/simulation/game.test.js b/src/simulation/game.test.js deleted file mode 100644 index 219dce6..0000000 --- a/src/simulation/game.test.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -import { apply } from '../util.js'; -import { setup_board, create_world } from './game.js'; - - -test("set up boards correctly", () => { - const _ = { type: 'empty', flags: {} }; - const a = { type: 'empty', flags: { team: 0 } }; - const b = { type: 'empty', flags: { team: 1 } }; - const c = { type: 'empty', flags: { team: 2 } }; - const d = { type: 'empty', flags: { team: 3 } }; - const W = { type: 'immutable', flags: {} }; - - expect(setup_board(6)).toEqual([ - [ W, W, W, W, W, W, ], - [ W, W, a, a, W, W, ], - [ W, d, _, _, b, W, ], - [ W, d, _, _, b, W, ], - [ W, W, c, c, W, W, ], - [ W, W, W, W, W, W, ], - ]); - expect(setup_board(9)).toEqual([ - [ W, W, W, W, W, W, W, W, W, ], - [ W, W, W, a, a, a, W, W, W, ], - [ W, W, W, a, a, a, W, W, W, ], - [ W, d, d, _, _, _, b, b, W, ], - [ W, d, d, _, _, _, b, b, W, ], - [ W, d, d, _, _, _, b, b, W, ], - [ W, W, W, c, c, c, W, W, W, ], - [ W, W, W, c, c, c, W, W, W, ], - [ W, W, W, W, W, W, W, W, W, ], - ]); -}); - - -test("creating a world works correctly", () => { - const id = 0; - const agent = (id) => ({ id, net: `${id}`, state: `s${id}` }); - const team1 = [agent(0), agent(1)]; - const team2 = [agent(2), agent(3)]; - const team3 = [agent(4), agent(5)]; - const team4 = [agent(6), agent(7)]; - - const world = create_world(6, [team1, team2, team3, team4]); - const agent_cell = (agent) => { - const { x, y } = agent; - return world.lattice[y][x]; - }; - - expect(agent_cell(world.agents[0])).toEqual({ type: 'empty', flags: { team: 0 } }); - expect(agent_cell(world.agents[1])).toEqual({ type: 'empty', flags: { team: 0 } }); - expect(agent_cell(world.agents[2])).toEqual({ type: 'empty', flags: { team: 1 } }); - expect(agent_cell(world.agents[3])).toEqual({ type: 'empty', flags: { team: 1 } }); - expect(agent_cell(world.agents[4])).toEqual({ type: 'empty', flags: { team: 2 } }); - expect(agent_cell(world.agents[5])).toEqual({ type: 'empty', flags: { team: 2 } }); - expect(agent_cell(world.agents[6])).toEqual({ type: 'empty', flags: { team: 3 } }); - expect(agent_cell(world.agents[7])).toEqual({ type: 'empty', flags: { team: 3 } }); -}); diff --git a/src/simulation/lattice_rules.js b/src/simulation/lattice_rules.js deleted file mode 100644 index cc2fc5b..0000000 --- a/src/simulation/lattice_rules.js +++ /dev/null @@ -1,77 +0,0 @@ -import { pairs } from '../util.js'; -import { get_team } from './game.js'; - -function mod(k, n) { - return ((k % n) + n) % n; -} - -function pos_wrap(lattice, x, y) { - const height = lattice.length; - const width = lattice[0].length; - return [mod(x, width), mod(y, height)]; -} - - -function neighbors(lattice, x, y) { - const offsets = [-1, 0, 1]; - const positions = pairs(offsets, offsets) - .filter(([dx, dy]) => dx !== 0 || dy !== 0) - .map(([dx, dy]) => pos_wrap(lattice, x+dx, y+dy)); - const neighbors = positions - .map(([x, y]) => [x, y, lattice[y][x]]); - return neighbors; -} - - -export const lattice_rules = { - - empty: (lattice, x, y) => { - const num_active_neighbors = neighbors(lattice, x, y) - .map(([x, y, cell]) => cell.type) - .filter(type => type === 'mutable' || type === 'active') - .length; - if (num_active_neighbors === 3) { - return { world_updates: [{ - x, y, from: 'empty', to: 'active', - flags: { emit: [0, 0, 0, 0, 0, 0, 0, 1] }, - }]}; - } else { - return { world_updates: [{ - x, y, flags: { team: get_team(lattice.length, x, y) }, - }]}; - } - }, - - active: (lattice, x, y) => { - const num_active_neighbors = neighbors(lattice, x, y) - .map(([x, y, cell]) => cell.type) - .filter(type => type === 'mutable' || type === 'active') - .length; - const die = { world_updates: [{ - x, y, from: 'active', to: 'empty', - flags: { emit: [0, 0, 0, 0, 0, 0, 0, -1] }, - }]}; - if (num_active_neighbors < 2) { - return die; - } else if (num_active_neighbors > 3) { - return die; - } - }, - - mutable: (lattice, x, y) => { - const num_active_neighbors = neighbors(lattice, x, y) - .map(([x, y, cell]) => cell.type) - .filter(type => type === 'active') - .length; - if (num_active_neighbors > 0) { - // become living cell - return { world_updates: [{ - x, y, from: 'empty', to: 'active', - flags: { emit: [0, 0, 0, 0, 0, 0, 0, 1] }, - }]}; - } - }, - immutable: () => {}, - flag: () => {}, - -}; diff --git a/src/simulation/lattice_rules.test.js b/src/simulation/lattice_rules.test.js deleted file mode 100644 index c285711..0000000 --- a/src/simulation/lattice_rules.test.js +++ /dev/null @@ -1,147 +0,0 @@ -import { world_update } from '../world/world.js'; -import { lattice_rules } from './lattice_rules.js'; - - -function apply(f, n, x0) { - if (n == 0) { - return x0; - } else { - return f(apply(f, n-1, x0)); - } -} - - -// remove cell team information -function clean_team(lattice) { - return lattice.map(row => row.map(cell => ({...cell, flags: {...cell.flags, team: undefined } }))); -} - - -test("blinker", () => { - const L = { type: 'active', flags: { team: undefined, } }; - const _ = { type: 'empty', flags: { team: undefined, } }; - const l = { type: 'active', flags: { team: undefined, emit: [0, 0, 0, 0, 0, 0, 0, 1] } }; - const d = { type: 'empty', flags: { team: undefined, emit: [0, 0, 0, 0, 0, 0, 0, -1] } }; - const lattice = [ - [ _, _, _, _, _ ], - [ _, _, _, _, _ ], - [ _, L, L, L, _ ], - [ _, _, _, _, _ ], - [ _, _, _, _, _ ], - ]; - - const world = { lattice, lattice_rules, agents: [], senses: [], actions: [], validity: [] }; - expect(clean_team(world_update(world).lattice)).toEqual([ - [ _, _, _, _, _ ], - [ _, _, l, _, _ ], - [ _, d, L, d, _ ], - [ _, _, l, _, _ ], - [ _, _, _, _, _ ], - ]); - expect(clean_team(world_update(world_update(world)).lattice)).toEqual([ - [ _, _, _, _, _ ], - [ _, _, d, _, _ ], - [ _, l, L, l, _ ], - [ _, _, d, _, _ ], - [ _, _, _, _, _ ], - ]); -}); - - -test("glider", () => { - const L = { type: 'active', flags: { team: undefined, } }; - const _ = { type: 'empty', flags: { team: undefined, } }; - const l = { type: 'active', flags: { team: undefined, emit: [0, 0, 0, 0, 0, 0, 0, 1] } }; - const d = { type: 'empty', flags: { team: undefined, emit: [0, 0, 0, 0, 0, 0, 0, -1] } }; - const lattice = [ - [ _, _, _, _, _, _ ], - [ _, _, _, L, _, _ ], - [ _, L, _, L, _, _ ], - [ _, _, L, L, _, _ ], - [ _, _, _, _, _, _ ], - [ _, _, _, _, _, _ ], - ]; - - const world = { lattice, lattice_rules, agents: [], senses: [], actions: [], validity: [] }; - //expect(clean_team(world_update(world).lattice)).toEqual([ - expect(clean_team(apply(world_update, 1, world).lattice)).toEqual([ - [ _, _, _, _, _, _ ], - [ _, _, l, d, _, _ ], - [ _, d, _, L, l, _ ], - [ _, _, L, L, _, _ ], - [ _, _, _, _, _, _ ], - [ _, _, _, _, _, _ ], - ]); - expect(clean_team(apply(world_update, 2, world).lattice)).toEqual([ - [ _, _, _, _, _, _ ], - [ _, _, d, l, _, _ ], - [ _, _, _, d, L, _ ], - [ _, _, L, L, l, _ ], - [ _, _, _, _, _, _ ], - [ _, _, _, _, _, _ ], - ]); - expect(clean_team(apply(world_update, 3, world).lattice)).toEqual([ - [ _, _, _, _, _, _ ], - [ _, _, _, d, _, _ ], - [ _, _, l, _, L, _ ], - [ _, _, d, L, L, _ ], - [ _, _, _, l, _, _ ], - [ _, _, _, _, _, _ ], - ]); - expect(clean_team(apply(world_update, 4, world).lattice)).toEqual([ - [ _, _, _, _, _, _ ], - [ _, _, _, _, _, _ ], - [ _, _, d, _, L, _ ], - [ _, _, l, d, L, _ ], - [ _, _, _, L, l, _ ], - [ _, _, _, _, _, _ ], - ]); -}); - - -test("beehive", () => { - const L = { type: 'active', flags: { team: undefined, } }; - const _ = { type: 'empty', flags: { team: undefined, } }; - const lattice = [ - [ _, _, _, _, _, _ ], - [ _, _, L, L, _, _ ], - [ _, L, _, _, L, _ ], - [ _, _, L, L, _, _ ], - [ _, _, _, _, _, _ ], - ]; - - const world = { lattice, lattice_rules, agents: [], senses: [], actions: [], validity: [] }; - //expect(clean_team(world_update(world).lattice)).toEqual([ - expect(clean_team(apply(world_update, 1, world).lattice)).toEqual(lattice); -}); - - -test("mutables are activated by neighboring actives", () => { - const L = { type: 'active', flags: { team: undefined, } }; - const _ = { type: 'empty', flags: { team: undefined, } }; - const l = { type: 'active', flags: { team: undefined, emit: [0, 0, 0, 0, 0, 0, 0, 1] } }; - const d = { type: 'empty', flags: { team: undefined, emit: [0, 0, 0, 0, 0, 0, 0, -1] } }; - const M = { type: 'mutable', flags: { team: undefined, } }; - - const lattice = [ - [ _, _, _, _, ], - [ _, L, M, _, ], - [ _, M, M, _, ], - [ _, _, _, _, ], - ]; - - const world = { lattice, lattice_rules, agents: [], senses: [], actions: [], validity: [] }; - - expect(clean_team(apply(world_update, 1, world).lattice)).toEqual([ - [ _, _, _, _, ], - [ _, L, l, _, ], - [ _, l, l, _, ], - [ _, _, _, _, ], - ]); - expect(clean_team(apply(world_update, 2, world).lattice)).toEqual([ - [ _, _, _, _, ], - [ _, L, L, _, ], - [ _, L, L, _, ], - [ _, _, _, _, ], - ]); -}); diff --git a/src/simulation/postprocess.js b/src/simulation/postprocess.js deleted file mode 100644 index d50839e..0000000 --- a/src/simulation/postprocess.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -export const postprocess = [ - (world) => ({ - ...world, - agents: world.agents.map(a => { - const {x, y} = a; - if ( - world.lattice[y][x].type === 'mutable' || - world.lattice[y][x].type === 'active' - ) { - return { ...a, flags: {...a.flags, frozen: true } }; - } else { - return a; - } - }), - }), -]; diff --git a/src/simulation/postprocess.test.js b/src/simulation/postprocess.test.js deleted file mode 100644 index dc77c6a..0000000 --- a/src/simulation/postprocess.test.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -import { world_update } from '../world/world.js'; -import { postprocess } from './postprocess.js'; - -test("agents freeze when finishing on a mutable or active", () => { - const agent = { - id: 1, - net: { compute: () => [[1], null] }, - state: null, - x: 0, y: 0, - flags: {}, - }; - - const lattice = [[{ type: 'empty', flags: {} }]]; - - const world = { - lattice, - lattice_rules: { empty: ()=>{}, active: ()=>{}, mutable: ()=>{} }, - agents: [agent], - senses: [], - actions: [], - validity: [], - }; - - expect(world_update(world, postprocess).agents[0]).toEqual(agent); - world.lattice[0][0].type = 'mutable'; - expect(world_update(world, postprocess).agents[0]).toEqual({ - ...agent, - flags: { frozen: true }, - }); - world.lattice[0][0].type = 'active'; - expect(world_update(world, postprocess).agents[0]).toEqual({ - ...agent, - flags: { frozen: true }, - }); -}); diff --git a/src/simulation/senses.js b/src/simulation/senses.js deleted file mode 100644 index 970f86b..0000000 --- a/src/simulation/senses.js +++ /dev/null @@ -1,182 +0,0 @@ -'use strict'; - - -const frozen = { - size: 1, - read: (world, agent) => { - if (agent.flags.frozen === true) { - return [ 1 ]; - } else { - return [ 0 ]; - } - }, -}; - - -// 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)); - }, -}; - - -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); - 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); - const result = vision_pos_to_world_pos(world, agent, vx, vy); - return result; -} - -function see_cell(world, x, y) { - const team = 0; - const orientation = 0; - if (!world.lattice[y] || !world.lattice[y][x]) { - // beyond the map edge - return [ 0, 0, 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 frozen = agent.flags.frozen || agent.flags.pretend_frozen; - const type = (() => { - if (frozen && agent.flags.flag) { - return -0.4; - } else if (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: 3*VIS_WIDTH * VIS_HEIGHT, - read: (world, agent) => { - const indices = [...Array(VIS_WIDTH*VIS_HEIGHT).keys()] - const vision = indices - .map(idx => { - const [x, y] = vision_idx_to_world_pos(world, agent, idx); - return see_cell(world, x, y); - }); - const result = 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 { - acc.splice(idx, 1, see_agent(agent, a)); - return acc; - } - }, - vision - ); - return result.flat(); - }, -}; - - - -export const senses = [ - frozen, hear, see, { size: 1, read: () => [1] }, -]; diff --git a/src/simulation/senses.test.js b/src/simulation/senses.test.js deleted file mode 100644 index d3941c7..0000000 --- a/src/simulation/senses.test.js +++ /dev/null @@ -1,499 +0,0 @@ -'use strict'; - -import { senses } from './senses.js'; - -const [ frozen, hear, see, ...rest ] = senses; - - -test("frozen sense", () => { - const agent = { - id: 0, x: 0, y: 0, - flags: { frozen: true, }, - }; - - expect(frozen.read(null, agent)).toEqual([1]); - agent.flags.frozen = false; - expect(frozen.read(null, agent)).toEqual([0]); -}); - - -// --===== hearing =====-- - -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), - ]); -}); - - -// --===== vision =====-- - - -test("see agents", () => { - const o = { type: 'empty', flags: {} }; - const lattice = [ - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - [ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o ], - ]; - const agentA = { id: 0, x: 15, y: 30, flags: { team: 0, orientation: 'n' } }; - const agentB = { id: 1, x: 15, y: 0, flags: { team: 1, orientation: 's' } }; - const agentC = { id: 2, x: 0, y: 15, flags: { team: 2, orientation: 'e', flag: true } }; - const agentD = { id: 3, x: 30, y: 15, flags: { team: 3, orientation: 'w', frozen: true } }; - const agentE = { id: 4, x: 30, y: 30, flags: { team: 0, orientation: 's', flag: true, frozen: true } }; - const world = { - lattice, - agents: [agentA, agentB, agentC, agentD, agentE], - }; - - const an = [ - -0.8 + 0.0625*(-10/11), // team + identity - -0.8 + 0.0625*(-36/37), // orientation + identity - 0.0 + 0.0625*(-498/499), // class + identity - ]; - const as = [ - -0.8 + 0.0625*(-10/11), // team + identity - 0.4 + 0.0625*(-36/37), // orientation + identity - 0.0 + 0.0625*(-498/499), // class + identity - ]; - const ae = [ - -0.8 + 0.0625*(-10/11), // team + identity - -0.4 + 0.0625*(-36/37), // orientation + identity - 0.0 + 0.0625*(-498/499), // class + identity - ]; - const aw = [ - -0.8 + 0.0625*(-10/11), // team + identity - 0.8 + 0.0625*(-36/37), // orientation + identity - 0.0 + 0.0625*(-498/499), // class + identity - ]; - - const bn = [ - -0.4 + 0.0625*(-9/11), // team + identity - -0.8 + 0.0625*(-35/37), // orientation + identity - 0.0 + 0.0625*(-497/499), // class + identity - ]; - const bs = [ - -0.4 + 0.0625*(-9/11), // team + identity - 0.4 + 0.0625*(-35/37), // orientation + identity - 0.0 + 0.0625*(-497/499), // class + identity - ]; - const be = [ - -0.4 + 0.0625*(-9/11), // team + identity - -0.4 + 0.0625*(-35/37), // orientation + identity - 0.0 + 0.0625*(-497/499), // class + identity - ]; - const bw = [ - -0.4 + 0.0625*(-9/11), // team + identity - 0.8 + 0.0625*(-35/37), // orientation + identity - 0.0 + 0.0625*(-497/499), // class + identity - ]; - - const cn = [ - 0.4 + 0.0625*(-8/11), // team + identity - -0.8 + 0.0625*(-34/37), // orientation + identity - 0.8 + 0.0625*(-496/499), // class + identity - ]; - const cs = [ - 0.4 + 0.0625*(-8/11), // team + identity - 0.4 + 0.0625*(-34/37), // orientation + identity - 0.8 + 0.0625*(-496/499), // class + identity - ]; - const ce = [ - 0.4 + 0.0625*(-8/11), // team + identity - -0.4 + 0.0625*(-34/37), // orientation + identity - 0.8 + 0.0625*(-496/499), // class + identity - ]; - const cw = [ - 0.4 + 0.0625*(-8/11), // team + identity - 0.8 + 0.0625*(-34/37), // orientation + identity - 0.8 + 0.0625*(-496/499), // class + identity - ]; - - const dn = [ - 0.8 + 0.0625*(-7/11), // team + identity - -0.8 + 0.0625*(-33/37), // orientation + identity - -0.8 + 0.0625*(-495/499), // class + identity - ]; - const ds = [ - 0.8 + 0.0625*(-7/11), // team + identity - 0.4 + 0.0625*(-33/37), // orientation + identity - -0.8 + 0.0625*(-495/499), // class + identity - ]; - const de = [ - 0.8 + 0.0625*(-7/11), // team + identity - -0.4 + 0.0625*(-33/37), // orientation + identity - -0.8 + 0.0625*(-495/499), // class + identity - ]; - const dw = [ - 0.8 + 0.0625*(-7/11), // team + identity - 0.8 + 0.0625*(-33/37), // orientation + identity - -0.8 + 0.0625*(-495/499), // class + identity - ]; - - const en = [ - -0.8 + 0.0625*(-6/11), // team + identity - -0.8 + 0.0625*(-32/37), // orientation + identity - -0.4 + 0.0625*(-494/499), // class + identity - ]; - const es = [ - -0.8 + 0.0625*(-6/11), // team + identity - 0.4 + 0.0625*(-32/37), // orientation + identity - -0.4 + 0.0625*(-494/499), // class + identity - ]; - const ee = [ - -0.8 + 0.0625*(-6/11), // team + identity - -0.4 + 0.0625*(-32/37), // orientation + identity - -0.4 + 0.0625*(-494/499), // class + identity - ]; - const ew = [ - -0.8 + 0.0625*(-6/11), // team + identity - 0.8 + 0.0625*(-32/37), // orientation + identity - -0.4 + 0.0625*(-494/499), // class + identity - ]; - - const _ = [ - 0.0, 0.0, 0.0, - ]; - - - expect(see.read(world, agentA)).toEqual([ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, bs, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ce, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, dw, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, an, _, _, _, _, _, _, _, _, _, _, _, _, _, _, es, - ]); - expect(see.read(world, agentB)).toEqual([ - en, _, _, _, _, _, _, _, _, _, _, _, _, _, _, as, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - de, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, cw, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, bn, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ]); - expect(see.read(world, agentC)).toEqual([ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, ds, _, _, _, _, _, _, _, _, _, _, _, _, _, _, ee, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - be, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, aw, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, cn, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ]); - expect(see.read(world, agentD)).toEqual([ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, cs, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ae, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, bw, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ew, _, _, _, _, _, _, _, _, _, _, _, _, _, _, dn, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ]); -}); - - -test("seeing 'nothing' looks like teamless empty squares", () => { - const lattice = [[]]; - const agent = { id: 0, x: 0, y: 0, flags: { team: 0, orientation: 'n' } }; - const world = { - lattice, agents: [agent], - }; - - const _ = [ - 0.0, 0.0, 0.0, - ]; - const an = [ - -0.8 + 0.0625*(-10/11), // team + identity - -0.8 + 0.0625*(-36/37), // orientation + identity - 0.0 + 0.0625*(-498/499), // class + identity - ]; - - expect(see.read(world, agent)).toEqual([ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, an, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ]); -}); - - -test("agents pretending to be frozen appear frozen", () => { - const lattice = [[]]; - const agent = { id: 0, x: 0, y: 0, flags: { team: 0, orientation: 'n', pretend_frozen: true } }; - const world = { - lattice, agents: [agent], - }; - - const _ = [ - 0.0, 0.0, 0.0, - ]; - const an = [ - -0.8 + 0.0625*(-10/11), // team + identity - -0.8 + 0.0625*(-36/37), // orientation + identity - -0.8 + 0.0625*(-498/499), // class + identity - ]; - - expect(see.read(world, agent)).toEqual([ - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, an, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, - ]); -}); diff --git a/src/simulation/trial.js b/src/simulation/trial.js deleted file mode 100644 index b4462c5..0000000 --- a/src/simulation/trial.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -import { create_team, create_epoch, update_epoch } from './game.js'; - -const start_teams = [...Array(50)].map(x => create_team(32, 5, 5)); - -let epoch = create_epoch(start_teams); - -while (epoch.epoch < 1) { - console.log(epoch.epoch, epoch.time, epoch.game.time); - epoch = update_epoch(epoch); -} diff --git a/src/simulation/validity.js b/src/simulation/validity.js deleted file mode 100644 index de4acd1..0000000 --- a/src/simulation/validity.js +++ /dev/null @@ -1,14 +0,0 @@ -export const validity = [ - // prevent agents from moving onto immutables - (world, proposal) => (proposal.agent_changes || []).reduce( - (acc, change) => { - const {x, y} = change; - if (x !== undefined && y !== undefined && world.lattice[y][x].type === 'immutable') { - return false; - } else { - return acc; - } - }, - true, - ), -]; diff --git a/src/simulation/validity.test.js b/src/simulation/validity.test.js deleted file mode 100644 index ba9e684..0000000 --- a/src/simulation/validity.test.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -import { world_update } from '../world/world.js'; -import { validity } from './validity.js'; - -test("agents are not allowed to move into immutables", () => { - const actions = [{ - size: 1, propose: (world, agent, head) => { - return [{ - agent_changes: [{ - agent_id: agent.id, - x: agent.x + 1, y: agent.y, - }], - }]; - }, - }]; - - const agent = { - id: 1, - net: { compute: () => [[1], null] }, - state: null, - x: 0, y: 0, - flags: {}, - }; - - const lattice = [[{ type: 'empty', flags: {} }, { type: 'immutable', flags: {} }]]; - - const world = { - lattice, - lattice_rules: { empty: ()=>{}, immutable: ()=>{} }, - agents: [agent], - senses: [], - actions, - validity, - }; - - expect(world_update(world).agents[0]).toEqual(agent); - world.validity = []; - expect(world_update(world).agents[0]).toEqual({ - ...agent, - x: 1, y: 0, - }); -}); |