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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
game.system.Logic = (entitiesGrid) => {
"use strict";
let currentVerbRules = [];
const isWord = (entity) => entity.hasComponent("gridPosition") && (entity.hasComponent("verb") || entity.hasComponent("noun"));
const getFirstWordEntity = (gridPosition) => {
if (!equivalence(gridPosition, clamp(gridPosition, game.config.xDim, game.config.yDim))) {
return null;
}
for (let entity of entitiesGrid[gridPosition.y][gridPosition.x].values()) {
if (isWord(entity)) {
return entity;
}
}
return null;
};
const verbActionsToComponent = {
"stop": game.components.Stop(),
"push": game.components.Pushable(),
"you": game.components.Controllable({controls: ['left', 'right', 'up', 'down']}),
};
const nounsToEntityCreators = {
"rock": game.createRock,
"wall": game.createWall,
};
const doOnRule = (rule, entities, direction) => {
const [applyee, application] = [entities[rule[0]], entities[rule[1]]];
const changedEntityIds = [];
if (applyee.hasComponent("noun")) {
const entityName = applyee.components.noun.select;
if (application.hasComponent("verb")) {
const verb = application.components.verb.action;
if (direction == "apply") {
currentVerbRules.push(rule);
}
for (let id in entities) {
if (entities[id].hasComponent("name") && entities[id].components.name.selector == entityName) {
changedEntityIds.push(id);
const component = verbActionsToComponent[verb];
if (component) {
if (direction == "apply") {
entities[id].addComponent(component);
} else if (direction == "deapply") {
entities[id].removeComponent(component.name);
}
}
}
}
}
if (application.hasComponent("noun")) {
const applicationEntityName = application.components.noun.select;
for (let id in entities) {
if (entities[id].hasComponent("name") && entities[id].components.name.selector == entityName) {
const e = nounsToEntityCreators[applicationEntityName]();
entities[id].components.name = e.components.name;
entities[id].components.sprite = e.components.sprite;
}
}
}
};
return changedEntityIds;
};
const parseRules = (entities) => {
currentVerbRules.map((rule) => doOnRule(rule, entities, "deapply"));
currentVerbRules = [];
const isWordGridPositions = [];
const changedEntityIds = new Set();
entitiesGrid.forEach((row) => row.forEach((entitiesInCell) => {
for (let entity of entitiesInCell.values()) {
if (isWord(entity) && entity.hasComponent("verb") && entity.components.verb.action == "Is") {
isWordGridPositions.push(entity.components.gridPosition);
}
}
}));
let newRules = [];
isWordGridPositions.forEach((gridPosition) => {
const east = getFirstWordEntity({y: gridPosition.y, x: gridPosition.x - 1});
const west = getFirstWordEntity({y: gridPosition.y, x: gridPosition.x + 1});
const north = getFirstWordEntity({x: gridPosition.x, y: gridPosition.y - 1});
const south = getFirstWordEntity({x: gridPosition.x, y: gridPosition.y + 1});
if (east && west) {
newRules.push([east.id, west.id]);
}
if (north && south) {
newRules.push([north.id, south.id]);
}
});
newRules = newRules.sort((a, b) => (entities[b[1]].hasComponent("noun") ? 1 : -1) - (entities[a[1]].hasComponent("noun") ? 1 : -1));
newRules.map((rule) => doOnRule(rule, entities, "apply").map((id) => changedEntityIds.add(id)));
return changedEntityIds;
};
const update = (_elapsedTime, entities, changedIds) => {
for (let id of changedIds) {
const changed = entities[id];
if (changed.hasComponent("verb") || changed.hasComponent("noun")) {
return parseRules(entities);
}
}
return new Set();
};
return { update, parseRules };
};
|