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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
game.system.Logic = (entitiesGrid) => {
"use strict";
let currentVerbRules = [];
let previousControllableIds = new Set();
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']}),
"burn": game.components.Burn(),
"sink": game.components.Sink(),
"win": game.components.Win(),
};
const nounsToEntityCreators = {
"rock": game.createRock,
"wall": game.createWall,
"bigblue": game.createBigBlue,
"flag": game.createFlag,
};
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) {
const entity = entities[id];
if (entity.hasComponent("alive") && entity.hasComponent("name") && entity.components.name.selector == entityName) {
changedEntityIds.push(id);
const component = verbActionsToComponent[verb];
if (component) {
if (direction == "apply") {
if (verb == "you") {
if (!previousControllableIds.has(id)) {
const newYouParticleSpawner = game.createBorderParticles({colors: ["#ffc0cb", "#ffb6c1", "#ffc1cc", "#ffbcd9", "#ff1493"], minAmount: 80, maxAmount: 150, maxSpeed: 0.5});
newYouParticleSpawner.addComponent(game.components.Position(entity.components.position));
newYouParticleSpawner.addComponent(game.components.Appearance({width: game.canvas.width / game.config.xDim, height: game.canvas.height / game.config.yDim}));
game.entities[newYouParticleSpawner.id] = newYouParticleSpawner;
}
}
entity.addComponent(component);
} else if (direction == "deapply") {
if (entity.hasComponent("controllable")) {
previousControllableIds.add(id);
}
entity.removeComponent(component.name);
}
}
}
}
if (direction == "apply" && changedEntityIds.some((id) => previousControllableIds.has(id))) {
previousControllableIds = new Set();
}
}
if (application.hasComponent("noun")) {
const applicationEntityName = application.components.noun.select;
for (let id in entities) {
const entity = entities[id];
if (entity.hasComponent("name") && entity.components.name.selector == entityName) {
const e = nounsToEntityCreators[applicationEntityName]();
entity.components.name = e.components.name;
entity.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 };
};
|