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
|
import { pairs } from '../util.js';
/* agent structure:
* {
* id: string
* net: network
* state: network_state
* x, y: number
* flags: object
* }
*/
/* action structure:
* {
* name: string,
* propose: (agent) => proposal[]
* }
*/
/* proposal structure
* all proposed world and agent changes must be included for the proposed action to be valid
* similarly, if any world or agent change creates merge conflicts, the proposal cannot be merged
* and must be removed
* {
* world_changes: proposal_world_change[]?
* agent_changes: proposal_agent_change[]?
* }
*/
/* proposal_world_change
* {
* x, y: number
* from: string
* to: string
* }
*/
/* proposal_agent_change
* {
* agent_id: string
* x, y: number?
* flags: object?
* }
*/
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];
}
function proposal_conflict_merge(a, b) {
const [world_conflict, world_merge] = pairs(a.world_changes, b.world_changes).reduce(
(acc, [a, b]) => {
const [conflict, merge] = world_change_conflict(a, b);
return [acc[0] || conflict, acc[1] || merge];
},
[false, false]
)
return [world_conflict, world_merge];
}
// merge proposals
// if two sub-updates conflict, they are both omitted from the final merged proposal
export function proposal_merge(arr, proposal) {
const conflict_merge = arr.map(x => proposal_conflict_merge(x, proposal));
// if any conflicts are detected then don't merge
if (conflict_merge.reduce((acc, [c, m]) => acc || c, false)) {
const conflict_free = arr.filter((x, i) => !conflict_merge[i][0]);
return conflict_free;
} else {
// no conflicts, but need to merge identical actions
const no_merge = arr.filter((x, i) => !conflict_merge[i][1]);
return [...no_merge, proposal];
}
}
|