function решить(в) {
  try {
    function num(v, d) {
      return (typeof v === "number" && isFinite(v)) ? (v | 0) : d;
    }

    const size = num(в && в.размер, 15) || 15;
    const turn = num(в && в.ход, 0);
    const total = num(в && в.всего_ходов, 150);
    const rem = total - turn;

    function inB(x, y) {
      return x >= 0 && x < size && y >= 0 && y < size;
    }

    const me = (в && в.я && typeof в.я === "object") ? в.я : {};
    let hx = num(me.x, 0);
    let hy = num(me.y, 0);
    if (!inB(hx, hy)) { hx = 0; hy = 0; }

    const hp = num(me.здоровье, 3);
    const carry = me.груз ? 1 : 0;

    const baseIn = (в && в.моя_база && typeof в.моя_база === "object") ? в.моя_база : { x: 1, y: 1 };
    const enemyBaseIn = (в && в.чужая_база && typeof в.чужая_база === "object") ? в.чужая_база : { x: 13, y: 13 };

    let bx = num(baseIn.x, 1), by = num(baseIn.y, 1);
    let ex = num(enemyBaseIn.x, 13), ey = num(enemyBaseIn.y, 13);
    if (!inB(bx, by)) { bx = 1; by = 1; }
    if (!inB(ex, ey)) { ex = 13; ey = 13; }

    const role = ((num(me.id, 0) % 4) + 4) % 4;
    const N = size * size;
    const mask = (1 << size) - 1;

    const T_UNSEEN = -1;
    const T_EMPTY = 0;
    const T_WALL = 1;
    const T_ALLY = 2;
    const T_ENEMY = 3;
    const T_BASE = 4;

    const DIRS = [
      { d: "С", dx: 0, dy: -1 },
      { d: "В", dx: 1, dy: 0 },
      { d: "Ю", dx: 0, dy: 1 },
      { d: "З", dx: -1, dy: 0 }
    ];
    const OPP = { "С": "Ю", "Ю": "С", "В": "З", "З": "В" };

    const imul = Math.imul ? Math.imul : function (a, b) {
      return ((a | 0) * (b | 0)) | 0;
    };

    function man(ax, ay, bx2, by2) {
      return Math.abs(ax - bx2) + Math.abs(ay - by2);
    }

    function dirName(dx, dy) {
      if (dy < 0) return "С";
      if (dy > 0) return "Ю";
      if (dx < 0) return "З";
      return "В";
    }

    function clamp(v, a, b) {
      return v < a ? a : (v > b ? b : v);
    }

    function hash2(a, b) {
      let h = imul(a | 0, 374761393) ^ imul(b | 0, 668265263);
      h = imul(h ^ (h >>> 13), 1274126177);
      return (h ^ (h >>> 16)) >>> 0;
    }

    function hash4(a, b, c, d) {
      let h = imul(a | 0, 374761393) ^ imul(b | 0, 668265263) ^ imul(c | 0, 2246822519) ^ imul(d | 0, 3266489917);
      h = imul(h ^ (h >>> 13), 1274126177);
      return (h ^ (h >>> 16)) >>> 0;
    }

    const memIn = (в && в.память && typeof в.память === "object") ? в.память : {};
    let blk = {};
    if (memIn.blk && typeof memIn.blk === "object" && !Array.isArray(memIn.blk)) {
      let cnt = 0;
      for (const k in memIn.blk) {
        const v = memIn.blk[k] | 0;
        if (v > turn) {
          blk[k] = v;
          cnt++;
        }
      }
      if (cnt > 12) {
        const keys = Object.keys(blk).sort((a, b) => blk[a] - blk[b]);
        for (let i = 0; i < keys.length - 12; i++) delete blk[keys[i]];
      }
    }

    const mem = {
      px: num(memIn.px, -1),
      py: num(memIn.py, -1),
      stuck: num(memIn.stuck, 0),
      hp: num(memIn.hp, 3),
      tkey: num(memIn.tkey, -1),
      ld: typeof memIn.ld === "string" ? memIn.ld : "",
      la: typeof memIn.la === "string" ? memIn.la : "",
      atkKey: num(memIn.atkKey, -1),
      atkTurn: num(memIn.atkTurn, -1),
      wx: num(memIn.wx, -1),
      wy: num(memIn.wy, -1),
      blk: blk
    };

    function addBlock(k, until) {
      if (k < 0 || k >= N) return;
      const key = String(k);
      mem.blk[key] = until;
      const keys = Object.keys(mem.blk);
      if (keys.length > 12) {
        let old = keys[0];
        let oldV = mem.blk[old] | 0;
        for (const kk of keys) {
          const vv = mem.blk[kk] | 0;
          if (vv < oldV) {
            oldV = vv;
            old = kk;
          }
        }
        delete mem.blk[old];
      }
    }

    const comIn = (в && в.общая && typeof в.общая === "object") ? в.общая : {};
    const com = { w: [], s: [], f: [], e: [], c: [], a: [] };

    for (let i = 0; i < size; i++) {
      const wv = Array.isArray(comIn.w) ? comIn.w[i] : undefined;
      const sv = Array.isArray(comIn.s) ? comIn.s[i] : undefined;
      com.w[i] = (typeof wv === "number" && isFinite(wv)) ? (wv | 0) & mask : 0;
      com.s[i] = (typeof sv === "number" && isFinite(sv)) ? (sv | 0) & mask : 0;
    }

    if (Array.isArray(comIn.f)) {
      for (const it of comIn.f) {
        if (Array.isArray(it) && it.length >= 3) {
          const k = it[0] | 0;
          const amt = it[1] | 0;
          const ts = it[2] | 0;
          if (k >= 0 && k < N && amt > 0) com.f.push([k, amt, ts]);
        }
      }
    }

    if (Array.isArray(comIn.e)) {
      for (const it of comIn.e) {
        if (Array.isArray(it) && it.length >= 2) {
          const k = it[0] | 0;
          const ts = it[1] | 0;
          if (k >= 0 && k < N) com.e.push([k, ts]);
        }
      }
    }

    if (Array.isArray(comIn.c)) {
      for (const it of comIn.c) {
        if (Array.isArray(it) && it.length >= 3) {
          const cid = it[0] | 0;
          const ck = it[1] | 0;
          const ct = it[2] | 0;
          if (ck >= 0 && ck < N) com.c.push([cid, ck, ct]);
        }
      }
    }

    if (Array.isArray(comIn.a)) {
      for (const it of comIn.a) {
        if (Array.isArray(it) && it.length >= 6) {
          const aid = it[0] | 0;
          const ax = it[1] | 0;
          const ay = it[2] | 0;
          const ahp = it[3] | 0;
          const ac = it[4] | 0;
          const at = it[5] | 0;
          if (inB(ax, ay)) com.a.push([aid, ax, ay, ahp, ac, at]);
        }
      }
    }

    function applyWall(x, y, val) {
      if (!inB(x, y)) return;
      if (val) com.w[y] = (com.w[y] | (1 << x)) & mask;
      else com.w[y] = (com.w[y] & ~(1 << x)) & mask;
    }

    function setWallSym(x, y, val) {
      applyWall(x, y, val);
      const mx = size - 1 - x;
      const my = size - 1 - y;
      if (mx !== x || my !== y) applyWall(mx, my, val);
    }

    function upsertFood(k, amt, ts) {
      for (let i = 0; i < com.f.length; i++) {
        if (com.f[i][0] === k) {
          com.f[i][1] = amt;
          com.f[i][2] = ts;
          return;
        }
      }
      com.f.push([k, amt, ts]);
    }

    function removeFood(k) {
      for (let i = com.f.length - 1; i >= 0; i--) {
        if (com.f[i][0] === k) com.f.splice(i, 1);
      }
    }

    function upsertEnemy(k, ts) {
      for (let i = 0; i < com.e.length; i++) {
        if (com.e[i][0] === k) {
          com.e[i][1] = ts;
          return;
        }
      }
      com.e.push([k, ts]);
    }

    const tArr = new Array(N).fill(T_UNSEEN);
    const fArr = new Array(N).fill(0);
    const localFood = [];
    const visibleEnemies = [];
    const visibleAllies = [];

    const vis = (в && Array.isArray(в.видно)) ? в.видно : [];
    for (const c of vis) {
      if (!c || typeof c !== "object") continue;
      const x = num(c.x, -1);
      const y = num(c.y, -1);
      if (!inB(x, y)) continue;

      const k = y * size + x;
      const isWall = c.что === "стена";
      setWallSym(x, y, isWall);
      com.s[y] = (com.s[y] | (1 << x)) & mask;

      let t = T_EMPTY;
      if (isWall) t = T_WALL;
      else if (c.что === "свой") t = T_ALLY;
      else if (c.что === "враг") t = T_ENEMY;
      else if (c.что === "база") t = T_BASE;

      const food = isWall ? 0 : num(c.еда, 0);
      tArr[k] = t;
      fArr[k] = food;

      if (food > 0) {
        upsertFood(k, food, turn);
        localFood.push({ k: k, amt: food, x: x, y: y });
      } else {
        removeFood(k);
      }

      if (t === T_ENEMY) {
        visibleEnemies.push({ x: x, y: y, k: k });
        upsertEnemy(k, turn);
      } else if (t === T_ALLY && !(x === hx && y === hy)) {
        visibleAllies.push({ x: x, y: y, k: k });
      }
    }

    const selfK = hy * size + hx;
    if (tArr[selfK] === T_UNSEEN) tArr[selfK] = T_ALLY;

    com.a.push([role, hx, hy, hp, carry, turn]);

    function knownWall(x, y) {
      if (!inB(x, y)) return true;
      if ((x === bx && y === by) || (x === ex && y === ey)) return false;
      if (x === 0 || y === 0 || x === size - 1 || y === size - 1) return true;
      const k = y * size + x;
      if (tArr[k] !== T_UNSEEN) return tArr[k] === T_WALL;
      return (((com.w[y] || 0) >>> x) & 1) !== 0;
    }

    function occupiedVisible(x, y) {
      if (!inB(x, y)) return true;
      if (x === hx && y === hy) return false;
      const t = tArr[y * size + x];
      return t === T_ALLY || t === T_ENEMY;
    }

    (function sanitize() {
      const fmap = Object.create(null);
      for (const it of com.f) {
        if (!Array.isArray(it) || it.length < 3) continue;
        const k = it[0] | 0;
        const amt = it[1] | 0;
        const ts = it[2] | 0;
        if (k < 0 || k >= N || amt <= 0) continue;
        if (turn - ts > 50) continue;
        const x = k % size;
        const y = (k / size) | 0;
        if (!inB(x, y) || knownWall(x, y)) continue;
        const prev = fmap[k];
        if (!prev || ts > prev[2] || (ts === prev[2] && amt > prev[1])) fmap[k] = [k, amt, ts];
      }
      let fl = [];
      for (const key in fmap) fl.push(fmap[key]);
      fl.sort((a, b) => b[2] - a[2] || b[1] - a[1]);
      if (fl.length > 40) fl.length = 40;
      com.f = fl;

      const emap = Object.create(null);
      for (const it of com.e) {
        if (!Array.isArray(it) || it.length < 2) continue;
        const k = it[0] | 0;
        const ts = it[1] | 0;
        if (k < 0 || k >= N) continue;
        if (turn - ts > 8) continue;
        const prev = emap[k];
        if (!prev || ts > prev[1]) emap[k] = [k, ts];
      }
      let el = [];
      for (const key in emap) el.push(emap[key]);
      el.sort((a, b) => b[1] - a[1]);
      if (el.length > 12) el.length = 12;
      com.e = el;

      const cmap = Object.create(null);
      for (const it of com.c) {
        if (!Array.isArray(it) || it.length < 3) continue;
        const cid = it[0] | 0;
        const ck = it[1] | 0;
        const ct = it[2] | 0;
        if (ck < 0 || ck >= N) continue;
        if (turn - ct > 6) continue;
        const x = ck % size;
        const y = (ck / size) | 0;
        if (knownWall(x, y)) continue;
        const prev = cmap[cid];
        if (!prev || ct > prev[2]) cmap[cid] = [cid, ck, ct];
      }
      let cl = [];
      for (const key in cmap) cl.push(cmap[key]);
      if (cl.length > 8) cl.length = 8;
      com.c = cl;

      const amap = Object.create(null);
      for (const it of com.a) {
        if (!Array.isArray(it) || it.length < 6) continue;
        const aid = it[0] | 0;
        const ax = it[1] | 0;
        const ay = it[2] | 0;
        const ahp = it[3] | 0;
        const ac = it[4] | 0;
        const at = it[5] | 0;
        if (!inB(ax, ay)) continue;
        if (turn - at > 3) continue;
        const prev = amap[aid];
        if (!prev || at > prev[5]) amap[aid] = [aid, ax, ay, ahp, ac, at];
      }
      let al = [];
      for (const key in amap) al.push(amap[key]);
      al.sort((a, b) => a[0] - b[0]);
      if (al.length > 4) al.length = 4;
      com.a = al;
    })();

    if (mem.tkey >= 0 && mem.tkey < N) {
      const tx = mem.tkey % size;
      const ty = (mem.tkey / size) | 0;
      if (knownWall(tx, ty) || (tArr[mem.tkey] !== T_UNSEEN && fArr[mem.tkey] <= 0)) {
        mem.tkey = -1;
      }
    }

    const samePos = mem.px === hx && mem.py === hy;
    mem.stuck = (samePos && mem.la === "идти") ? (mem.stuck + 1) : 0;
    const wasDamaged = mem.hp > hp;
    mem.hp = hp;

    if (mem.stuck >= 2 && mem.ld) {
      let dx = 0, dy = 0;
      if (mem.ld === "С") dy = -1;
      else if (mem.ld === "Ю") dy = 1;
      else if (mem.ld === "З") dx = -1;
      else if (mem.ld === "В") dx = 1;
      const nx = hx + dx, ny = hy + dy;
      if (inB(nx, ny)) addBlock(ny * size + nx, turn + 6);
    }

    if (mem.stuck >= 5) {
      if (mem.tkey >= 0) addBlock(mem.tkey, turn + 18);
      else if (mem.wx >= 0 && mem.wy >= 0) addBlock(mem.wy * size + mem.wx, turn + 12);
      mem.stuck = 0;
    }

    const adjEnemies = [];
    for (const e of visibleEnemies) {
      if (man(hx, hy, e.x, e.y) === 1) {
        adjEnemies.push({ x: e.x, y: e.y, k: e.k, dir: dirName(e.x - hx, e.y - hy) });
      }
    }

    function threatAt(x, y) {
      let s = 0;
      for (const e of visibleEnemies) {
        const d = man(x, y, e.x, e.y);
        if (d <= 1) s += 40;
        else if (d <= 2) s += 12;
        else if (d <= 3) s += 3;
      }
      for (const it of com.e) {
        if (turn - it[1] <= 2) {
          const px = it[0] % size;
          const py = (it[0] / size) | 0;
          const d = man(x, y, px, py);
          if (d <= 1) s += 15;
          else if (d <= 2) s += 5;
        }
      }
      if (wasDamaged && x === hx && y === hy) s += 10;
      return s;
    }

    function bfs(sx, sy, blockOcc) {
      const dist = new Array(N).fill(-1);
      if (!inB(sx, sy)) return dist;
      const sk = sy * size + sx;
      if (knownWall(sx, sy) && sk !== selfK) return dist;

      const q = new Array(N);
      let head = 0, tail = 0;
      dist[sk] = 0;
      q[tail++] = sk;

      while (head < tail) {
        const k = q[head++];
        const x = k % size;
        const y = (k / size) | 0;
        const nd = dist[k] + 1;

        for (let i = 0; i < 4; i++) {
          const nx = x + DIRS[i].dx;
          const ny = y + DIRS[i].dy;
          if (!inB(nx, ny)) continue;
          const nk = ny * size + nx;
          if (dist[nk] !== -1) continue;
          if (knownWall(nx, ny)) continue;
          if (blockOcc && occupiedVisible(nx, ny)) continue;
          dist[nk] = nd;
          q[tail++] = nk;
        }
      }

      return dist;
    }

    function chooseStep(tx, ty, opts) {
      opts = opts || {};
      if (!inB(tx, ty)) return null;
      if (tx === hx && ty === hy) return null;
      if (knownWall(tx, ty)) return null;

      const dist = bfs(tx, ty, false);
      const myD = dist[selfK];
      const curMan = man(hx, hy, tx, ty);
      const curThreat = threatAt(hx, hy);

      let best = null;
      let bestScore = 1e9;
      let bestProgress = false;

      for (const o of DIRS) {
        const nx = hx + o.dx;
        const ny = hy + o.dy;
        if (!inB(nx, ny)) continue;
        const nk = ny * size + nx;
        if (knownWall(nx, ny)) continue;
        if (occupiedVisible(nx, ny)) continue;

        const dGoal = dist[nk] >= 0 ? dist[nk] : man(nx, ny, tx, ty) + 20;
        const progress =
          (myD >= 0 && dist[nk] >= 0 && dist[nk] < myD) ||
          (myD < 0 && man(nx, ny, tx, ty) < curMan);

        let score = dGoal * 10;
        if (progress) score -= 70;
        else score += 45;

        const th = threatAt(nx, ny);
        score += th * ((opts.carry || opts.flee || hp <= 1) ? 3 : 1);

        if (curThreat > 0 && th < curThreat) score -= 18;
        if ((opts.carry || hp <= 1) && th >= 40) score += 90;

        if (nx === bx && ny === by) {
          if (opts.carry && tx === bx && ty === by) score -= 35;
          else if (!opts.carry && !(tx === bx && ty === by)) score += 130;
          else score += 15;
        }

        if (nx === ex && ny === ey) score += 45;
        if (!opts.carry && fArr[nk] > 0) score -= 10;
        if (mem.blk[String(nk)] > turn) score += 150;
        if (mem.stuck > 1 && mem.ld && o.d === OPP[mem.ld]) score += 30;
        score += hash4(nx, ny, role, turn) & 7;

        if (score < bestScore) {
          bestScore = score;
          best = o;
          bestProgress = progress;
        }
      }

      if (!best) return null;
      if (!bestProgress && !(opts.urgent || opts.carry || opts.flee || curThreat > 10 || mem.stuck >= 1)) {
        return null;
      }
      return { "тип": "идти", "куда": best.d };
    }

    function chooseEscape(forCarry) {
      const cx = size >> 1;
      const cy = size >> 1;
      const curScore = threatAt(hx, hy) * 4 +
        (forCarry ? man(hx, hy, bx, by) * 6 : (hp <= 1 ? man(hx, hy, bx, by) * 4 : man(hx, hy, cx, cy) * 2));

      let best = null;
      let bestScore = 1e9;

      for (const o of DIRS) {
        const nx = hx + o.dx;
        const ny = hy + o.dy;
        if (!inB(nx, ny)) continue;
        const nk = ny * size + nx;
        if (knownWall(nx, ny)) continue;
        if (occupiedVisible(nx, ny)) continue;

        const th = threatAt(nx, ny);
        let score = th * 4;

        if (forCarry) score += man(nx, ny, bx, by) * 6;
        else if (hp <= 1) score += man(nx, ny, bx, by) * 4;
        else score += man(nx, ny, cx, cy) * 2;

        if (!forCarry && fArr[nk] > 0) score -= 12;

        if (nx === bx && ny === by) {
          if (forCarry) score -= 20;
          else if (hp <= 1) score -= 10;
          else score += 50;
        }

        if (nx === ex && ny === ey) score += 50;
        if (mem.blk[String(nk)] > turn) score += 130;
        score += hash4(nx, ny, role, turn) & 7;

        if (score < bestScore) {
          bestScore = score;
          best = o;
        }
      }

      if (best && bestScore < curScore) return { "тип": "идти", "куда": best.d };
      return null;
    }

    function chooseAttack() {
      if (adjEnemies.length === 0) return null;

      let best = null;
      let bestScore = 1e9;

      for (const e of adjEnemies) {
        let score = 0;
        const dBase = man(e.x, e.y, bx, by);

        if (e.x === bx && e.y === by) score -= 180;
        if (dBase <= 2) score -= 80;
        if ((fArr[e.k] || 0) > 0) score -= 110;
        if (dBase < man(e.x, e.y, ex, ey)) score -= 40;

        let support = 0;
        for (const a of visibleAllies) {
          if (man(a.x, a.y, e.x, e.y) <= 1) support++;
        }
        if (support > 0) score -= 35 * support;

        if (hp === 3) score -= 20;
        else if (hp === 2) score += 5;
        else score += 220;

        if (carry) score += 140;
        if (adjEnemies.length >= 2) score += 100;
        if (mem.atkKey === e.k && mem.atkTurn === turn - 1) score -= 30;
        if (rem <= 12 && !(e.x === bx && e.y === by)) score += 50;

        score += dBase * 2;
        score += hash4(e.x, e.y, role, turn) & 7;

        if (score < bestScore) {
          bestScore = score;
          best = e;
        }
      }

      if (!best) return null;
      return { act: { "тип": "бить", "куда": best.dir }, key: best.k, score: bestScore };
    }

    function doTake() {
      const amt = fArr[selfK] > 0 ? fArr[selfK] : 0;
      if (amt <= 1) {
        removeFood(selfK);
        if (mem.tkey === selfK) mem.tkey = -1;
      } else {
        upsertFood(selfK, amt - 1, turn);
      }
      mem.stuck = 0;
      return { "тип": "взять" };
    }

    function chooseFoodTarget(tieMode) {
      const cand = [];
      const used = Object.create(null);

      function add(k, amt, ts) {
        if (amt <= 0 || used[k]) return;
        const x = k % size;
        const y = (k / size) | 0;
        if (!inB(x, y)) return;
        if (knownWall(x, y)) return;
        if (tArr[k] === T_WALL) return;
        used[k] = 1;
        cand.push({ k: k, x: x, y: y, amt: amt, ts: ts });
      }

      for (const it of localFood) add(it.k, it.amt, turn);
      for (const it of com.f) add(it[0] | 0, it[1] | 0, it[2] | 0);
      if (cand.length === 0) return null;

      const distSelf = bfs(hx, hy, false);
      const distBase = tieMode ? null : bfs(bx, by, false);

      let best = null;
      let bestScore = 1e9;

      for (const c of cand) {
        const dS = distSelf[c.k] >= 0 ? distSelf[c.k] : man(hx, hy, c.x, c.y) + 20;
        let dB = 0;

        if (!tieMode) {
          dB = distBase ? (distBase[c.k] >= 0 ? distBase[c.k] : man(c.x, c.y, bx, by) + 20) : man(c.x, c.y, bx, by) + 20;
          const canDeliver = (dS + dB + 2 <= rem) || (c.k === selfK && dB + 2 <= rem);
          if (rem <= 45 && !canDeliver) continue;
        } else {
          if (dS > rem) continue;
        }

        let score;
        if (tieMode) {
          score = dS * 12 - Math.min(c.amt, 4) * 4;
        } else {
          score = dS * 9 + dB * 13 - Math.min(c.amt, 4) * 7;
        }

        const age = Math.max(0, turn - c.ts);
        score += tieMode ? Math.min(age, 15) : Math.min(age, 30);

        const danger = threatAt(c.x, c.y);
        score += danger * (hp <= 1 ? 3 : (tieMode ? 2 : 1));

        let claims = 0;
        for (const cl of com.c) {
          if (cl[0] !== role && cl[1] === c.k && turn - cl[2] <= 6) claims++;
        }
        if (claims > 0) {
          if (c.amt <= claims) score += 170;
          else score += claims * 30;
        }

        for (const a of visibleAllies) {
          const ad = man(a.x, a.y, c.x, c.y);
          const md = man(hx, hy, c.x, c.y);
          if (ad < md) score += 16;
          else if (ad <= 1) score += 6;
        }

        for (const a of com.a) {
          if (a[0] !== role && turn - a[5] <= 2 && a[4] === 0) {
            const ad = man(a[1], a[2], c.x, c.y);
            const md = man(hx, hy, c.x, c.y);
            if (ad < md) score += 14;
            else if (ad === md && a[0] < role) score += 5;
          }
        }

        const slots = Math.min(c.amt, 4);
        let owned = 0;
        for (let s = 0; s < slots; s++) {
          if ((hash2(c.k, s * 7 + 13) & 3) === role) owned++;
        }
        if (owned > 0) score -= owned * 20;
        else score += 14;

        if (c.k === mem.tkey) score -= 20;
        if (mem.blk[String(c.k)] > turn) score += 150;
        if (c.k === selfK) score -= 30;
        if (tArr[c.k] === T_ALLY) score += 50;
        if (tArr[c.k] === T_ENEMY) score += 40;
        if (c.x === ex && c.y === ey) score += 30;
        if (!tieMode && rem <= 15 && dS > 1) score += 70;

        score += hash4(c.k, role, turn, rem) & 7;

        if (score < bestScore) {
          bestScore = score;
          best = c;
        }
      }

      return best;
    }

    function chooseExploreTarget() {
      const pts = [];
      for (let y = 2; y <= size - 3; y += 2) {
        for (let x = 2; x <= size - 3; x += 2) {
          if (!knownWall(x, y) && !(x === bx && y === by) && !(x === ex && y === ey)) {
            pts.push({ x: x, y: y });
          }
        }
      }
      const cx = size >> 1;
      const cy = size >> 1;
      if (!knownWall(cx, cy) && !(cx === bx && cy === by) && !(cx === ex && cy === ey)) {
        pts.push({ x: cx, y: cy });
      }
      if (pts.length === 0) return { x: hx, y: hy };

      const sx = ex > bx ? 1 : -1;
      const sy = ey > by ? 1 : -1;
      const anchors = [
        { x: clamp(bx + 4 * sx, 2, size - 3), y: clamp(by + 2 * sy, 2, size - 3) },
        { x: clamp(bx + 2 * sx, 2, size - 3), y: clamp(by + 4 * sy, 2, size - 3) },
        { x: clamp(bx + 6 * sx, 2, size - 3), y: clamp(by + 6 * sy, 2, size - 3) },
        { x: clamp(bx + 8 * sx, 2, size - 3), y: clamp(by + 8 * sy, 2, size - 3) }
      ];
      const anchor = anchors[role];

      let best = null, bestScore = 1e9;
      let second = null, secondScore = 1e9;

      for (const p of pts) {
        const seen = ((com.s[p.y] || 0) >>> p.x) & 1;
        let score = man(hx, hy, p.x, p.y) * 4 + (seen ? 28 : -35) + man(p.x, p.y, anchor.x, anchor.y) * 3;
        if (mem.stuck < 2 && mem.wx === p.x && mem.wy === p.y) score -= 35;
        if (p.x === ex && p.y === ey) score += 30;
        if (p.x === bx && p.y === by) score += 100;
        score += hash4(p.x, p.y, role, turn) & 15;

        if (score < bestScore) {
          second = best;
          secondScore = bestScore;
          best = p;
          bestScore = score;
        } else if (score < secondScore) {
          second = p;
          secondScore = score;
        }
      }

      if (best && best.x === hx && best.y === hy && second) best = second;
      if (!best) return { x: hx, y: hy };
      mem.wx = best.x;
      mem.wy = best.y;
      return best;
    }

    function fallbackExplore() {
      const cx = size >> 1;
      const cy = size >> 1;
      let best = null;
      let bestScore = 1e9;

      for (const o of DIRS) {
        const nx = hx + o.dx;
        const ny = hy + o.dy;
        if (!inB(nx, ny)) continue;
        const nk = ny * size + nx;
        if (knownWall(nx, ny)) continue;
        if (occupiedVisible(nx, ny)) continue;

        const seen = ((com.s[ny] || 0) >>> nx) & 1;
        let score = threatAt(nx, ny) * 2 + man(nx, ny, cx, cy) * 3 + (seen ? 12 : -18);
        if (nx === ex && ny === ey) score += 35;
        if (mem.blk[String(nk)] > turn) score += 120;
        score += hash4(nx, ny, role, turn) & 15;

        if (score < bestScore) {
          bestScore = score;
          best = o;
        }
      }

      if (!best) return null;
      return { "тип": "идти", "куда": best.d };
    }

    function chooseLeaveBase() {
      let best = null;
      let bestScore = 1e9;
      const cx = size >> 1;
      const cy = size >> 1;

      for (const o of DIRS) {
        const nx = hx + o.dx;
        const ny = hy + o.dy;
        if (!inB(nx, ny)) continue;
        const nk = ny * size + nx;
        if (knownWall(nx, ny)) continue;
        if (occupiedVisible(nx, ny)) continue;

        let score = threatAt(nx, ny) * 2;
        score -= man(nx, ny, bx, by) * 8;
        score += man(nx, ny, cx, cy) * 2;
        if (fArr[nk] > 0) score -= 25;
        if (nx === ex && ny === ey) score += 40;
        if (mem.blk[String(nk)] > turn) score += 120;
        score += hash4(nx, ny, role, turn) & 7;

        if (score < bestScore) {
          bestScore = score;
          best = o;
        }
      }

      if (!best) return null;
      return { "тип": "идти", "куда": best.d };
    }

    function ret(act) {
      if (!act || typeof act !== "object") act = { "тип": "ждать" };

      mem.px = hx;
      mem.py = hy;

      if (act.тип === "идти") {
        mem.ld = typeof act.куда === "string" ? act.куда : "";
        mem.la = "идти";
      } else {
        mem.ld = "";
        mem.la = typeof act.тип === "string" ? act.тип : "ждать";
      }

      if (act.тип === "взять" || act.тип === "положить" || act.тип === "бить") {
        mem.stuck = 0;
      }

      if (mem.atkTurn < turn - 1) {
        mem.atkKey = -1;
        mem.atkTurn = -1;
      }

      let willCarry = carry;
      if (act.тип === "взять") willCarry = 1;
      if (act.тип === "положить") willCarry = 0;

      const cc = [];
      const seen = Object.create(null);
      for (const cl of com.c) {
        if (!Array.isArray(cl) || cl.length < 3) continue;
        const cid = cl[0] | 0;
        const ck = cl[1] | 0;
        const ct = cl[2] | 0;
        if (turn - ct > 6) continue;
        if (ck < 0 || ck >= N) continue;
        if (cid === role) continue;
        if (seen[cid]) continue;
        const x = ck % size;
        const y = (ck / size) | 0;
        if (knownWall(x, y)) continue;
        seen[cid] = 1;
        cc.push([cid, ck, ct]);
      }

      if (!willCarry && mem.tkey >= 0 && mem.tkey < N) {
        const x = mem.tkey % size;
        const y = (mem.tkey / size) | 0;
        if (!knownWall(x, y)) cc.push([role, mem.tkey, turn]);
      }

      com.c = cc.slice(-8);

      return { "действие": act, "память": mem, "общая": com };
    }

    const onBase = hx === bx && hy === by;
    const hereFood = fArr[selfK] > 0 ? fArr[selfK] : 0;

    if (carry && onBase) {
      mem.tkey = -1;
      return ret({ "тип": "положить" });
    }

    if (rem <= 0) {
      if (!carry && hereFood > 0) return ret(doTake());
      return ret({ "тип": "ждать" });
    }

    if (onBase && !carry && adjEnemies.length === 0) {
      if (hereFood > 0) return ret(doTake());
      const lv = chooseLeaveBase();
      if (lv) return ret(lv);
    }

    if (adjEnemies.length > 0) {
      const many = adjEnemies.length >= 2;
      const enemyOnBase = adjEnemies.some(function (e) { return e.x === bx && e.y === by; });
      const enemyOnFood = adjEnemies.some(function (e) { return (fArr[e.k] || 0) > 0; });
      const enemyNearBase = adjEnemies.some(function (e) { return man(e.x, e.y, bx, by) <= 2; });
      const enemyInOurHalf = adjEnemies.some(function (e) {
        return man(e.x, e.y, bx, by) < man(e.x, e.y, ex, ey);
      });
      const lastTarget = mem.atkTurn === turn - 1 && adjEnemies.some(function (e) { return e.k === mem.atkKey; });
      const support = visibleAllies.filter(function (a) { return man(a.x, a.y, hx, hy) <= 1; }).length;

      if (carry) {
        if (enemyOnBase && hp >= 2 && (!many || support > 0 || hp === 3)) {
          const at = chooseAttack();
          if (at) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        if (man(hx, hy, bx, by) === 1 && !occupiedVisible(bx, by)) {
          return ret({ "тип": "идти", "куда": dirName(bx - hx, by - hy) });
        }

        if (man(hx, hy, bx, by) === 1 && occupiedVisible(bx, by)) {
          return ret({ "тип": "ждать" });
        }

        const esc = chooseEscape(true);
        if (esc && (hp <= 2 || many || wasDamaged || threatAt(hx, hy) >= 40 || !enemyOnBase)) {
          return ret(esc);
        }

        if (hp >= 2 && !many && (enemyOnBase || enemyOnFood || enemyNearBase || lastTarget)) {
          const at = chooseAttack();
          if (at) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        if (hp === 3 && !many && enemyInOurHalf) {
          const at = chooseAttack();
          if (at) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        const mv = chooseStep(bx, by, { carry: true, urgent: true });
        if (mv) return ret(mv);

        if (hp >= 2 && !many) {
          const at = chooseAttack();
          if (at) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        if (hp === 1 && !many && enemyOnBase) {
          const at = chooseAttack();
          if (at) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        return ret({ "тип": "ждать" });
      } else {
        if (hp <= 1) {
          const esc = chooseEscape(false);
          if (esc) return ret(esc);

          if (enemyOnBase && rem > 20) {
            const at = chooseAttack();
            if (at && at.score < 160) {
              mem.atkKey = at.key;
              mem.atkTurn = turn;
              return ret(at.act);
            }
          }

          if (hereFood > 0 && rem <= 8 && !many) return ret(doTake());
          return ret({ "тип": "ждать" });
        }

        const wantFight =
          enemyOnBase ||
          enemyOnFood ||
          enemyNearBase ||
          lastTarget ||
          (hp === 3 && !many && enemyInOurHalf) ||
          (support > 0 && !many && enemyInOurHalf);

        if (wantFight) {
          const at = chooseAttack();
          if (at && (at.score < 150 || enemyOnBase || enemyOnFood)) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        if (hereFood > 0 && rem <= 10 && !many && hp >= 2) return ret(doTake());

        const goal = (hp <= 2 || wasDamaged || enemyNearBase) ? { x: bx, y: by } : chooseExploreTarget();
        const mv = chooseStep(goal.x, goal.y, { flee: true, urgent: true, carry: false });
        if (mv) return ret(mv);

        if (hp >= 2 && !many) {
          const at = chooseAttack();
          if (at && at.score < 170) {
            mem.atkKey = at.key;
            mem.atkTurn = turn;
            return ret(at.act);
          }
        }

        if (hereFood > 0 && hp >= 2) return ret(doTake());
        return ret({ "тип": "ждать" });
      }
    }

    if (!carry && hereFood > 0) {
      return ret(doTake());
    }

    if (carry) {
      mem.tkey = -1;

      if (man(hx, hy, bx, by) === 1 && occupiedVisible(bx, by)) {
        return ret({ "тип": "ждать" });
      }

      if (man(hx, hy, bx, by) === 1 && !occupiedVisible(bx, by) && (rem > 10 || 2 <= rem)) {
        return ret({ "тип": "идти", "куда": dirName(bx - hx, by - hy) });
      }

      const distBase = bfs(bx, by, false);
      let dBase = distBase[selfK];
      if (dBase < 0) dBase = man(hx, hy, bx, by) + 20;

      if (rem <= 25) {
        if (dBase >= 0 && dBase + 1 <= rem) {
          const mv = chooseStep(bx, by, { carry: true, urgent: true });
          if (mv) return ret(mv);
        }

        if (threatAt(hx, hy) > 5) {
          const esc = chooseEscape(true);
          if (esc) return ret(esc);
        }

        return ret({ "тип": "ждать" });
      }

      const mv = chooseStep(bx, by, { carry: true, urgent: true });
      if (mv) return ret(mv);
      return ret({ "тип": "ждать" });
    }

    if (!carry && hp >= 2 && rem > 15 && visibleEnemies.length > 0) {
      let nearBase = false;
      for (const e of visibleEnemies) {
        if (man(e.x, e.y, bx, by) <= 3) {
          nearBase = true;
          break;
        }
      }
      if (nearBase && man(hx, hy, bx, by) <= 5) {
        const mv = chooseStep(bx, by, { urgent: true, carry: false });
        if (mv) return ret(mv);
      }
    }

    if (!carry) {
      let fg = chooseFoodTarget(false);
      if (!fg && rem <= 35) fg = chooseFoodTarget(true);

      if (fg) {
        mem.tkey = fg.k;

        if (fg.k === selfK) {
          if (hereFood > 0) return ret(doTake());
          mem.tkey = -1;
          addBlock(fg.k, turn + 8);
        } else {
          let mv = chooseStep(fg.x, fg.y, { carry: false, urgent: rem <= 25 });
          if (!mv) mv = chooseStep(fg.x, fg.y, { carry: false, urgent: true });
          if (mv) return ret(mv);

          if (mem.stuck >= 2 || (tArr[fg.k] !== T_UNSEEN && occupiedVisible(fg.x, fg.y))) {
            addBlock(fg.k, turn + 10);
            mem.tkey = -1;
          } else {
            return ret({ "тип": "ждать" });
          }
        }
      } else {
        mem.tkey = -1;
      }

      if (rem <= 10) {
        let bestF = null;
        let bd = 999;
        for (const it of localFood) {
          if (knownWall(it.x, it.y)) continue;
          const d = man(hx, hy, it.x, it.y);
          if (d <= rem && d < bd) {
            bd = d;
            bestF = it;
          }
        }
        if (bestF) {
          if (bestF.k === selfK) {
            if (hereFood > 0) return ret(doTake());
          } else {
            const mv = chooseStep(bestF.x, bestF.y, { carry: false, urgent: true });
            if (mv) return ret(mv);
          }
        }
      }

      const wp = chooseExploreTarget();
      if (wp.x !== hx || wp.y !== hy) {
        const mv = chooseStep(wp.x, wp.y, { carry: false, urgent: false });
        if (mv) return ret(mv);
      }

      const fb = fallbackExplore();
      if (fb) return ret(fb);

      if (hereFood > 0) return ret(doTake());
      return ret({ "тип": "ждать" });
    }

    return ret({ "тип": "ждать" });
  } catch (e) {
    return {
      "действие": { "тип": "ждать" },
      "память": (в && в.память) ? в.память : {},
      "общая": (в && в.общая) ? в.общая : {}
    };
  }
}
