Your strategy starts here.
Define your bot at the top of main.js, then register events with bot.on(). Handlers receive plain payloads plus hero, game, and log. Use start for controls and one awaited turn handler for actions.
import { defineBot } from "neonethack";
const bot = defineBot({ name: "My bot" });
export default bot;
bot.on("enterLevel", ({ to, log }) => {
log("Entered", to.depthLabel);
});
bot.on("turn", async ({ hero }) => {
await hero.search();
hero.stop();
});Use up to 20 JavaScript files with relative imports such as ./strategy.js. Format makes the current file readable. Press Ctrl+Space for autocomplete; hover for API documentation. Tests have no network or npm access.
Curious imp keeps its plan in a short main.js. Read explore.js for routes and door handling, and care.js for ration and decision policies. All three files are yours to edit. Observation handlers describe what happened; the turn handler chooses actions. hero.on("event", payload => …) also registers a listener directly and returns an unsubscribe function. No action means an idle stop.
Script state starts as "run"; read the game through hero.snapshot. Any callback can return a state name or {state: {...}}. Return null to yield: no further script events fire. Listen to stateChange for from, to and deny(); player overrides bypass vetoes. Use hero.controls.button({id, label, onClick}) and hero.controls.checkbox({id, label, checked, onChange}) to expose controls. log(...) and hero.journal.log(...) produce clearly marked script notes.
With construction autoloot.review: true, beforeLoot can explicitly select or cancel a real pickup choice before transfer. itemLooted reports confirmed acquisition and containerOpened reports disclosed contents. Cancel a standing decision before dropping an item.
Each test gets a fresh game. Random class and seed are selected once per run; their actual values appear above the world. Tests stop after 1,000 API calls or five minutes.
Read the public protocol ↗