<!-- SOLID CITY · part 2069 -->
unction () {
    var opts = HY.pois.filter(function (o) { return !/^(sable|fallen|sanctuary)$/.test(o.id) && Math.hypot(o.x - S.p.x, o.z - S.p.z) > 40; });
    return walkTo(pickOne(opts), null, rnd(8, 18));
  },
  citizen: function () {
    if (!window.CityCitizens) return false;
    var cs = CityCitizens.state().filter(function (c) { return c.st !== 'fly' && c.id !== 'sable' && Math.hypot(c.x - S.p.x, c.z - S.p.z) > 15 && Math.hypot(c.x, c.z) < 780; });
    if (!cs.length) return false;
    var c = CityCitizens.get(pickOne(cs).id); if (!c) return false;
    st.goal = 'visiting ' + c.name; st.status = st.goal; CityCitizens.goTo(c, false); st.next = Date.now() + 4000; return true;
  },
  sit: function () {
    var p = Math.random() < 0.5 ? (poi('sanctuary') || poi('fallen')) : (poi('fallen') || poi('sanctuary'));
    return walkTo(p, p ? 'walking to sit a while at ' + p.name : '', rnd(25, 45), 'sitting a while at ');
  },
  hop: function () { if (!window.CityWatch) return false; addHop(); st.goal = 'a short hop over the city'; st.status = 'flying a city hop'; CityWatch.start('hop', 'Hyper Controller'); return true; },
  watch: function () { if (!window.CityWatch) return false; var k = pickOne(['grand', 'volcano', 'island']); st.goal = 'Watch tour: ' + ((CityWatch.routes[k] && CityWatch.routes[k].name) || k); st.status = st.goal; CityWatch.start(k, 'Hyper Controller'); return true; },
  tour: function () { st.goal = 'the guided walking tour'; st.status = st.goal; HY.cmd('tour'); return true; }
};
var WEIGHTS = [['district', 30], ['citizen', 22], ['sit', 16], ['hop', 12], ['tour', 8], ['watch', 6]];
function chooseAct() {
  var pool = WEIGHTS.filter(function (w) { return st.last.indexOf(w[0]) < 0; }), tot = 0, i;
  for (i = 0; i < pool.length; i++) tot += pool[i][1];
  var r = Math.random() * tot; for (i = 0; i < pool.length; i++) { r -= pool[i][1]; if (r <= 0) return pool[i][0]; }
  return 'district';
}
function aiDistrict() {   // allow-listed accounts only: an occasional AI pick (server rate-limited), local fallback
  var opts = HY.pois.filter(function (o) { return o.id !== 'sable'; }).map(function (o) { return { id: o.id, name: o.name }; });
  st.aiNext = Date.now() + 90000; st.status = 'thinking\u2026'; paint();
  return post('/api/city/hyper-auto/goal', { here: where().slice(0, 40), mode: 'walk', options: opts }).then(function (j) {
    if (!st.on || st.paused) return true;
    var p = j && j.ok && poi(j.id);
    if (!p) return false;
    if (j.say) HY.narrate('<b>' + esc(st.name) + ':</b> ' + esc(j.say), 6);
    return walkTo(p, null, rnd(8, 18));
  }).catch(function () { return false; });
}
function step() {
  if (S.mode === 'boarded') { var act = $('sc-act'); if (act && !act.hidden) { st.status = 'leaving the ship'; act.click(); } st.next = Date.now() + 1500; return; }
  if (S.mode !== 'walk') { st.next = Date.now() + 3000; return; }
  if (st.kind === 'account' && Date.now() > st.aiNext && Math.random() < 0.35) {
    st.next = Date.now() + 12000;
    aiDistrict().then(function (ok) { if (!ok && st.on && !st.paused) run(); else st.picks++; paint(); });
    return;
  }
  run();
}
function run() {
  var k = chooseAct(), ok = false;
  try { ok = ACTS[k](); } catch (e) { ok = false; }
  if (!ok) { k = 'district'; try { ok = ACTS.district(); } catch (e) {} }
  st.last.push(k); if (st.last.length > 2) st.last.shift();
  st.act = k; st.picks++; st.since = Date.now();
  if (Date.now() >= st.next) st.next = Date.now() + 4000;
  paint();
}
function tick() {
  if (!st.on) return;
  if (st.paused || document.hidden) { paint(); return; }
  // stuck watchdog: walking but not moving for 25 s -> stop and choose again
  var h = HY.state || {};
  if (h.nav && S.mode === 'walk') {
    if (Math.hypot(S.p.x - st.lx, S.p.z - st.lz) < 0.3) st.stillT += 1; else st.stillT = 0;
    st.lx = S.p.x; st.lz = S.p.z;
    if (st.stillT > 25) { st.stillT = 0; try { HY.stopAI(true); } catch (e) {} st.status = 'rerouting'; st.next = Date.now() + 1000; }
  } else st.stillT = 0;
  var W = window.CityWatch && CityWatch.state;
  if (S.mode === 'fly' && !(h.flyDrive) && !(W && W.state && W.state !== 'idle') && Date.now() > st.next) { st.status = 'flying home to land'; st.goal = st.status; HY.cmd('land'); st.next = Date.now() + 5000; paint(); return; }
  if (busy() || Date.now() < st.next) { paint(); return; }
  step(); paint();
}
function checkin() {
  if (st.kind !== 'account') return;
  var key = 'ha-checkin-' + st.name, lastC = 0; try { lastC = +localStorage.getItem(key) || 0; } catch (e) {}
  if (Date.now() - lastC < 30 * 60000) return;
  post('/api/city/hyper-auto/activate', {}).then(function (j) {
    if (!j || !j.checkin) return;
    try { localStorage.setItem(key, String(Date.now())); } catch (e) {}
    return post('/api/soluv-room', { msg: '\uD83E\uDD16 ' + st.name + ' check-in: Hyper Controller active in Solid City \u2014 exploring on autopilot (walks, citizen visits, the monument and the sanctuary,