|  | stories = [];
function initGame(story) {
  state.info = {};
  state.info.time = {
    id: "time",
    name: "Time",
    type: "counter",
    value: 60*60*9,
    get render() {
      return renderTime(this.value);
    }
  }
  state.player.stats = {};
  state.timers = [];
}
function createStatDisplays(stats, statType) {
  const holder = document.querySelector("#" + statType + "-info");
  holder.innerHTML = "";
  Object.entries(stats).forEach(([key, val]) => {
    if (val.type == "meter") {
      const field = document.createElement("div");
      field.id = statType + "-info-" + key;
      field.setAttribute("max", val.max);
      field.setAttribute("value", val.value);
      field.classList.add("stat-bar-holder");
      const label = document.createElement("div");
      label.classList.add("stat-bar-label");
      label.textContent = val.name;
      const bar = document.createElement("div");
      bar.classList.add("stat-bar");
      bar.style["background-color"] = val.color;
      field.appendChild(label);
      field.appendChild(bar);
      holder.appendChild(field);
    } else if (val.type == "counter") {
      const field = document.createElement("div");
      field.id = statType + "-info-" + key;
      holder.appendChild(field);
    }
  });
}
function initGamePostSetup() {
  createStatDisplays(state.info, "world");
  createStatDisplays(state.player.stats, "player");
}
function getStat(stat) {
  return state.player.stats[stat].value;
}
function changeStat(stat, amount) {
  let value = state.player.stats[stat].value;
  value += amount;
  value = Math.max(value, state.player.stats[stat].min);
  value = Math.min(value, state.player.stats[stat].max);
  state.player.stats[stat].value = value;
}
// TODO: format string this lol
function renderTime(time) {
  let hours = Math.floor(time / 3600) % 12;
  const ampm = Math.floor(time / 3600) % 24 < 12 ? "AM" : "PM";
  let minutes = Math.floor(time / 60) % 60;
  let seconds = time % 60;
  if (minutes <= 9)
    minutes = "0" + minutes;
  if (seconds <= 9)
    seconds = "0" + seconds;
  return hours + ":" + minutes + ":" + seconds + " " + ampm;
}
function updateStatDisplay(stats, statType) {
  Object.entries(stats).forEach(([key, val]) => {
    
    if (val.hidden === true) {
      const field = document.querySelector("#" + statType + "-info-" + key);
      field.style.display = "none";
    } else {
      const field = document.querySelector("#" + statType + "-info-" + key);
      field.style.display = "block";
      if (val.type == "meter") {
        const bar = document.querySelector("#" + statType + "-info-" + key + " > .stat-bar");
        bar.style["background-color"] = val.color;
      }
    }
    if (val.type == "meter") {
      const field = document.querySelector("#" + statType + "-info-" + key + " > .stat-bar");
      field.style.width = (val.value / val.max * 100) + "%";
    } else if (val.type == "counter") {
      const field = document.querySelector("#" + statType + "-info-" + key);
      field.innerText = val.name + ": " + (val.render !== undefined ? val.render : val.value);
    }
  });
}
/*
{
  id: an optional name; needed to manually kill a timer
  func: the function to invoke
  delay: how long to wait between invocations
  loop: false = no looping, true = loop forever
}
Returns the timeout id - but you still need to cancel it through stopTimer!
*/
function startTimer(config) {
  const timeout = setTimeout(() => {
    const result = config.func(config);
    refresh();
    // the timer may have terminated itself!
    // we have to make sure it still exists
    if (state.timers.some(x => x.timeout == timeout)){
      state.timers = state.timers.filter(x => x.timeout != timeout);
      if (typeof(result) === "number") {
        config.delay = result;
      }
      // you shouldn't use a delay of 0 anyway
      if (result && config.loop) {
        startTimer(config);
      }
    }
  }, config.delay);
  
  state.timers.push({id: config.id, timeout: timeout, classes: config.classes || []});
  return timeout;
}
function stopTimer(id) {
  const matches = state.timers.filter(timer => timer.id == id);
  matches.forEach(timer => clearTimeout(timer.timeout));
  state.timers = state.timers.filter(timer => timer.id != id);
}
function stopClassTimers(timerClass, inverse) {
  const matches = state.timers.filter(timer => timer.classes.includes(timerClass));
  const others = state.timers.filter(timer => !timer.classes.includes(timerClass));
  if (inverse) {
    others.forEach(timer => clearTimeout(timer.timeout));
    state.timers = matches;
  } else {
    matches.forEach(timer => clearTimeout(timer.timeout));
    state.timers = others;
  }
}
function stopAllTimers() {
  state.timers.forEach(x => clearTimeout(x.timeout));
  state.timers = [];
}
function setBackgroundColor(r, g, b) {
  document.querySelector(".scene").style["background-color"] = "rgb(" + r + "," + g + "," + b + ")";
}
 |