import { Registry } from "./registry.js";
import { ON } from "./state.js";
/**
* Utility helpers for terrain manipulation.
* Mirrors TerrainUtils.java.
*/
export const TerrainUtils = {
/**
* Remove a decorator from every cell on the board where it appears,
* replacing it with the decorator's proxied (wrapped) terrain.
*
* Used by TriggerOnce and similar one-shot decorators.
*
* @param {GameEvent} event
* @param {Terrain} terrain the decorator instance to remove
*/
removeDecorator(event, terrain) {
event.board.visit((cell) => {
if (cell.terrain === terrain) {
// terrain is a Decorator — replace it with the proxied terrain
cell.setTerrain(terrain.getProxiedTerrain());
}
return false; // keep visiting
});
},
/**
* Toggle the state of the terrain in `cell` (ON→OFF or OFF→ON).
* Does nothing if an agent occupies the cell.
*
* @param {Cell} cell
* @param {Terrain} terrain
* @param {State} state current state of the terrain
*/
toggleCellState(cell, terrain, state) {
if (cell.agent == null) {
const other = this.getTerrainOtherState(terrain, state);
cell.setTerrain(other);
}
},
/**
* Return the same terrain type but with its state toggled (ON↔OFF).
* Works by manipulating the Registry serialization key: replaces the
* word "on" with "off" (or vice-versa) then looks up the new key.
*
* @param {Terrain} terrain
* @param {State} state current state
* @returns {Terrain}
*/
getTerrainOtherState(terrain, state) {
let key = Registry.serialize(terrain);
if (state.isOn()) {
key = key.replace(/\bon\b/g, "off");
} else {
key = key.replace(/\boff\b/g, "on");
}
return Registry.get(key);
},
/**
* Return the cell on the opposite side of the board from `cell`
* when traveling in `direction`. Used by rolling-boulder wrap-around.
*
* @param {Cell} cell
* @param {Direction} direction
* @returns {Cell|null}
*/
getCellOnOppositeSide(cell, direction) {
const { ROWS, COLUMNS } = /** @type {any} */ (cell.board);
if (cell.y === 0 || cell.y === ROWS - 1) {
if (direction.isNortherly()) {
return cell.board.getCellAt(cell.x, ROWS - 1);
} else if (direction.isSoutherly()) {
return cell.board.getCellAt(cell.x, 0);
} else if (direction.isEasterly()) {
return cell.board.getCellAt(0, cell.y);
} else if (direction.isWesterly()) {
return cell.board.getCellAt(COLUMNS - 1, cell.y);
}
} else {
if (direction.isEasterly()) {
return cell.board.getCellAt(0, cell.y);
} else if (direction.isWesterly()) {
return cell.board.getCellAt(COLUMNS - 1, cell.y);
} else if (direction.isNortherly()) {
return cell.board.getCellAt(cell.x, ROWS - 1);
} else if (direction.isSoutherly()) {
return cell.board.getCellAt(cell.x, 0);
}
}
return null;
},
};