|  | dirs = {
  "up-left": "Northwest",
  "up": "North",
  "up-right": "Northeast",
  "left": "West",
  "right": "East",
  "down-left": "Southwest",
  "down": "South",
  "down-right": "Southeast",
  "ascend": "Up",
  "descend": "Down"
}
function initWorld(story, state) {
  state.world = story["world"];
  initRoomState(state);
}
function initRoomState(state) {
  state.player.rooms = {};
  Object.entries(state.world).forEach(([key, val]) => {
    state.player.rooms[key] = {};
  });
}
function showActionDescription(desc) {
  const descHolder = document.querySelector("#desc");
  descHolder.textContent = desc;
}
function removeActionDescription() {
  const descHolder = document.querySelector("#desc");
  descHolder.textContent = "";
}
function moveToRoom(src, exit, dest, state) {
  const from = state.world[state.player.location];
  const room = state.world[dest];
  if (exit.hooks) {
    for (let hook of exit.hooks) {
      if (!hook(room, exit, state)) {
        return;
      }
    }
  }
  if (room.hooks) {
    for (let hook of room.hooks) {
      if (!hook(room, state)) {
        return;
      }
    }
  }
  if (exit.move)
    exit.move(from, state);
  if (from && from.exit)
    from.exit(from, state);
  if (room.move)
    room.move(room, state);
  if (room.enter)
    room.enter(room, state);
  state.player.location = dest;
  refresh();
}
function goToRoom(dest, state) {
  const from = state.world[state.player.location];
  const room = state.world[dest];
  if (room.hooks) {
    for (let hook of room.hooks) {
      if (!hook(room, state)) {
        return;
      }
    }
  }
  if (from && from.exit)
    from.exit(state.world[dest], state);
  if (room.enter)
    room.enter(state.world[dest], state);
  state.player.location = dest;
  refresh();
}
function updateRoom(state) {
  const name = state.player.location;
  const room = state.world[name];
  if (!state.player.rooms[room.id]) {
    state.player.rooms[room.id] = {};
  }
  const areaName = document.querySelector("#area-name");
  const areaDesc = document.querySelector("#area-desc");
  areaName.textContent = room.name;
  areaDesc.textContent = room.desc;
  const moveHolder = document.querySelector("#move-holder");
  moveHolder.innerHTML = "";
  Object.entries(dirs).forEach(([dir, name]) => {
    const button = document.createElement("button");
    button.classList.add("move-button")
    button.id = "move-" + dir;
    button.classList.add("disabled");
    button.setAttribute("disabled", "true");
    button.textContent = dirs[dir];
    moveHolder.appendChild(button);
  });
  if (room.exits) {
    Object.entries(room.exits).forEach(([dir, exit]) => {
      const button = document.querySelector("#move-" + dir);
      const dest = state.world[exit.target];
      // don't even show an exit if this fails!
      if (exit.show) {
        if (!exit.show.every(cond => cond(room, state))) {
          return;
        }
      }
      button.textContent = dest.name;
      // if any condition fails, don't enable/add a listener
      if (exit.conditions) {
        if (!exit.conditions.every(cond => cond(room,state))) {
          return;
        }
      }
      button.classList.remove("disabled");
      button.removeAttribute("disabled");
      button.addEventListener("click", () => {
        // todo: log
        moveToRoom(room, exit, exit.target, state);
      })
      button.addEventListener("mouseenter", () => {
        showActionDescription(exit.desc);
      });
      button.addEventListener("mouseleave", () => {
        removeActionDescription();
      });
    });
  }
  const actionHolder = document.querySelector("#actions");
  actionHolder.innerHTML = "";
  if (room.actions) {
    room.actions.forEach(action => {
      const button = document.createElement("button");
      button.classList.add("action-button");
      if (action.show) {
        if (!action.show.every(cond => cond(room, state))) {
          return;
        }
      }
      button.textContent = action.name;
      actionHolder.appendChild(button);
      if (action.conditions) {
        if (!action.conditions.every(cond => cond(room, state))) {
          button.classList.add("disabled");
          button.setAttribute("disabled", "true");
          return;
        }
      }
      button.addEventListener("click", () => {
        action.execute(room, state);
        refresh();
      });
      button.addEventListener("mouseenter", () => {
        showActionDescription(action.desc);
      });
      button.addEventListener("mouseleave", () => {
        removeActionDescription();
      });
    });
  }
}
 |