-
Notifications
You must be signed in to change notification settings - Fork 3
/
Simulate.hx
335 lines (294 loc) · 9.1 KB
/
Simulate.hx
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
import World;
import Jump;
import flash.display.Sprite;
import flash.display.Bitmap;
typedef StepResult = {
var world: World_t;
var badger_died: Bool;
var badger_on_floor: Bool;
}
class Simulate {
/*
btw:
theme from time badger
2x Gm C Gm D7
2x Bm7 Em Bm7 Amaj 9
*/
public static function get(w : World_t, x : Int, y : Int) : Tile {
if (x < 0 || x >= World.tilesw || y < 0 || y >= World.tilesh) {
return World.allTiles[World.WALL];
}
return w[y * World.tilesw + x];
}
public static function set(w : World_t, x : Int, y : Int, t : Tile) {
if (x < 0 || x >= World.tilesw || y < 0 || y >= World.tilesh) {
trace('OOB ASSHOLE');
} else {
w[y * World.tilesw + x] = t;
}
}
// If you are stepped on, then you are dead.
public static function steppedOn(w : World_t, x : Int, y : Int) {
var t = get(w, x, y - 1);
return t.style.prop.isbadger || t.style.prop.isturtle;
}
public static function solidThere(oldworld : World_t,
newworld : World_t,
x : Int, y : Int) {
return get(oldworld, x, y).style.prop.solid ||
get(newworld, x, y).style.prop.solid;
}
public static function standingOnfloor(oldworld : World_t,
newworld : World_t,
x : Int, y : Int) {
return get(oldworld, x, y).style.prop.standon &&
get(newworld, x, y).style.prop.standon;
}
public static function clearThere(oldworld : World_t,
newworld : World_t,
x : Int, y : Int) {
return get(oldworld, x, y).style.id == World.NOTHING &&
get(newworld, x, y).style.id == World.NOTHING;
}
// Compute the next world state from the current one.
// When you read this code you will realize that I did not
// think it through very well before starting, hehe! - tom7
public static function step(w : World_t) : World_t {
// XXX should be same size as w; allegedly this allocates
// as fields are accessed.
var newworld = new Array<Tile>();
// trace('make step!');
for (y in 0...World.tilesh) {
for (x in 0...World.tilesw) {
newworld.push(World.allTiles[World.NOTHING]);
}
}
// Pass 1: Copy all the solid stuff, walk turtles, fall turtles and rocks.
for (y in 0...World.tilesh) {
for (x in 0...World.tilesw) {
var thistile = get(w, x, y);
if (thistile == null) {
trace('null ASSHOLE2');
}
switch (thistile.style.id) {
case 0x0000: // NOTHING
// Don't do anything, because we don't want to overwrite
// new material that moved into this spot.
case 0x000a: // MOVEDOWN
if (solidThere(w, newworld, x, y + 1)) {
// Blocked; flip in place.
set(newworld, x, y, World.allTiles[World.MOVEUP]);
} else {
set(newworld, x, y + 1, thistile);
set(newworld, x, y, World.allTiles[World.NOTHING]);
}
case 0x000b: // MOVELEFT
if (solidThere(w, newworld, x - 1, y)) {
// Blocked; flip in place.
set(newworld, x, y, World.allTiles[World.MOVERIGHT]);
} else {
set(newworld, x - 1, y, thistile);
set(newworld, x, y, World.allTiles[World.NOTHING]);
}
case 0x000c: // MOVERIGHT
if (solidThere(w, newworld, x + 1, y)) {
// Blocked; flip in place.
set(newworld, x, y, World.allTiles[World.MOVELEFT]);
} else {
set(newworld, x + 1, y, thistile);
set(newworld, x, y, World.allTiles[World.NOTHING]);
}
case 0x000d: // MOVEUP
if (solidThere(w, newworld, x, y - 1)) {
// Blocked; flip in place.
set(newworld, x, y, World.allTiles[World.MOVEDOWN]);
} else {
set(newworld, x, y - 1, thistile);
set(newworld, x, y, World.allTiles[World.NOTHING]);
}
case 0x0001: // TURTLE L
var xx : Int, yy : Int, deadtile : Int;
// XXX allow walking into badger -- but in the future or now??
if (!solidThere(w, newworld, x - 1, y)) {
// Might kill badger!
set(newworld, x - 1, y, thistile);
set(newworld, x, y, World.allTiles[World.NOTHING]);
xx = x - 1;
yy = y;
deadtile = World.TURTLELDEAD;
} else {
// Flip in place.
set(newworld, x, y, World.allTiles[World.TURTLER]);
xx = x;
yy = y;
deadtile = World.TURTLERDEAD;
}
// Fall too?
/*
if (clearThere(w, newworld, xx, yy + 1)) {
set(newworld, xx, yy, World.allTiles[World.NOTHING]);
yy++;
set(newworld, xx, yy, thistile);
}
if (steppedOn(newworld, xx, yy)) {
set(newworld, xx, yy, World.allTiles[deadtile]);
Achievements.got('killturt');
}
*/
case 0x0002: // TURTLE R
var xx : Int, yy : Int, deadtile : Int;
if (!solidThere(w, newworld, x + 1, y)) {
// Might kill badger!
set(newworld, x + 1, y, thistile);
set(newworld, x, y, World.allTiles[World.NOTHING]);
xx = x + 1;
yy = y;
deadtile = World.TURTLERDEAD;
} else {
// Flip in place.
set(newworld, x, y, World.allTiles[World.TURTLEL]);
xx = x;
yy = y;
deadtile = World.TURTLELDEAD;
}
// Fall too?
/*
if (clearThere(w, newworld, xx, yy + 1)) {
set(newworld, xx, yy, World.allTiles[World.NOTHING]);
yy = yy + 1;
set(newworld, xx, yy, thistile);
}
if (steppedOn(newworld, xx, yy)) {
set(newworld, xx, yy, World.allTiles[deadtile]);
Achievements.got('killturt');
}
*/
case 0x0037: // Rock
var xx : Int = x;
var yy : Int = y;
if (clearThere(w, newworld, xx, yy + 1)) {
set(newworld, xx, yy, World.allTiles[World.NOTHING]);
yy = yy + 1;
set(newworld, xx, yy, thistile);
} else {
// stays.
set(newworld, xx, yy, thistile);
}
case 0x0035: // Dead turtles
set(newworld, x, y, World.allTiles[World.NOTHING]);
case 0x0036: // Dead turtles
set(newworld, x, y, World.allTiles[World.NOTHING]);
default:
set(newworld, x, y, thistile);
}
}
}
// Pass 2: Fall things that fall.
for (yinv in 0...World.tilesh) {
// Go upward so we don't keep falling something with each
// successive row...
var y = World.tilesh - yinv - 1;
for (x in 0...World.tilesw) {
var thistile = get(newworld, x, y);
if (thistile.style.prop.falls) {
// You keep falling?
if (clearThere(newworld, newworld, x, y + 1)) {
set(newworld, x, y, World.allTiles[World.NOTHING]);
set(newworld, x, y + 1, thistile);
}
}
}
}
// Pass 3: Conveyors move material.
var just_conveyed = false; // hehe I am pro hacker
for (y in 0...World.tilesh) {
for (x in 0...World.tilesw) {
var thistile = get(newworld, x, y);
if (thistile.style.id == World.CONVEYORL) {
just_conveyed = false;
// Is the thing atop me conveyed?
var above = get(newworld, x, y - 1);
if (above.style.prop.conveyed) {
if (clearThere(newworld, newworld, x - 1, y - 1)) {
set(newworld, x, y - 1, World.allTiles[World.NOTHING]);
set(newworld, x - 1, y - 1, above);
}
}
} else if (thistile.style.id == World.CONVEYORR) {
// Is the thing atop me conveyed?
var above = get(newworld, x, y - 1);
if (above.style.prop.conveyed && !just_conveyed) {
if (clearThere(newworld, newworld, x + 1, y - 1)) {
set(newworld, x, y - 1, World.allTiles[World.NOTHING]);
set(newworld, x + 1, y - 1, above);
just_conveyed = true;
} else {
just_conveyed = false;
}
} else {
just_conveyed = false;
}
} else {
just_conveyed = false;
}
}
}
// Pass 4: Kill shit that is dead.
for (yinv in 0...World.tilesh) {
// Go upward so a whole stack of turtles kills all of
// them but the top.
var y = World.tilesh - yinv - 1;
for (x in 0...World.tilesw) {
var thistile = get(newworld, x, y);
if (thistile.style.prop.nostep) {
if (steppedOn(newworld, x, y)) {
if (thistile.style.prop.isturtle) {
Achievements.got('killturt');
} else if (thistile.style.id == World.GWILLEN) {
Achievements.got('killgwill');
}
set(newworld, x, y, World.allTiles[World.deathTile(thistile.style.id)]);
}
}
}
}
// XXX DEATHS!
trace('return: ' + newworld.length);
return newworld;
}
/* where can we jump if we start at {x,y} ?
*/
public static function validJumps(w0: World_t, w1: World_t, x: Int, y: Int) : Array< Coor>{
var r: Array<Coor> = new Array<Coor>();
for(j in Jump.jmps){
if(Jump.canJump(j, w0, w1, x,y)){
r.push({x:x, y:y});
}
}
return r;
}
static function drawMove(mv: Coor){
var s = new Sprite();
s.x = mv.x * World.tilesize + World.tilesize / 2;
s.y = mv.y * World.tilesize + World.tilesize / 2;
s.graphics.beginFill(0x0000FF);
s.graphics.drawCircle(0,0,7);
s.graphics.endFill();
s.visible= true;
s.alpha = 0.5;
Game.mainmc.addChild(s);
}
public static function drawMoves(mvs: Array<Coor>) {
for(mv in mvs){
drawMove(mv);
}
}
// Draw an array of moves |mvs| which are relative to the player's position |x,y|.
public static function drawMovesRel(player_x:Int, player_y:Int, mvs:Array<Coor>) {
var newmvs = Utils.map(function(c) {
return {x : c.x + player_x, y : c.y + player_y};
},
mvs);
drawMoves(newmvs);
}
}