function решить(вход) {
  try {
    const W = вход.размер || 15;
    const TOTAL = W * W;
    const me = вход.я;
    const base = вход.моя_база;
    const enemyBase = вход.чужая_база;
    const turn = вход.ход;
    const maxTurns = вход.всего_ходов || 150;
    const turnsLeft = maxTurns - turn;

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

    function toIdx(x, y) { return y * W + x; }
    function toCoord(idx) { return { x: idx % W, y: (idx / W) | 0 }; }
    function manhattan(x1, y1, x2, y2) { return Math.abs(x1 - x2) + Math.abs(y1 - y2); }

    let общая = вход.общая || {};
    if (!общая.walls || общая.walls.length !== TOTAL) {
      общая.walls = new Array(TOTAL).fill(0); // 0: unknown, 1: wall, 2: open
      общая.food = new Array(TOTAL).fill(0);
      общая.seen = new Array(TOTAL).fill(0);
    }

    if (общая.turn !== turn) {
      общая.turn = turn;
      общая.reserved = {}; // idx -> antId
      общая.intentions = {}; // antId -> targetIdx
      общая.myAnts = {};
    }
    общая.reserved = общая.reserved || {};
    общая.intentions = общая.intentions || {};
    общая.myAnts = общая.myAnts || {};
    общая.myAnts[me.id] = { x: me.x, y: me.y, hp: me.здоровье, load: me.груз };

    const visibleMap = {};
    const visibleEnemies = [];
    let currentCellFood = 0;

    // 1. Обработка видимости и симметрии 180°
    for (let i = 0; i < вход.видно.length; i++) {
      const cell = вход.видно[i];
      const idx = toIdx(cell.x, cell.y);
      visibleMap[idx] = cell;

      const symX = W - 1 - cell.x;
      const symY = W - 1 - cell.y;
      const symIdx = toIdx(symX, symY);

      общая.seen[idx] = 1;
      общая.food[idx] = cell.еда || 0;

      if (cell.что === "стена") {
        общая.walls[idx] = 1;
        общая.walls[symIdx] = 1;
      } else {
        общая.walls[idx] = 2;
        if (общая.walls[symIdx] === 0) общая.walls[symIdx] = 2;
      }

      if (cell.x === me.x && cell.y === me.y) {
        currentCellFood = cell.еда || 0;
      } else if (cell.что === "враг") {
        visibleEnemies.push(cell);
      }
    }

    // Позиции своих муравьев на текущем ходу
    const occupiedByFriend = {};
    for (let i = 0; i < вход.видно.length; i++) {
      const c = вход.видно[i];
      if (c.что === "свой" && !(c.x === me.x && c.y === me.y)) {
        occupiedByFriend[toIdx(c.x, c.y)] = true;
      }
    }

    // Предварительный расчет дистанций от базы через BFS
    function bfsDistances(startX, startY) {
      const dists = new Int16Array(TOTAL).fill(-1);
      const q = [toIdx(startX, startY)];
      dists[toIdx(startX, startY)] = 0;
      let head = 0;
      while (head < q.length) {
        const cIdx = q[head++];
        const cx = cIdx % W;
        const cy = (cIdx / W) | 0;
        const cd = dists[cIdx];
        for (let i = 0; i < 4; i++) {
          const nx = cx + DIRS[i].dx;
          const ny = cy + DIRS[i].dy;
          if (nx < 0 || nx >= W || ny < 0 || ny >= W) continue;
          const nIdx = toIdx(nx, ny);
          if (общая.walls[nIdx] === 1 || dists[nIdx] !== -1) continue;
          dists[nIdx] = cd + 1;
          q.push(nIdx);
        }
      }
      return dists;
    }

    const distToBase = bfsDistances(base.x, base.y);

    // Действие: положить груз на базе
    if (me.x === base.x && me.y === base.y && me.груз > 0) {
      delete общая.intentions[me.id];
      return { действие: { тип: "положить" }, память: вход.память, общая: общая };
    }

    // Действие: взять еду под собой
    if (me.груз === 0 && currentCellFood > 0 && !(me.x === base.x && me.y === base.y)) {
      delete общая.intentions[me.id];
      общая.food[toIdx(me.x, me.y)] = Math.max(0, currentCellFood - 1);
      return { действие: { тип: "взять" }, память: вход.память, общая: общая };
    }

    // Проверка соседних врагов (Бой)
    let bestAttackDir = null;
    let maxAttackPriority = -1;

    for (let i = 0; i < DIRS.length; i++) {
      const dir = DIRS[i];
      const nx = me.x + dir.dx;
      const ny = me.y + dir.dy;
      if (nx < 0 || nx >= W || ny < 0 || ny >= W) continue;
      const cell = visibleMap[toIdx(nx, ny)];
      if (cell && cell.что === "враг") {
        let pri = 10;
        if (cell.еда > 0) pri += 100; // Сбить еду с врага
        if (me.груз === 0) pri += 30; // Без груза мы свободный боец
        if (pri > maxAttackPriority) {
          maxAttackPriority = pri;
          bestAttackDir = dir.d;
        }
      }
    }

    // Если мы на базе с грузом 0 - обязательно уходим, освобождая базу
    const isOnBaseEmpty = (me.x === base.x && me.y === base.y && me.груз === 0);

    // Если с грузом стоим прямо у базы - шаг на базу
    if (me.груз > 0) {
      for (let i = 0; i < DIRS.length; i++) {
        const dir = DIRS[i];
        if (me.x + dir.dx === base.x && me.y + dir.dy === base.y) {
          const tIdx = toIdx(base.x, base.y);
          общая.reserved[tIdx] = me.id;
          return { действие: { тип: "идти", куда: dir.d }, память: вход.память, общая: общая };
        }
      }
    }

    // Если враг несет еду - бьем его немедленно
    if (bestAttackDir && maxAttackPriority >= 100) {
      return { действие: { тип: "бить", куда: bestAttackDir }, память: вход.память, общая: общая };
    }

    // Если мы без груза и враг рядом, и мы не на базе
    if (bestAttackDir && me.груз === 0 && !isOnBaseEmpty && maxAttackPriority >= 30) {
      // Если рядом враг и у нас есть здоровье - можно ударить, либо идти за едой если она важнее
      if (currentCellFood === 0 && me.здоровье >= 2) {
        return { действие: { тип: "бить", куда: bestAttackDir }, память: вход.память, общая: общая };
      }
    }

    // Функция поиска пути к цели через BFS
    function findPath(targetCheckFn, preferFn) {
      const q = [{ x: me.x, y: me.y, firstDir: null, firstIdx: -1, dist: 0 }];
      const visited = new Uint8Array(TOTAL);
      visited[toIdx(me.x, me.y)] = 1;
      let head = 0;
      let bestChoice = null;
      let bestScore = -Infinity;

      while (head < q.length) {
        const curr = q[head++];

        if (curr.firstDir !== null && targetCheckFn(curr.x, curr.y, curr.dist)) {
          const score = preferFn ? preferFn(curr.x, curr.y, curr.dist) : -curr.dist;
          if (score > bestScore) {
            bestScore = score;
            bestChoice = { dir: curr.firstDir, nextIdx: curr.firstIdx, targetIdx: toIdx(curr.x, curr.y) };
          }
          if (!preferFn) return bestChoice;
        }

        for (let i = 0; i < 4; i++) {
          const dir = DIRS[i];
          const nx = curr.x + dir.dx;
          const ny = curr.y + dir.dy;
          if (nx < 0 || nx >= W || ny < 0 || ny >= W) continue;
          const nIdx = toIdx(nx, ny);

          if (visited[nIdx] || общая.walls[nIdx] === 1) continue;

          if (curr.firstDir === null) {
            const cell = visibleMap[nIdx];
            if (cell && (cell.что === "стена" || cell.что === "свой")) continue;
            if (cell && cell.что === "враг" && me.груз > 0) continue;
            if (общая.reserved[nIdx] !== undefined) continue;
          }

          visited[nIdx] = 1;
          q.push({
            x: nx,
            y: ny,
            firstDir: curr.firstDir === null ? dir.d : curr.firstDir,
            firstIdx: curr.firstIdx === -1 ? nIdx : curr.firstIdx,
            dist: curr.dist + 1
          });
        }
      }
      return bestChoice;
    }

    // Режим с грузом: несем на базу
    if (me.груз > 0) {
      delete общая.intentions[me.id];
      const move = findPath((x, y) => x === base.x && y === base.y, null);
      if (move) {
        общая.reserved[move.nextIdx] = me.id;
        return { действие: { тип: "идти", куда: move.dir }, память: вход.память, общая: общая };
      }
    } else {
      // Режим без груза: сбор еды
      const claimedTargets = {};
      for (const id in общая.intentions) {
        if (parseInt(id, 10) !== me.id) {
          const tidx = общая.intentions[id];
          claimedTargets[tidx] = (claimedTargets[tidx] || 0) + 1;
        }
      }

      const foodMove = findPath(
        (x, y, d) => {
          const idx = toIdx(x, y);
          if (x === base.x && y === base.y) return false;
          const foodAmt = общая.food[idx] || 0;
          const claims = claimedTargets[idx] || 0;
          if (foodAmt > claims) {
            const dtb = distToBase[idx];
            if (dtb !== -1) {
              // Успеваем донести до базы
              if (d + dtb + 1 <= turnsLeft) return true;
              // Либо на последних ходах успеваем просто взять в руки
              if (d <= turnsLeft) return true;
            }
          }
          return false;
        },
        (x, y, d) => {
          const idx = toIdx(x, y);
          const dtb = distToBase[idx] !== -1 ? distToBase[idx] : 15;
          const foodAmt = общая.food[idx] || 0;
          return 5000 - (d * 1.8 + dtb * 1.0) + foodAmt * 5;
        }
      );

      if (foodMove) {
        общая.intentions[me.id] = foodMove.targetIdx;
        общая.reserved[foodMove.nextIdx] = me.id;
        return { действие: { тип: "идти", куда: foodMove.dir }, память: вход.память, общая: общая };
      }

      // Разведка неизвестных клеток / тумана
      const exploreMove = findPath(
        (x, y) => общая.seen[toIdx(x, y)] === 0 && общая.walls[toIdx(x, y)] !== 1,
        (x, y, d) => {
          const distToEnemyBase = manhattan(x, y, enemyBase.x, enemyBase.y);
          return 2000 - d - distToEnemyBase * 0.5;
        }
      );

      if (exploreMove) {
        общая.reserved[exploreMove.nextIdx] = me.id;
        return { действие: { тип: "идти", куда: exploreMove.dir }, память: вход.память, общая: общая };
      }
    }

    // Если враг рядом - атакуем
    if (bestAttackDir) {
      return { действие: { тип: "бить", куда: bestAttackDir }, память: вход.память, общая: общая };
    }

    // Запасной шаг в любую свободную клетку (особенно важно сойти с базы)
    for (let i = 0; i < DIRS.length; i++) {
      const dir = DIRS[i];
      const nx = me.x + dir.dx;
      const ny = me.y + dir.dy;
      if (nx >= 0 && nx < W && ny >= 0 && ny < W) {
        const nIdx = toIdx(nx, ny);
        const cell = visibleMap[nIdx];
        if (общая.walls[nIdx] !== 1 &&
            общая.reserved[nIdx] === undefined &&
            !occupiedByFriend[nIdx] &&
            (!cell || cell.что !== "стена")) {
          общая.reserved[nIdx] = me.id;
          return { действие: { тип: "идти", куда: dir.d }, память: вход.память, общая: общая };
        }
      }
    }

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