diff options
author | sanine <sanine.not@pm.me> | 2023-11-06 00:34:06 -0600 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-11-06 00:34:06 -0600 |
commit | 078a01a078dae15b5e8e3482b57f156ecd0c7fae (patch) | |
tree | f60cdd0e537663fd4e7856786dd5ec6ce5168d55 /src/world/agent.js | |
parent | 7274cef10061f0b9c2c907b730589b4f221b2487 (diff) |
implement flag conflicts
Diffstat (limited to 'src/world/agent.js')
-rw-r--r-- | src/world/agent.js | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/src/world/agent.js b/src/world/agent.js index f7e5a63..95d869c 100644 --- a/src/world/agent.js +++ b/src/world/agent.js @@ -46,39 +46,90 @@ import { pairs, deepEqual } from '../util.js'; */ +function flags_compatible(a, b) { + const keys = [...new Set(Object.keys(a).concat(Object.keys(b)))]; + return keys.reduce( + (acc, key) => { + const eq = (a[key] === undefined || b[key] === undefined) ? true : deepEqual(a[key], b[key]); + return acc && eq; + }, + true + ); +} + + // return a tuple [conflict, merge] // conflict is true if the two world_changes are incompatible // merge is true if the two world changes are identical // otherwise they are false function world_change_conflict(a, b) { - if (a.x != b.x) { return [false, false]; } - if (a.y != b.y) { return [false, false]; } - if (a.to != b.to) { return [true, false]; } - // x, y, and to all match -- merge - return [false, true]; + if (deepEqual(a, b)) { + // merge + return [false, true]; + } + if ( + a.x === b.x && + a.y === b.y && + (a.to != b.to || !flags_compatible(a.flags || {}, b.flags || {})) + ) { + // conflict! + return [true, false]; + } else { + // no conflict c: + return [false, false]; + } } +// returns true as long as x & y are both defined +function pos_exists(a) { + if (a.x !== undefined && a.y !== undefined) { + return true; + } else { + return false; + } +} + + +function pos_equal(a, b) { + if (a.x !== b.x) { return false; } + if (a.y !== b.y) { return false; } + return true; +} + + +// agent changes merge if they are identical +// they conflict if two agents are trying to move to the same tile, or +// if the same agent is trying to move to two different tiles, or if an agent +// is being updated to incompatible flags +// +// function agent_change_conflict(a, b) { if (deepEqual(a, b)) { // identical: merge return [false, true]; - } else if ( - (a.agent_id === b.agent_id) && - ((a.x != b.x) || (a.y != b.y)) - ) { - // same agent, different tiles: conflict - return [true, false]; - } else if ( - (a.agent_id != b.agent_id) && - (a.x === b.x) && - (a.y === b.y) - ) { - // different agents, same tile: conflict - return [true, false]; + } else if (a.agent_id === b.agent_id) { + if ( + pos_exists(a) && pos_exists(b) && !pos_equal(a, b) + ) { + // same agent, different positions: conflict + return [true, false]; + } else if (!flags_compatible(a.flags, b.flags)) { + // same agent, incompatible flags: conflict + return [true, false]; + } else { + // no conflict c: + return [false, false]; + } } else { - // no conflict c: - return [false, false]; + // different agents + if (pos_exists(a) && pos_exists(b) && pos_equal(a, b)) { + // different agents, same position: conflict + return [true, false]; + } else { + // no conflict c: + return [false, false]; + } } } |