function решить(в) {
  try {
    var DIRS = { "С": [0, -1], "Ю": [0, 1], "З": [-1, 0], "В": [1, 0] };
    var DLIST = ["С", "В", "Ю", "З"];
    var память = в.память && typeof в.память === "object" ? в.память : {};
    var общая = в.общая && typeof в.общая === "object" ? в.общая : {};
    var я = в.я || { id: 0, x: 1, y: 1, здоровье: 3, груз: 0 };
    var ход = в.ход | 0;
    var N = в.размер || 15;
    var база = в.моя_база || { x: 1, y: 1 };
    var чбаза = в.чужая_база || { x: 13, y: 13 };
    var видно = в.видно || [];
    var left = (в.всего_ходов || 150) - ход;
    var hp = я.здоровье | 0;
    var id = я.id | 0;
    var sx = база.x < 7 ? 1 : -1;
    var sy = база.y < 7 ? 1 : -1;

    function k(x, y) { return x + "," + y; }
    function abs(n) { return n < 0 ? -n : n; }
    function min(a, b) { return a < b ? a : b; }
    function max(a, b) { return a > b ? a : b; }
    function manh(a, b, c, d) { return abs(a - c) + abs(b - d); }
    function clamp(v, a, b) { return v < a ? a : (v > b ? b : v); }
    function rot(seed) {
      var s = seed % 4;
      if (s < 0) s += 4;
      return [DLIST[s], DLIST[(s + 1) % 4], DLIST[(s + 2) % 4], DLIST[(s + 3) % 4]];
    }
    function dirTo(x1, y1, x2, y2) {
      var dx = x2 - x1, dy = y2 - y1;
      if (abs(dx) >= abs(dy) && dx !== 0) return dx > 0 ? "В" : "З";
      if (dy !== 0) return dy > 0 ? "Ю" : "С";
      if (dx !== 0) return dx > 0 ? "В" : "З";
      return "С";
    }

    if (!общая.ok) {
      общая.ok = 1;
      общая.w = {};
      общая.f = {};
      общая.seen = [];
      for (var i0 = 0; i0 < 225; i0++) общая.seen.push(0);
    }
    if (!общая.w) общая.w = {};
    if (!общая.f) общая.f = {};
    if (!общая.seen || общая.seen.length !== 225) {
      общая.seen = [];
      for (var i1 = 0; i1 < 225; i1++) общая.seen.push(0);
    }

    if (общая.T !== ход) {
      общая.L = общая.P || {};
      общая.T = ход;
      общая.I = {};
      общая.P = {};
    }
    общая.P[id] = [я.x, я.y, я.груз | 0, hp];

    var mateMap = {};
    var L = общая.L || {};
    var P = общая.P || {};
    var mid;
    for (mid in L) {
      if (L.hasOwnProperty(mid)) mateMap[mid] = L[mid];
    }
    for (mid in P) {
      if (P.hasOwnProperty(mid)) mateMap[mid] = P[mid];
    }
    mateMap[id] = [я.x, я.y, я.груз | 0, hp];

    var ids = [];
    for (mid in mateMap) {
      if (mateMap.hasOwnProperty(mid)) ids.push(+mid);
    }
    ids.sort(function (a, b) { return a - b; });
    if (ids.length > 4) ids = ids.slice(0, 4);
    var myIndex = ids.indexOf(id);
    if (myIndex < 0) myIndex = abs(id) % 4;

    if (память.lx === я.x && память.ly === я.y) память.stk = (память.stk | 0) + 1;
    else память.stk = 0;
    var stuck = память.stk | 0;

    var foodHere = 0;
    var enList = [];
    var frList = [];
    var adjEn = [];
    var adjFr = 0;
    var occE = {};
    var occF = {};
    var vi, c, ck, si, fx, fy;

    for (vi = 0; vi < видно.length; vi++) {
      c = видно[vi];
      if (!c) continue;
      ck = k(c.x, c.y);
      si = c.y * N + c.x;
      if (si >= 0 && si < 225) общая.seen[si] = ход + 1;
      if (c.что === "стена") {
        общая.w[ck] = 1;
        общая.w[k(N - 1 - c.x, N - 1 - c.y)] = 1;
      }
      if (c.еда > 0 && c.что !== "стена") {
        общая.f[ck] = [c.еда | 0, ход, c.x | 0, c.y | 0];
      } else if (общая.f[ck]) {
        delete общая.f[ck];
      }
      if (c.x === я.x && c.y === я.y) {
        foodHere = c.еда | 0;
      } else if (c.что === "враг") {
        enList.push(c);
        occE[ck] = 1;
        if (manh(я.x, я.y, c.x, c.y) === 1) adjEn.push(c);
      } else if (c.что === "свой") {
        frList.push(c);
        occF[ck] = 1;
        if (manh(я.x, я.y, c.x, c.y) === 1) adjFr++;
      }
    }

    function wall(x, y) {
      if (x < 1 || y < 1 || x > N - 2 || y > N - 2) return true;
      return !!общая.w[k(x, y)];
    }
    function enemyAt(x, y) { return !!occE[k(x, y)]; }
    function friendAt(x, y) { return !!occF[k(x, y)]; }
    function reserved(x, y) {
      var v = общая.I[k(x, y)];
      return v != null && v !== id;
    }
    function nEnAtk(x, y) {
      var n = 0;
      for (var i = 0; i < enList.length; i++) {
        if (manh(x, y, enList[i].x, enList[i].y) === 1) n++;
      }
      return n;
    }
    function nearestEn(x, y) {
      var best = 99, i, d;
      for (i = 0; i < enList.length; i++) {
        d = manh(x, y, enList[i].x, enList[i].y);
        if (d < best) best = d;
      }
      return best;
    }
    function canStep(x, y, force) {
      if (wall(x, y)) return false;
      if (enemyAt(x, y)) return false;
      if (!force && friendAt(x, y)) return false;
      if (!force && reserved(x, y)) return false;
      return true;
    }

    function runBfs(avoidDng) {
      var DIST = [], FST = [], i;
      for (i = 0; i < 225; i++) { DIST[i] = 999; FST[i] = null; }
      var q = [], qi = 0;
      var si0 = я.y * N + я.x;
      DIST[si0] = 0;
      q.push(si0);
      var order = rot(id * 7 + ход * 3 + myIndex + (avoidDng ? 1 : 0));
      while (qi < q.length) {
        var ci = q[qi++];
        var cx = ci % N;
        var cy = (ci / N) | 0;
        var cd = DIST[ci];
        var oi, dnm, dd, nx, ny, ni, nd;
        for (oi = 0; oi < 4; oi++) {
          dnm = order[oi];
          dd = DIRS[dnm];
          nx = cx + dd[0];
          ny = cy + dd[1];
          if (nx < 1 || ny < 1 || nx > N - 2 || ny > N - 2) continue;
          if (wall(nx, ny)) continue;
          if (ci === si0) {
            if (enemyAt(nx, ny)) continue;
            if (stuck < 2 && friendAt(nx, ny)) continue;
            if (stuck < 2 && reserved(nx, ny)) continue;
          }
          if (avoidDng && nEnAtk(nx, ny) > 0) continue;
          ni = ny * N + nx;
          nd = cd + 1;
          if (nd >= DIST[ni]) continue;
          DIST[ni] = nd;
          FST[ni] = ci === si0 ? dnm : FST[ci];
          q.push(ni);
        }
      }
      return { d: DIST, f: FST };
    }

    var cautious = !!(я.груз || hp <= 1);
    var Bsafe = runBfs(cautious);
    var Bany = cautious ? runBfs(false) : Bsafe;

    function dirTowards(tx, ty, safe) {
      var t = ty * N + tx;
      if (t < 0 || t >= 225) return null;
      if (safe && Bsafe.d[t] < 999 && Bsafe.f[t]) return Bsafe.f[t];
      if (Bany.d[t] < 999 && Bany.f[t]) return Bany.f[t];
      return null;
    }
    function distTowards(tx, ty) {
      var t = ty * N + tx;
      if (t < 0 || t >= 225) return 999;
      if (Bsafe.d[t] < 999) return Bsafe.d[t];
      return Bany.d[t];
    }

    function anyStep(preferHome) {
      var best = null, bs = 1e9;
      var order = rot(id * 31 + ход * 17 + stuck * 5 + myIndex);
      for (var i = 0; i < 4; i++) {
        var d = order[i];
        var nx = я.x + DIRS[d][0], ny = я.y + DIRS[d][1];
        if (!canStep(nx, ny, stuck >= 2)) continue;
        var sc = nEnAtk(nx, ny) * 40;
        var dh = manh(nx, ny, база.x, база.y);
        sc += preferHome ? dh * 3 : -dh;
        if (enList.length) sc += (3 - min(nearestEn(nx, ny), 3)) * 8;
        if (reserved(nx, ny)) sc += 12;
        if (friendAt(nx, ny)) sc += 20;
        if (sc < bs) { bs = sc; best = d; }
      }
      return best;
    }

    function bestFlee() {
      var best = null, bs = 1e9;
      var order = rot(ход + myIndex * 5 + 3);
      for (var i = 0; i < 4; i++) {
        var d = order[i];
        var nx = я.x + DIRS[d][0], ny = я.y + DIRS[d][1];
        if (!canStep(nx, ny, true)) continue;
        var sc = nEnAtk(nx, ny) * 50 - nearestEn(nx, ny) * 6;
        if (я.груз) sc += manh(nx, ny, база.x, база.y) * 3;
        else sc -= manh(nx, ny, база.x, база.y);
        if (reserved(nx, ny)) sc += 6;
        if (sc < bs) { bs = sc; best = d; }
      }
      return best;
    }

    function listFoods() {
      var foods = [], fk, info, parts;
      for (fk in общая.f) {
        if (!общая.f.hasOwnProperty(fk)) continue;
        info = общая.f[fk];
        if (!info) continue;
        fx = info[2];
        fy = info[3];
        if (fx == null) {
          parts = fk.split(",");
          fx = +parts[0];
          fy = +parts[1];
        }
        fx = fx | 0;
        fy = fy | 0;
        if (wall(fx, fy)) continue;
        var amt = info[0] | 0;
        if (amt < 1) amt = 1;
        foods.push({
          k: fk, x: fx, y: fy, amt: amt, t: info[1] | 0,
          dHome: manh(fx, fy, база.x, база.y),
          dEn: manh(fx, fy, чбаза.x, чбаза.y)
        });
      }
      return foods;
    }

    function stealCount(fo, myM) {
      var n = 0, m, p, om, oid, car;
      for (m in mateMap) {
        if (!mateMap.hasOwnProperty(m)) continue;
        oid = +m;
        if (oid === id) continue;
        p = mateMap[m];
        if (!p) continue;
        car = p[2] | 0;
        if (car) continue;
        om = manh(p[0] | 0, p[1] | 0, fo.x, fo.y);
        if (om < myM || (om === myM && oid < id)) n++;
      }
      return n;
    }

    function pickFood() {
      var foods = listFoods();
      if (!foods.length) return null;
      if (память.tx != null && память.ty != null) {
        var pk = k(память.tx, память.ty), still = null, i;
        for (i = 0; i < foods.length; i++) {
          if (foods[i].k === pk) { still = foods[i]; break; }
        }
        if (still) {
          var dKeep = distTowards(still.x, still.y);
          var myMk = manh(я.x, я.y, still.x, still.y);
          var stl = stealCount(still, myMk);
          if (dKeep < 999 && dKeep + still.dHome + 1 <= left) {
            if (stl < still.amt || dKeep <= 2) {
              if (dKeep <= 8 || (ход - (память.tt | 0) < 10)) return still;
            }
          }
        }
      }
      var best = null, bestSc = -1e9, f, fo, d1, myM, stl, sc, canDel, visBonus;
      for (f = 0; f < foods.length; f++) {
        fo = foods[f];
        d1 = distTowards(fo.x, fo.y);
        if (d1 >= 999) continue;
        if (d1 + fo.dHome + 1 > left) continue;
        myM = manh(я.x, я.y, fo.x, fo.y);
        stl = stealCount(fo, myM);
        if (stl >= fo.amt && d1 > 1) continue;
        canDel = d1 + fo.dHome + 1 <= left;
        sc = fo.amt * 20 - d1 * 10 - fo.dHome * 4;
        sc -= stl * 22;
        visBonus = (fo.t === ход) ? 18 : 0;
        sc += visBonus;
        if (d1 <= 1) sc += 55;
        else if (d1 <= 2) sc += 28;
        else if (d1 <= 4) sc += 12;
        else if (d1 <= 7) sc += 4;
        if (fo.dHome + 1 < fo.dEn) sc += 18;
        else if (fo.dHome <= fo.dEn) sc += 8;
        else sc -= (fo.dHome - fo.dEn) * 5;
        if (fo.dEn <= 2) sc -= 22;
        if (!canDel) sc -= 30;
        if (ход < 30 && fo.dHome > 10) sc -= 8;
        if (myM <= 2 && fo.t === ход) sc += 20;
        if (sc > bestSc) { bestSc = sc; best = fo; }
      }
      return best;
    }

    function pickExplore() {
      var bestI = -1, bestSc = 1e9;
      var bx, by;
      if (myIndex === 0) { bx = база.x + 8 * sx; by = база.y + 2 * sy; }
      else if (myIndex === 1) { bx = база.x + 2 * sx; by = база.y + 8 * sy; }
      else if (myIndex === 2) { bx = база.x + 7 * sx; by = база.y + 7 * sy; }
      else { bx = база.x + 5 * sx; by = база.y + 5 * sy; }
      bx = clamp(bx, 1, 13);
      by = clamp(by, 1, 13);
      var x, y, i, dd, st, sc, age, dh, de;
      for (y = 1; y <= 13; y++) {
        for (x = 1; x <= 13; x++) {
          if (wall(x, y)) continue;
          i = y * N + x;
          dd = Bany.d[i];
          if (dd < 1 || dd >= 999) continue;
          st = общая.seen[i] | 0;
          sc = dd * 7;
          if (st === 0) sc -= 90;
          else {
            age = ход + 1 - st;
            if (age < 10) sc += 50;
            else sc -= min(age, 70);
          }
          dh = manh(x, y, база.x, база.y);
          de = manh(x, y, чбаза.x, чбаза.y);
          if (de <= 2) sc += 90;
          if (dh > de + 1) sc += 16;
          sc += manh(x, y, bx, by) * 3;
          if (sc < bestSc) { bestSc = sc; bestI = i; }
        }
      }
      if (bestI < 0) return null;
      return Bany.f[bestI];
    }

    var действие = null;
    var dying = hp <= 1 && adjEn.length > 0;

    if (я.груз && я.x === база.x && я.y === база.y) {
      действие = { тип: "положить" };
    } else if (!я.груз && foodHere > 0 && !dying) {
      действие = { тип: "взять" };
    } else if (adjEn.length) {
      if (я.груз || hp <= 1) {
        var fd = bestFlee();
        if (fd) действие = { тип: "идти", куда: fd };
        else if (hp >= 2 && adjEn.length) {
          действие = { тип: "бить", куда: dirTo(я.x, я.y, adjEn[0].x, adjEn[0].y) };
        }
      } else {
        var tgt = adjEn[0], ei, es, bestE = -1, ev, help, fv;
        for (ei = 0; ei < adjEn.length; ei++) {
          ev = adjEn[ei];
          help = 0;
          for (fv = 0; fv < frList.length; fv++) {
            if (manh(frList[fv].x, frList[fv].y, ev.x, ev.y) === 1) help++;
          }
          es = help * 8 + (ev.еда | 0) * 12;
          if (es > bestE) { bestE = es; tgt = ev; }
        }
        действие = { тип: "бить", куда: dirTo(я.x, я.y, tgt.x, tgt.y) };
      }
    }

    if (!действие && я.груз) {
      var dH = dirTowards(база.x, база.y, true);
      if (!dH) dH = dirTowards(база.x, база.y, false);
      if (dH) действие = { тип: "идти", куда: dH };
    }

    if (!действие && !я.груз && я.x === база.x && я.y === база.y) {
      var outA = sx > 0 ? "В" : "З";
      var outB = sy > 0 ? "Ю" : "С";
      var leaveDirs = (myIndex & 1) === 0 ? [outA, outB, DLIST[0], DLIST[1]] : [outB, outA, DLIST[2], DLIST[3]];
      var ld, nxL, nyL;
      for (ld = 0; ld < leaveDirs.length; ld++) {
        if (!DIRS[leaveDirs[ld]]) continue;
        nxL = я.x + DIRS[leaveDirs[ld]][0];
        nyL = я.y + DIRS[leaveDirs[ld]][1];
        if (canStep(nxL, nyL, true)) {
          действие = { тип: "идти", куда: leaveDirs[ld] };
          break;
        }
      }
    }

    var foodT = null;
    if (!действие && !я.груз) {
      foodT = pickFood();
      if (foodT) {
        память.tx = foodT.x;
        память.ty = foodT.y;
        память.tt = ход;
        if (я.x === foodT.x && я.y === foodT.y) {
          if (foodHere > 0 && !dying) действие = { тип: "взять" };
        } else {
          var dFood = dirTowards(foodT.x, foodT.y, hp <= 1);
          if (dFood) действие = { тип: "идти", куда: dFood };
        }
      } else {
        память.tx = null;
        память.ty = null;
      }
    }

    if (!действие && !я.груз && ход < 20 && listFoods().length === 0) {
      var sp = [
        [база.x + 6 * sx, база.y + 2 * sy],
        [база.x + 2 * sx, база.y + 6 * sy],
        [база.x + 6 * sx, база.y + 6 * sy],
        [база.x + 4 * sx, база.y + 4 * sy]
      ][myIndex & 3];
      var txe = clamp(sp[0], 1, 13), tye = clamp(sp[1], 1, 13);
      var dSp = dirTowards(txe, tye, hp <= 1);
      if (dSp) действие = { тип: "идти", куда: dSp };
    }

    if (!действие && !я.груз) {
      var dEx = pickExplore();
      if (dEx) действие = { тип: "идти", куда: dEx };
    }

    if (!действие) {
      var dAny = anyStep(!!я.груз);
      if (dAny) действие = { тип: "идти", куда: dAny };
    }

    if (!действие) действие = { тип: "ждать" };

    if (действие.тип === "идти") {
      var ddF = DIRS[действие.куда];
      if (!ddF) действие = { тип: "ждать" };
      else {
        var nxA = я.x + ddF[0], nyA = я.y + ddF[1];
        if (!canStep(nxA, nyA, stuck >= 2)) {
          var alt = anyStep(!!я.груз);
          if (alt && DIRS[alt] && canStep(я.x + DIRS[alt][0], я.y + DIRS[alt][1], stuck >= 2)) {
            действие = { тип: "идти", куда: alt };
            ddF = DIRS[alt];
            nxA = я.x + ddF[0];
            nyA = я.y + ddF[1];
          } else {
            действие = { тип: "ждать" };
          }
        }
        if (действие.тип === "идти") {
          if (wall(nxA, nyA) || enemyAt(nxA, nyA) || !DIRS[действие.куда]) {
            действие = { тип: "ждать" };
          } else if (stuck < 2 && friendAt(nxA, nyA)) {
            действие = { тип: "ждать" };
          } else {
            общая.I[k(nxA, nyA)] = id;
          }
        }
      }
    }
    if (действие.тип === "бить") {
      var db = DIRS[действие.куда];
      if (!db) действие = { тип: "ждать" };
      else {
        var bx2 = я.x + db[0], by2 = я.y + db[1];
        var okHit = false, eh;
        for (eh = 0; eh < adjEn.length; eh++) {
          if (adjEn[eh].x === bx2 && adjEn[eh].y === by2) okHit = true;
        }
        if (!okHit) действие = { тип: "ждать" };
      }
    }
    if (действие.тип === "взять") {
      if (я.груз || foodHere < 1) действие = { тип: "ждать" };
    }
    if (действие.тип === "положить") {
      if (!я.груз) действие = { тип: "ждать" };
    }
    if (действие.тип !== "идти") {
      общая.I[k(я.x, я.y)] = id;
    }

    память.lx = я.x;
    память.ly = я.y;
    return { действие: действие, память: память, общая: общая };
  } catch (e) {
    return { действие: { тип: "ждать" }, память: (в && в.память) || {}, общая: (в && в.общая) || {} };
  }
}
