From 09eb03dad6e05258d578fb14efa4dd7d72559fe5 Mon Sep 17 00:00:00 2001 From: "Eevee (Evelyn Woods)" Date: Wed, 21 Oct 2020 21:24:59 -0600 Subject: [PATCH] Iterate actors in reverse order to match Lynx/CC2 (fixes #7) --- js/game.js | 28 ++++++++++++++++------------ js/main.js | 1 + js/tiletypes.js | 3 ++- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/js/game.js b/js/game.js index 38194cd..c7f4ea3 100644 --- a/js/game.js +++ b/js/game.js @@ -253,22 +253,18 @@ export class Level { if (tile.type.is_player) { // TODO handle multiple players, also chip and melinda both - // TODO complain if no chip + // TODO complain if no player this.player = tile; - // Always put the player at the start of the actor list - // (accomplished traditionally with a swap) - this.actors.push(this.actors[0]); - this.actors[0] = tile; } - else if (tile.type.is_actor) { + if (tile.type.is_actor) { if (has_cloner) { // TODO is there any reason not to add clone templates to the actor // list? tile.stuck = true; } - else { - this.actors.push(tile); - } + } + if (! tile.stuck) { + this.actors.push(tile); } cell._add(tile); @@ -373,7 +369,13 @@ export class Level { // immediately), we still want every time's animation to finish, or it'll look like some // objects move backwards when the death screen appears! let cell_steppers = []; - for (let actor of this.actors) { + // Note that we iterate in reverse order, DESPITE keeping dead actors around with null + // cells, to match the Lynx and CC2 behavior. This is actually important in some cases; + // check out the start of CCLP3 #54, where the gliders will eat the blue key immediately if + // they act in forward order! (More subtly, even the earlier passes do things like advance + // the RNG, so for replay compatibility they need to be in reverse order too.) + for (let i = this.actors.length - 1; i >= 0; i--) { + let actor = this.actors[i]; // Actors with no cell were destroyed if (! actor.cell) continue; @@ -423,7 +425,8 @@ export class Level { } // Second pass: actors decide their upcoming movement simultaneously - for (let actor of this.actors) { + for (let i = this.actors.length - 1; i >= 0; i--) { + let actor = this.actors[i]; if (! actor.cell) continue; @@ -592,7 +595,8 @@ export class Level { } // Third pass: everyone actually moves - for (let actor of this.actors) { + for (let i = this.actors.length - 1; i >= 0; i--) { + let actor = this.actors[i]; if (! actor.cell) continue; diff --git a/js/main.js b/js/main.js index 81d53a6..819d01a 100644 --- a/js/main.js +++ b/js/main.js @@ -1349,6 +1349,7 @@ class Splash extends PrimaryView { continue; let ext = m[1]; + // TODO this can't load an individual c2m, hmmm if (ext === 'c2g' || ext === 'dat' || ext === 'ccl') { let buf = await source.get(path); await this.conductor.parse_and_load_game(buf, source, path); diff --git a/js/tiletypes.js b/js/tiletypes.js index 719c8a3..3e55c8b 100644 --- a/js/tiletypes.js +++ b/js/tiletypes.js @@ -882,7 +882,8 @@ const TILE_TYPES = { level.sfx.play_once('button-press', me.cell); // Move all yellow tanks one tile in the direction of the pressing actor - for (let actor of level.actors) { + for (let i = level.actors.length - 1; i >= 0; i--) { + let actor = level.actors[i]; // TODO generify somehow?? if (actor.type.name === 'tank_yellow') { level.attempt_step(actor, other.direction);