Iterate actors in reverse order to match Lynx/CC2 (fixes #7)

This commit is contained in:
Eevee (Evelyn Woods) 2020-10-21 21:24:59 -06:00
parent 8073604271
commit 09eb03dad6
3 changed files with 19 additions and 13 deletions

View File

@ -253,22 +253,18 @@ export class Level {
if (tile.type.is_player) { if (tile.type.is_player) {
// TODO handle multiple players, also chip and melinda both // TODO handle multiple players, also chip and melinda both
// TODO complain if no chip // TODO complain if no player
this.player = tile; 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) { if (has_cloner) {
// TODO is there any reason not to add clone templates to the actor // TODO is there any reason not to add clone templates to the actor
// list? // list?
tile.stuck = true; tile.stuck = true;
} }
else { }
this.actors.push(tile); if (! tile.stuck) {
} this.actors.push(tile);
} }
cell._add(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 // immediately), we still want every time's animation to finish, or it'll look like some
// objects move backwards when the death screen appears! // objects move backwards when the death screen appears!
let cell_steppers = []; 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 // Actors with no cell were destroyed
if (! actor.cell) if (! actor.cell)
continue; continue;
@ -423,7 +425,8 @@ export class Level {
} }
// Second pass: actors decide their upcoming movement simultaneously // 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) if (! actor.cell)
continue; continue;
@ -592,7 +595,8 @@ export class Level {
} }
// Third pass: everyone actually moves // 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) if (! actor.cell)
continue; continue;

View File

@ -1349,6 +1349,7 @@ class Splash extends PrimaryView {
continue; continue;
let ext = m[1]; let ext = m[1];
// TODO this can't load an individual c2m, hmmm
if (ext === 'c2g' || ext === 'dat' || ext === 'ccl') { if (ext === 'c2g' || ext === 'dat' || ext === 'ccl') {
let buf = await source.get(path); let buf = await source.get(path);
await this.conductor.parse_and_load_game(buf, source, path); await this.conductor.parse_and_load_game(buf, source, path);

View File

@ -882,7 +882,8 @@ const TILE_TYPES = {
level.sfx.play_once('button-press', me.cell); level.sfx.play_once('button-press', me.cell);
// Move all yellow tanks one tile in the direction of the pressing actor // 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?? // TODO generify somehow??
if (actor.type.name === 'tank_yellow') { if (actor.type.name === 'tank_yellow') {
level.attempt_step(actor, other.direction); level.attempt_step(actor, other.direction);