// Муравей: общая карта с симметрией 180°, общий реестр еды,
// динамическое распределение куч (с антипробкой), приоритет спорной еды,
// доверие к зеркальной догадке по своей половине, уход из-под удара с грузом,
// экономный бой, разведка по секторам, эндшпиль (еда в руках — тай-брейк).
function решить(в) {
  var N = 15, SZ = 225;
  var DIRS = [[0, -1, "С"], [0, 1, "Ю"], [-1, 0, "З"], [1, 0, "В"]];

  var память = (в && в.память && typeof в.память === "object") ? в.память : {};
  var общая = (в && в.общая && typeof в.общая === "object") ? в.общая : {};
  var M = null, мойTgt = -1, ЯID = null, MX = 0, MY = 0, CARRY = 0;

  function сохр() {
    try {
      if (M && M.length === SZ) общая.m = M.join("");
      if (ЯID !== null) {
        if (!общая.p || typeof общая.p !== "object") общая.p = {};
        общая.p[ЯID] = [MX, MY, CARRY, (в && в.ход | 0) || 0, мойTgt];
      }
    } catch (e) { }
  }
  function готово(d) { сохр(); return { действие: d, память: память, общая: общая }; }

  try {
    var я = в.я, ход = в.ход | 0;
    var всего = (в.всего_ходов | 0) || 150;
    var ост = всего - ход;                        // ходов после текущего
    var mx = я.x | 0, my = я.y | 0, mi = my * N + mx;
    var carry = (я.груз | 0) > 0;
    var hp = я.здоровье | 0;
    var bx = в.моя_база.x | 0, by = в.моя_база.y | 0, baseI = by * N + bx;
    var ebx = в.чужая_база.x | 0, eby = в.чужая_база.y | 0;
    ЯID = я.id; MX = mx; MY = my; CARRY = carry ? 1 : 0;

    function idx(x, y) { return y * N + x; }
    function ix(i) { return i % N; }
    function iy(i) { return (i - i % N) / N; }
    function зерк(i) { return (N - 1 - iy(i)) * N + (N - 1 - ix(i)); }
    function манх(a, b) { return Math.abs(ix(a) - ix(b)) + Math.abs(iy(a) - iy(b)); }
    function манхXY(i, x, y) { return Math.abs(ix(i) - x) + Math.abs(iy(i) - y); }
    function хеш(a) { a = (a * 1103515245 + 12345) & 0x7fffffff; return a; }
    function стенаCh(ch) { return ch === "#" || ch === "w"; }
    function виделCh(ch) { return ch === "#" || ch === "."; }
    // перевес: >0 — клетка ближе к нашей базе (безопасная), <0 — к чужой
    function перевес(i) { return манхXY(i, ebx, eby) - манхXY(i, bx, by); }

    /* ---------- общая карта ---------- */
    var i, x, y, k;
    if (typeof общая.m === "string" && общая.m.length === SZ) {
      M = общая.m.split("");
    } else {
      M = [];
      for (i = 0; i < SZ; i++) {
        x = ix(i); y = iy(i);
        M.push((x === 0 || y === 0 || x === N - 1 || y === N - 1) ? "#" : "?");
      }
    }
    if (!общая.f || typeof общая.f !== "object") общая.f = {};
    var F = общая.f;
    if (!общая.p || typeof общая.p !== "object") общая.p = {};
    var P = общая.p;

    /* ---------- слот муравья (сектор разведки) ---------- */
    if (!общая.ids || !общая.ids.length) общая.ids = [];
    var slot = -1;
    for (i = 0; i < общая.ids.length; i++) if (общая.ids[i] === я.id) { slot = i; break; }
    if (slot < 0) {
      if (общая.ids.length < 8) { общая.ids.push(я.id); slot = общая.ids.length - 1; }
      else slot = 0;
    }

    /* ---------- разбор обзора ---------- */
    var видно = в.видно || [];
    var занятоСвой = {}, занятоВраг = {}, врагиСписок = [], едаЗдесь = 0;
    for (i = 0; i < видно.length; i++) {
      var c = видно[i];
      if (!c) continue;
      x = c.x | 0; y = c.y | 0;
      if (x < 0 || y < 0 || x >= N || y >= N) continue;
      var ci = idx(x, y);
      var стена = (c.что === "стена");
      M[ci] = стена ? "#" : ".";
      var mzi = зерк(ci);
      if (M[mzi] === "?") M[mzi] = стена ? "w" : "o";   // карта симметрична на 180°

      if (c.что === "свой" && ci !== mi) занятоСвой[ci] = 1;
      if (c.что === "враг") { занятоВраг[ci] = 1; врагиСписок.push(ci); }

      var ед = c.еда | 0;
      if (!стена && ед > 0) {
        F[ci] = [ед, ход, 0];
        // зеркальная догадка: на своей половине она надёжна и живёт долго,
        // на чужой — быстро протухает (соперник рядом и заберёт первым)
        var своя = перевес(mzi) > 0;
        var окно = своя ? 115 : 55;
        if (ход <= окно && !F[mzi] && !виделCh(M[mzi]) && !стенаCh(M[mzi])) {
          F[mzi] = [ед, ход, своя ? 1 : 2];
        }
        if (ci === mi) едаЗдесь = ед;
      } else {
        if (F[ci]) delete F[ci];
        if (ci === mi) едаЗдесь = 0;
      }
    }

    /* ---------- чистка реестров ---------- */
    var ключи = [];
    for (k in F) if (F.hasOwnProperty(k)) ключи.push(k);
    for (i = 0; i < ключи.length; i++) {
      var e0 = F[ключи[i]];
      if (!e0 || e0.length < 2) { delete F[ключи[i]]; continue; }
      var г0 = e0[2] | 0;
      if (г0 === 1 && ход - e0[1] > 120) delete F[ключи[i]];
      else if (г0 === 2 && ход - e0[1] > 55) delete F[ключи[i]];
    }
    ключи = [];
    for (k in F) if (F.hasOwnProperty(k)) ключи.push(k);
    if (ключи.length > 90) {
      ключи.sort(function (a, b) { return (F[a] ? F[a][1] : 0) - (F[b] ? F[b][1] : 0); });
      for (i = 0; i < 20; i++) delete F[ключи[i]];
    }
    for (k in P) if (P.hasOwnProperty(k)) {
      var pe0 = P[k];
      if (!pe0 || pe0.length < 4 || ход - (pe0[3] | 0) > 4) delete P[k];
    }

    /* ---------- заявки на этот ход ---------- */
    if (!общая.r || общая.r.t !== ход) общая.r = { t: ход, a: {} };
    var RS = общая.r.a;
    if (!общая.e || общая.e.t !== ход) общая.e = { t: ход, m: {} };
    var EX = общая.e.m;

    var бронь = {}, освобождают = {};
    for (k in RS) if (RS.hasOwnProperty(k) && k !== String(я.id)) {
      var rr = RS[k];
      if (rr && rr.length === 2) {
        if (rr[1] >= 0) бронь[rr[1]] = 1;
        if (rr[1] !== rr[0]) освобождают[rr[0]] = 1;
      }
    }

    /* ---------- опасность: клетки под ударом врага ---------- */
    var опас = {};
    for (i = 0; i < врагиСписок.length; i++) {
      var ei = врагиСписок[i], ex2 = ix(ei), ey2 = iy(ei);
      for (var t0 = 0; t0 < 4; t0++) {
        var ax2 = ex2 + DIRS[t0][0], ay2 = ey2 + DIRS[t0][1];
        if (ax2 < 0 || ay2 < 0 || ax2 >= N || ay2 >= N) continue;
        var ai2 = ay2 * N + ax2;
        опас[ai2] = (опас[ai2] | 0) + 1;
      }
    }

    /* ---------- проходимость и BFS ---------- */
    var стены = new Array(SZ);
    for (i = 0; i < SZ; i++) стены[i] = стенаCh(M[i]) ? 1 : 0;
    стены[mi] = 0;

    function мягкоЗанято(n) {
      if (стены[n]) return 1;
      if (занятоВраг[n]) return 1;
      if (занятоСвой[n] && !освобождают[n]) return 1;
      if (бронь[n]) return 1;
      return 0;
    }

    function bfs(старт) {
      var d = new Array(SZ);
      for (var j = 0; j < SZ; j++) d[j] = -1;
      var q = [старт], h = 0; d[старт] = 0;
      while (h < q.length) {
        var cur = q[h++], cd = d[cur], cx = ix(cur), cy = iy(cur);
        for (var t = 0; t < 4; t++) {
          var nx = cx + DIRS[t][0], ny = cy + DIRS[t][1];
          if (nx < 0 || ny < 0 || nx >= N || ny >= N) continue;
          var ni = ny * N + nx;
          if (d[ni] !== -1 || стены[ni]) continue;
          d[ni] = cd + 1; q.push(ni);
        }
      }
      return d;
    }

    var Dme = bfs(mi);
    var Dbase = bfs(baseI);

    function идти(ni) {
      var dir = null;
      for (var t = 0; t < 4; t++) {
        if (mx + DIRS[t][0] === ix(ni) && my + DIRS[t][1] === iy(ni)) { dir = DIRS[t][2]; break; }
      }
      if (dir === null) { RS[я.id] = [mi, mi]; return готово({ тип: "ждать" }); }
      RS[я.id] = [mi, ni];
      return готово({ тип: "идти", куда: dir });
    }
    function стоять(d) { RS[я.id] = [mi, mi]; return готово(d); }

    /* ---------- соседи ---------- */
    var соседи = [], врагиРядом = [];
    for (i = 0; i < 4; i++) {
      var nx2 = mx + DIRS[i][0], ny2 = my + DIRS[i][1];
      if (nx2 < 0 || ny2 < 0 || nx2 >= N || ny2 >= N) continue;
      var ni2 = ny2 * N + nx2;
      соседи.push({ i: ni2, d: DIRS[i][2] });
      if (занятоВраг[ni2]) врагиРядом.push({ i: ni2, d: DIRS[i][2] });
    }

    /* ---------- застревание ---------- */
    if (память.lp === mi) память.st = (память.st | 0) + 1; else память.st = 0;
    память.lp = mi;
    память.slot = slot;
    var застрял = память.st | 0;

    /* ---------- мгновенные действия ---------- */
    if (carry && mi === baseI) {
      общая.s = (общая.s | 0) + 1;
      память.tgt = null;
      мойTgt = -1;
      CARRY = 0;
      return стоять({ тип: "положить" });
    }
    if (!carry && едаЗдесь > 0) {
      память.tgt = null;
      мойTgt = mi;
      CARRY = 1;                                   // со следующего хода я гружёный
      if (F[mi]) {
        var ост_ед = (F[mi][0] | 0) - 1;
        if (ост_ед > 0) F[mi] = [ост_ед, ход, F[mi][2]]; else delete F[mi];
      }
      return стоять({ тип: "взять" });
    }

    /* ---------- бой ---------- */
    function лучшийВраг() {
      var b = null, bs = 1e9;
      for (var t = 0; t < врагиРядом.length; t++) {
        var vi = врагиРядом[t].i;
        var s = ((Dbase[vi] >= 0) ? Dbase[vi] : манх(vi, baseI)) * 4 + t;
        if (s < bs) { bs = s; b = врагиРядом[t]; }
      }
      return b;
    }
    var вр = врагиРядом.length ? лучшийВраг() : null;
    var dВрБаза = вр ? ((Dbase[вр.i] >= 0) ? Dbase[вр.i] : манх(вр.i, baseI)) : 99;

    // Бьём с толком: у своей базы (защита), на еде (сбиваем груз/отгоняем)
    // или на своей половине. Дальние драки на чужой земле — потеря темпа.
    var стоитБить = false;
    if (вр && !carry && hp >= 2) {
      if (dВрБаза <= 6) стоитБить = true;                    // враг лезет к базе
      else if (F[вр.i]) стоитБить = true;                    // стоит на нашей еде
      else if (перевес(вр.i) >= -1 && hp >= 3) стоитБить = true; // наша половина
    }
    if (стоитБить) return стоять({ тип: "бить", куда: вр.d });

    if (вр && !carry && hp <= 1) {
      var бег = -1, бегСч = -1e9;
      for (i = 0; i < соседи.length; i++) {
        var s1 = соседи[i].i;
        if (мягкоЗанято(s1)) continue;
        var сч = -(опас[s1] | 0) * 30;
        for (var q2 = 0; q2 < врагиРядом.length; q2++) сч += манх(s1, врагиРядом[q2].i) * 10;
        if (Dbase[s1] >= 0) сч -= Dbase[s1] * 2;
        сч += (хеш(ход * 31 + slot * 7 + i) % 3);
        if (сч > бегСч) { бегСч = сч; бег = s1; }
      }
      if (бег >= 0) return идти(бег);
      return стоять({ тип: "бить", куда: вр.d });
    }

    /* ---------- выбор цели ---------- */
    var цель = -1;

    if (carry) {
      цель = baseI;
    } else {
      /* динамическое жадное распределение куч между свободными муравьями */
      var едоки = [];                              // {id, pos, D, tgt}
      едоки.push({ id: я.id | 0, pos: mi, D: Dme, tgt: (память.tgt === 0 || память.tgt) ? (память.tgt | 0) : -1 });
      for (k in P) if (P.hasOwnProperty(k)) {
        var pe = P[k];
        if (!pe || pe.length < 4) continue;
        if ((k | 0) === (я.id | 0)) continue;
        if (ход - (pe[3] | 0) > 1) continue;        // старая запись — муравей мог погибнуть
        if (pe[2]) continue;                       // гружёный идёт на базу, кучи не занимает
        var px = pe[0] | 0, py = pe[1] | 0;
        if (px < 0 || py < 0 || px >= N || py >= N) continue;
        var pi = py * N + px;
        if (стенаCh(M[pi])) continue;
        едоки.push({ id: k | 0, pos: pi, D: null, tgt: (pe.length > 4 && pe[4] >= 0) ? (pe[4] | 0) : -1 });
        if (едоки.length >= 5) break;
      }
      for (i = 1; i < едоки.length; i++) едоки[i].D = bfs(едоки[i].pos);

      var кучи = [];
      for (k in F) if (F.hasOwnProperty(k)) {
        var fi0 = k | 0, ent0 = F[k];
        if (!ent0) continue;
        var cnt0 = ent0[0] | 0;
        if (cnt0 < 1) continue;
        if (cnt0 > 4) cnt0 = 4;
        кучи.push({ i: fi0, cap: cnt0, g: ent0[2] | 0 });
      }

      // k — сколько наших уже назначено на эту кучу (антипробка)
      function ценаЕды(ед, куча, kk) {
        var dd = ед.D ? ед.D[куча.i] : -1;
        if (dd < 0) return 1e9;
        if (dd > ост + 1) return 1e9;                     // даже дойти не успеем
        var db = (Dbase[куча.i] >= 0) ? Dbase[куча.i] : манх(куча.i, baseI);
        var ш = dd * 10 + db * 3 + kk * 18;               // очередь к одной куче — пробка

        if (куча.g === 1) ш += 8;                         // догадка на своей половине — почти верна
        else if (куча.g === 2) ш += 45;                   // догадка на чужой — ненадёжна

        var adv = перевес(куча.i);                        // >0 — ближе к нам
        // спорная еда — «сейчас или никогда»: своя никуда не денется
        var риск = (adv >= 0) ? Math.max(0, 10 - adv) : Math.max(0, 10 + adv * 2);
        ш -= риск * 2.5;
        if (adv < -4) ш += 12;                            // глубоко под чужой базой — дорого

        if (dd + db + 1 > ост) ш += 180;                  // доставить не успеем — только в руки
        if ((опас[куча.i] | 0) > 0) ш += 15;
        if (ед.tgt === куча.i) ш -= 18;                    // липкость: без метаний
        return ш;
      }

      var назначен = {}, счКучи = {}, мояКуча = -1, сделано = 0;
      while (сделано < едоки.length) {
        var bS = 1e9, bA = -1, bP = -1;
        for (var ai = 0; ai < едоки.length; ai++) {
          if (назначен[ai]) continue;
          for (var pj = 0; pj < кучи.length; pj++) {
            var kk0 = счКучи[pj] | 0;
            if (kk0 >= кучи[pj].cap) continue;
            var ц0 = ценаЕды(едоки[ai], кучи[pj], kk0);
            if (ц0 >= 1e9) continue;
            if (ц0 < bS - 1e-9 ||
              (Math.abs(ц0 - bS) < 1e-9 && bA >= 0 &&
                (едоки[ai].id < едоки[bA].id ||
                  (едоки[ai].id === едоки[bA].id && кучи[pj].i < кучи[bP].i)))) {
              bS = ц0; bA = ai; bP = pj;
            }
          }
        }
        if (bA < 0) break;
        назначен[bA] = 1; сделано++;
        счКучи[bP] = (счКучи[bP] | 0) + 1;
        if (bA === 0) { мояКуча = кучи[bP].i; break; }
      }
      if (мояКуча >= 0) цель = мояКуча;
    }

    /* ---------- разведка неосмотренных клеток ---------- */
    if (цель < 0) {
      var якоряБаза = [[12, 3], [3, 12], [7, 7], [11, 11]];
      var a = якоряБаза[slot % 4];
      var ax = a[0], ay = a[1];
      if (bx > 7) { ax = N - 1 - ax; ay = N - 1 - ay; }
      var якорь = idx(ax, ay);

      var чужие = [];
      for (k in EX) if (EX.hasOwnProperty(k) && k !== String(я.id)) {
        var ct = EX[k] | 0;
        if (ct >= 0) чужие.push(ct);
      }

      var лучшU = -1, лучшUС = 1e9;
      for (i = 0; i < SZ; i++) {
        if (виделCh(M[i]) || стенаCh(M[i])) continue;   // осмотрено или стена
        var du = Dme[i];
        if (du < 0) continue;
        if (du > ост) continue;
        var ц = du * 2 + манх(i, якорь);
        // еду ищем прежде всего там, откуда её реально донести
        var dbU = (Dbase[i] >= 0) ? Dbase[i] : манхXY(i, bx, by);
        if (dbU * 2 + du > ост) ц += 40;
        ц += Math.max(0, dbU - 13) * 4;
        for (var q3 = 0; q3 < чужие.length; q3++) {
          var раз = манх(i, чужие[q3]);
          if (раз < 10) ц += (10 - раз) * 2;
        }
        if (ц < лучшUС || (ц === лучшUС && i < лучшU)) { лучшUС = ц; лучшU = i; }
      }
      if (лучшU >= 0) цель = лучшU;
      else if (mi !== якорь && Dme[якорь] >= 0) цель = якорь;
      else {
        var ц2 = idx(7, 7);
        цель = (mi !== ц2 && Dme[ц2] >= 0) ? ц2 : baseI;
      }
      EX[я.id] = цель;
    }

    память.tgt = carry ? null : цель;
    мойTgt = carry ? -1 : цель;

    /* ---------- шаг к цели ---------- */
    if (цель === mi) {
      if (вр && !carry && hp >= 2) return стоять({ тип: "бить", куда: вр.d });
      if (carry && (опас[mi] | 0) > 0) {
        // с грузом под ударом стоять нельзя: удар выбивает еду
        var уход = -1, уходСч = 1e18;
        for (i = 0; i < соседи.length; i++) {
          var s4 = соседи[i].i;
          if (мягкоЗанято(s4)) continue;
          var сч4 = (опас[s4] | 0) * 100 + ((Dbase[s4] >= 0) ? Dbase[s4] : 60) * 5 + (хеш(ход * 71 + я.id * 13 + i) % 3);
          if (сч4 < уходСч) { уходСч = сч4; уход = s4; }
        }
        if (уход >= 0) return идти(уход);
        if (вр && hp >= 2) return стоять({ тип: "бить", куда: вр.d });
      }
      return стоять({ тип: "ждать" });
    }

    var D = (цель === baseI) ? Dbase : bfs(цель);
    var текущ = (D[mi] >= 0) ? D[mi] : 1e9;
    var подУдаром = (опас[mi] | 0) > 0;
    var вес = carry ? 45 : (hp <= 2 ? 20 : 5);   // как сильно боимся клеток под ударом
    var свободно = (carry && подУдаром) || застрял >= 2;

    var шаг = -1, шагСч = 1e18;
    for (i = 0; i < соседи.length; i++) {
      var s2 = соседи[i].i;
      if (мягкоЗанято(s2)) continue;
      var dn = (D[s2] >= 0) ? D[s2] : (1000 + манх(s2, цель));
      if (!свободно) {
        if (dn > текущ) continue;                              // назад — только если зажали
        if (dn === текущ && застрял < 1 && !подУдаром) continue;
      }
      var сч2 = dn * 10 + (опас[s2] | 0) * вес + (хеш(ход * 131 + я.id * 17 + i) % 3);
      if (сч2 < шагСч) { шагСч = сч2; шаг = s2; }
    }

    if (шаг < 0 && застрял >= 3) {              // совсем зажали — любой свободный сосед
      шагСч = 1e18;
      for (i = 0; i < соседи.length; i++) {
        var s3 = соседи[i].i;
        if (мягкоЗанято(s3)) continue;
        var сч3 = (опас[s3] | 0) * вес + (хеш(ход * 977 + я.id * 41 + i) % 7);
        if (сч3 < шагСч) { шагСч = сч3; шаг = s3; }
      }
    }

    if (шаг >= 0) return идти(шаг);

    // идти некуда
    if (вр && hp >= 2) return стоять({ тип: "бить", куда: вр.d });
    return стоять({ тип: "ждать" });

  } catch (err) {
    return готово({ тип: "ждать" });
  }
}
