function решить(в) {
  var я=в.я, ход=в.ход, N=в.размер, конец=в.всего_ходов||150;
  var база=в.моя_база, чужая=в.чужая_база;
  var п=в.память&&typeof в.память==="object"?в.память:{};
  var о=в.общая&&typeof в.общая==="object"?в.общая:{};
  var S=N*N, dirs=[
    {n:"С",x:0,y:-1},{n:"В",x:1,y:0},
    {n:"Ю",x:0,y:1},{n:"З",x:-1,y:0}
  ];

  if(typeof о.m!=="string"||о.m.length!==S) о.m=new Array(S+1).join("?");
  if(!о.f||typeof о.f!=="object") о.f={};
  if(!о.c||typeof о.c!=="object") о.c={};
  if(!о.mw||typeof о.mw!=="object") о.mw={};

  var карта=о.m.split(""), еда=о.f, цели=о.c, движения=о.mw, вид={};

  function idx(x,y){return y*N+x}
  function key(x,y){return x+","+y}
  function ok(x,y){return x>=0&&y>=0&&x<N&&y<N}
  function md(x,y,a,b){return Math.abs(x-a)+Math.abs(y-b)}
  function cell(x,y){return вид[key(x,y)]}
  function сохранить(a){
    о.m=карта.join("");
    return {действие:a,память:п,общая:о};
  }
  function act(t,d){
    var a={тип:t};
    if(d) a.куда=d;
    if(t==="идти"){
      for(var z=0;z<4;z++) if(dirs[z].n===d){
        движения[я.id]=[ход,key(я.x+dirs[z].x,я.y+dirs[z].y)];
        break;
      }
    }else delete движения[я.id];
    return сохранить(a);
  }

  var i,k,c;
  for(i=0;i<в.видно.length;i++){
    c=в.видно[i];
    if(!ok(c.x,c.y)) continue;
    k=key(c.x,c.y);
    вид[k]=c;
    карта[idx(c.x,c.y)]=c.что==="стена"?"#":".";
    if(c.еда>0) еда[k]=[c.x,c.y,c.еда,ход];
    else delete еда[k];
  }

  for(k in еда)
    if(!еда[k]||ход-еда[k][3]>28) delete еда[k];
  for(k in цели)
    if(!цели[k]||цели[k][1]<ход-1||!еда[цели[k][0]]) delete цели[k];
  for(k in движения)
    if(!движения[k]||движения[k][0]!==ход) delete движения[k];

  function врагиРядом(x,y){
    var n=0;
    for(var d=0;d<4;d++){
      var q=cell(x+dirs[d].x,y+dirs[d].y);
      if(q&&q.что==="враг") n++;
    }
    return n;
  }

  function своиРядом(x,y){
    var n=0;
    for(var d=0;d<4;d++){
      var q=cell(x+dirs[d].x,y+dirs[d].y);
      if(q&&q.что==="свой") n++;
    }
    return n;
  }

  function зарезервировано(x,y){
    var q=key(x,y);
    for(var id in движения)
      if(String(id)!==String(я.id)&&движения[id]&&
         движения[id][0]===ход&&движения[id][1]===q) return true;
    return false;
  }

  function можно(x,y,tx,ty,safe){
    if(!ok(x,y)||карта[idx(x,y)]==="#") return false;
    var q=cell(x,y);
    if(q&&(q.что==="стена"||q.что==="враг")) return false;
    if(q&&q.что==="свой"&&!(x===tx&&y===ty)) return false;
    if(зарезервировано(x,y)&&!(x===tx&&y===ty)) return false;
    if(safe&&врагиРядом(x,y)>0) return false;
    return true;
  }

  function путь(tx,ty,safe){
    if(!ok(tx,ty)) return null;
    if(я.x===tx&&я.y===ty) return {d:null,l:0};
    var qx=[я.x],qy=[я.y],ql=[0],h=0;
    var seen=new Array(S), first=new Array(S);
    seen[idx(я.x,я.y)]=1;

    while(h<qx.length){
      var x=qx[h],y=qy[h],len=ql[h++];
      var sh=(ход+я.id*3+x*5+y*7)&3;
      for(var j=0;j<4;j++){
        var s=dirs[(j+sh)&3],nx=x+s.x,ny=y+s.y;
        if(!ok(nx,ny)) continue;
        var ni=idx(nx,ny);
        if(seen[ni]||!можно(nx,ny,tx,ty,safe)) continue;
        seen[ni]=1;
        first[ni]=(x===я.x&&y===я.y)?s.n:first[idx(x,y)];
        if(nx===tx&&ny===ty) return {d:first[ni],l:len+1};
        qx.push(nx); qy.push(ny); ql.push(len+1);
      }
    }
    return null;
  }

  function локальныйШаг(tx,ty,опасность){
    var bd=null,bs=1e9;
    for(var j=0;j<4;j++){
      var s=dirs[(j+ход+я.id)&3],nx=я.x+s.x,ny=я.y+s.y;
      if(!можно(nx,ny,-1,-1,false)) continue;
      var e=врагиРядом(nx,ny);
      var q=cell(nx,ny);
      var sc=md(nx,ny,tx,ty)+e*(опасность?300:75);
      if(!я.груз&&q&&q.еда>0) sc-=20;
      if(карта[idx(nx,ny)]==="?") sc-=2;
      if(q&&q.что==="свой") sc+=40;
      sc+=((j+я.id+ход)&3)*.01;
      if(sc<bs){bs=sc;bd=s.n}
    }
    return bd;
  }

  var здесь=cell(я.x,я.y);

  if(я.груз&&я.x===база.x&&я.y===база.y){
    delete цели[я.id]; delete п.t;
    return act("положить");
  }
  if(!я.груз&&здесь&&здесь.еда>0){
    delete цели[я.id]; delete п.t;
    return act("взять");
  }

  var рядом=[];
  for(i=0;i<4;i++){
    c=cell(я.x+dirs[i].x,я.y+dirs[i].y);
    if(c&&c.что==="враг")
      рядом.push({d:dirs[i],c:c,поддержка:своиРядом(c.x,c.y)});
  }

  if(рядом.length){
    if(я.груз||я.здоровье===1){
      var escape=null,es=1e9;
      for(i=0;i<4;i++){
        var sd=dirs[(i+ход+я.id)&3],ex=я.x+sd.x,ey=я.y+sd.y;
        if(!можно(ex,ey,-1,-1,false)) continue;
        var danger=врагиРядом(ex,ey);
        var score=danger*500+md(ex,ey,база.x,база.y);
        if(score<es){es=score;escape=sd.n}
      }
      if(escape&&es<500) return act("идти",escape);
    }

    var choice=рядом[0],best=-1e9;
    for(i=0;i<рядом.length;i++){
      var e=рядом[i],sc=(e.c.еда>0?45:0)+e.поддержка*8;
      if(md(e.c.x,e.c.y,база.x,база.y)<=3) sc+=12;
      if(я.здоровье===3) sc+=4;
      sc+=((ход+я.id+i*11)&3);
      if(sc>best){best=sc;choice=e}
    }
    return act("бить",choice.d.n);
  }

  if(я.груз){
    delete цели[я.id]; delete п.t;
    var remain=конец-ход;
    var home=null;
    if(я.здоровье<3||remain<24) home=путь(база.x,база.y,true);
    if(!home) home=путь(база.x,база.y,false);
    if(home&&home.d) return act("идти",home.d);
    var hb=локальныйШаг(база.x,база.y,true);
    return hb?act("идти",hb):act("ждать");
  }

  var counts={};
  for(k in цели){
    var ck=цели[k][0];
    counts[ck]=(counts[ck]||0)+1;
  }

  var bestFood=null,bestRoute=null,bestScore=1e9;
  for(k in еда){
    var f=еда[k];
    if(!f||!ok(f[0],f[1])||f[2]<=0) continue;

    var r=путь(f[0],f[1],я.здоровье===1);
    if(!r) r=путь(f[0],f[1],false);
    if(!r) continue;

    var homeEstimate=md(f[0],f[1],база.x,база.y);
    var canTake=ход+r.l+1<=конец;
    var canDeliver=ход+r.l+homeEstimate+2<=конец;
    if(!canTake) continue;

    var n=counts[k]||0;
    if(цели[я.id]&&цели[я.id][0]===k) n--;
    var over=n>=f[2];
    var age=ход-f[3];
    var sc=r.l+n*7+(over?55:0)-Math.min(f[2],4)*1.7+age*.14;

    if(canDeliver) sc+=homeEstimate*.08;
    else sc+=20-homeEstimate*.12;
    if(п.t===k) sc-=6;
    if(ход>=140&&!canDeliver) sc-=15;
    if(врагиРядом(f[0],f[1])>0) sc+=я.здоровье===1?80:12;

    if(sc<bestScore){
      bestScore=sc; bestFood=k; bestRoute=r;
    }
  }

  if(bestFood&&bestRoute){
    п.t=bestFood;
    цели[я.id]=[bestFood,ход];
    if(bestRoute.d) return act("идти",bestRoute.d);
  }else{
    delete цели[я.id]; delete п.t;
  }

  var role=((я.id%4)+4)%4;
  if(!п.e||typeof п.e!=="object") п.e={q:role*17,s:-99,x:база.x,y:база.y};
  var ex=п.e;

  function новаяЦель(){
    var sx=база.x<чужая.x?1:-1, sy=база.y<чужая.y?1:-1;
    for(var tries=0;tries<12;tries++){
      ex.q=(ex.q+19+role*4)%225;
      var z=(ex.q*73+role*41)%225;
      var gx=z%15,gy=Math.floor(z/15);
      var tx=sx>0?gx:14-gx,ty=sy>0?gy:14-gy;
      if(карта[idx(tx,ty)]!=="#"){
        ex.x=tx;ex.y=ty;ex.s=ход;
        return;
      }
    }
    ex.x=чужая.x;ex.y=чужая.y;ex.s=ход;
  }

  if(!ok(ex.x,ex.y)||(ex.x===я.x&&ex.y===я.y)||ход-ex.s>22)
    новаяЦель();

  var er=путь(ex.x,ex.y,я.здоровье===1);
  if(!er){
    новаяЦель();
    er=путь(ex.x,ex.y,false);
  }

  if(er&&er.d) return act("идти",er.d);

  var tx=role===0?чужая.x:role===1?Math.floor(N/2):role===2?база.x:чужая.x;
  var ty=role===0?Math.floor(N/2):role===1?чужая.y:role===2?чужая.y:база.y;
  var wd=локальныйШаг(tx,ty,я.здоровье===1);
  return wd?act("идти",wd):act("ждать");
}
