-
Notifications
You must be signed in to change notification settings - Fork 0
/
kill-helpers.ts
111 lines (98 loc) · 3.9 KB
/
kill-helpers.ts
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
import { produce } from "../util/produce";
import { Point } from "../util/types";
import { vequal } from "../util/vutil";
import { Animation } from "./animation-types";
import { mkExplosionAnimation } from './animations';
import { getBonusFromLayer, updateBonusLayer } from "./bonus-helpers";
import { WidgetPoint, locationOfWidgetPoint } from "./core-ui-types";
import { KillIntent, killableBonus } from './intent-types';
import { deselect } from "./selection-helpers";
import { CoreState } from "./state";
import { checkValid } from './state-helpers';
import { Location, MobileEntity } from './state-types';
import { get_hand_tiles, get_mobiles, removeMobile } from "./tile-helpers";
import { BOMB_RADIUS } from './tools';
function eligibleKillIntent(state: CoreState, intent: KillIntent): boolean {
switch (intent.t) {
case 'kill': return state.slowState.inventory.dynamites >= 1;
case 'bomb': return state.slowState.inventory.bombs >= 1;
case 'fillWater': return true;
}
}
function spendKillIntent(state: CoreState, intent: KillIntent): CoreState {
switch (intent.t) {
case 'kill': return produce(state, s => { s.slowState.inventory.dynamites--; });
case 'bomb': return produce(state, s => { s.slowState.inventory.bombs--; });
case 'fillWater': return state;
}
}
export function tryKillTileOfStateLoc(state: CoreState, loc: Location, intent: KillIntent): CoreState {
if (!eligibleKillIntent(state, intent))
return state;
return killTileOfStateLoc(state, loc, intent);
}
export function tryKillTileOfState(state: CoreState, wp: WidgetPoint, intent: KillIntent): CoreState {
if (!eligibleKillIntent(state, intent))
return state;
return killTileOfState(state, wp, intent);
}
function splashDamage(center: Point, radius: number): Point[] {
if (radius == 0)
return [center];
const pts: Point[] = [];
for (let x = -radius; x <= radius; x++) {
for (let y = -radius; y <= radius; y++) {
pts.push({ x: center.x + x, y: center.y + y });
}
}
return pts;
}
function killTileOfState(state: CoreState, wp: WidgetPoint, intent: KillIntent): CoreState {
return killTileOfStateLoc(state, locationOfWidgetPoint(wp), intent);
}
function killTileOfStateLoc(state: CoreState, loc: Location, intent: KillIntent): CoreState {
const radius = intent.t == 'bomb' ? BOMB_RADIUS : intent.t == 'fillWater' ? 0 : intent.radius;
// Definitely want to clear the selection, because invariants get
// violated if a tileId gets deleted but remains in the selection
state = deselect(state);
switch (loc.t) {
case 'world': {
const p_in_world_int = loc.p_in_world_int;
const anim: Animation = mkExplosionAnimation(p_in_world_int, radius, state.game_from_clock);
function mobileAt(p: Point): MobileEntity | undefined {
return get_mobiles(state).find(mobile => mobile.loc.t == 'world' && vequal(mobile.loc.p_in_world_int, p));
}
const tilesToDestroy: Point[] = splashDamage(p_in_world_int, radius);
// remove all tiles in radius
tilesToDestroy.forEach(p => {
const tileAtP = mobileAt(p);
if (tileAtP !== undefined)
state = removeMobile(state, tileAtP.id);
});
// remove all killable bonuses in radius
tilesToDestroy.forEach(p => {
if (killableBonus(intent, getBonusFromLayer(state, p))) {
state = updateBonusLayer(state, p, { t: 'empty' });
}
});
return checkValid(produce(spendKillIntent(state, intent), s => {
s.animations.push(anim);
}));
}
case 'hand': {
const index = loc.index;
const hand_tiles = get_hand_tiles(state);
if (index >= 0 && index < hand_tiles.length) {
const tile = hand_tiles[index];
if (tile == undefined)
return state;
return checkValid(spendKillIntent(removeMobile(state, tile.id), intent));
}
else {
return state;
}
}
case 'nowhere':
return state;
}
}