Implement clone machine!

This commit is contained in:
Eevee (Evelyn Woods) 2020-09-01 01:31:42 -06:00
parent 2b4450fc8c
commit eb2dd7a4a4
4 changed files with 72 additions and 6 deletions

View File

@ -485,6 +485,7 @@ export function parse_level(buf) {
if (! has_next) if (! has_next)
break; break;
} }
cell.reverse();
level.linear_cells.push(cell); level.linear_cells.push(cell);
} }
} }

View File

@ -180,7 +180,7 @@ function parse_level(buf) {
continue; continue;
} }
cell.push({name, direction}); cell.unshift({name, direction});
} }
} }
if (c !== 1024) if (c !== 1024)

View File

@ -231,6 +231,7 @@ class Level {
this.hint_shown = null; this.hint_shown = null;
let n = 0; let n = 0;
let connectables = [];
for (let y = 0; y < this.height; y++) { for (let y = 0; y < this.height; y++) {
let row = []; let row = [];
this.cells.push(row); this.cells.push(row);
@ -240,6 +241,7 @@ class Level {
let stored_cell = this.stored_level.linear_cells[n]; let stored_cell = this.stored_level.linear_cells[n];
n++; n++;
let has_cloner, has_forbidden;
for (let template_tile of stored_cell) { for (let template_tile of stored_cell) {
let tile = Tile.from_template(template_tile, x, y); let tile = Tile.from_template(template_tile, x, y);
@ -247,6 +249,11 @@ class Level {
// Copy over the tile-specific hint, if any // Copy over the tile-specific hint, if any
tile.specific_hint = template_tile.specific_hint ?? null; tile.specific_hint = template_tile.specific_hint ?? null;
} }
if (tile.type.name === 'cloner') {
has_cloner = true;
}
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 chip
@ -257,16 +264,50 @@ class Level {
this.actors[0] = tile; this.actors[0] = tile;
} }
else if (tile.type.is_actor) { else if (tile.type.is_actor) {
if (has_cloner) {
tile.stuck = true;
}
else {
this.actors.push(tile); this.actors.push(tile);
} }
}
cell.push(tile); cell.push(tile);
if (tile.type.connects_to) {
connectables.push(tile);
} }
// Make the bottom tile be /first/
cell.reverse();
} }
} }
} }
// Connect buttons and teleporters
let num_cells = this.width * this.height;
for (let connectable of connectables) {
let x = connectable.x;
let y = connectable.y;
let goal = connectable.type.connects_to;
let found = false;
for (let i = 0; i < num_cells - 1; i++) {
x++;
while (x >= this.width) {
x -= this.width;
y++;
y %= this.width;
}
for (let tile of this.cells[y][x]) {
if (tile.type.name === goal) {
// TODO should be weak, but you can't destroy cloners so in practice not a concern
connectable.connection = tile;
found = true;
}
}
if (found)
break;
}
// TODO soft warn for e.g. a button with no cloner? (or a cloner with no button?)
}
}
advance_tic(player_direction) { advance_tic(player_direction) {
if (this.state !== 'playing') { if (this.state !== 'playing') {
console.warn(`Level.advance_tic() called when state is ${this.state}`); console.warn(`Level.advance_tic() called when state is ${this.state}`);
@ -284,6 +325,9 @@ class Level {
if (actor.movement_cooldown > 0) if (actor.movement_cooldown > 0)
continue; continue;
} }
// XXX does the cooldown drop while in a trap? is this even right?
if (actor.stuck)
continue;
let direction_preference; let direction_preference;
// Actors can't make voluntary moves on ice, so they're stuck with // Actors can't make voluntary moves on ice, so they're stuck with

View File

@ -278,8 +278,23 @@ const TILE_TYPES = {
blocks: true, blocks: true,
}, },
cloner: { cloner: {
// TODO ???
blocks: true, blocks: true,
activate(me, level) {
let cell = level.cells[me.y][me.x];
// Clone so we don't end up repeatedly cloning the same object
let current_tiles = Array.from(cell);
for (let tile of current_tiles) {
if (tile !== me && tile.type.is_actor) {
tile.stuck = false;
// TODO precise behavior? is this added immediately and can move later that same turn or what?
level.actors.push(tile);
// FIXME rearrange to make this possible lol
// FIXME go through level for this, and everything else of course
// FIXME add this underneath, just above the cloner
cell._add(new tile.constructor(tile.type, tile.x, tile.y, tile.direction));
}
}
}
}, },
trap: { trap: {
// TODO ??? // TODO ???
@ -326,7 +341,13 @@ const TILE_TYPES = {
// TODO how do i implement this. // TODO how do i implement this.
}, },
button_red: { button_red: {
// TODO connects_to: 'cloner',
connect_order: 'forward',
on_arrive(me, level, other) {
if (me.connection && ! me.connection.doomed) {
me.connection.type.activate(me.connection, level);
}
}
}, },
// Critters // Critters