#include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

typedef pair<int,int> ii;

const int IINF = INT_MAX;

struct Data{
  ii hero,rock[3];
  int step;
  Data(ii hero=ii(0,0),ii r1=ii(0,0),ii r2=ii(0,0),ii r3=ii(0,0),int step=0):hero(hero),step(step){
    rock[0] = r1, rock[1] = r2, rock[2] = r3;
  }
  bool operator < ( const Data& data ) const {
    return step > data.step;
  }
};

int H,W,Index[20][20],mindist[60][60][60][60];
char G[20][20];
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};

bool isValid(int x,int y){ return 0 <= x && x < W && 0 <= y && y < H; }

int main(){
  while( cin >> W >> H, W|H ){
    vector<ii> R,M;
    ii sp = ii(0,0);
    int dex = 0;
    rep(i,H) rep(j,W) {
      cin >> G[i][j];
      if( G[i][j] == '#' ) continue;
      Index[i][j] = dex++;
      if( G[i][j] == '@' ) sp = ii(j,i);
      else if( G[i][j] == '_' ) M.push_back(ii(j,i));
      else if( G[i][j] == '*' ) R.push_back(ii(j,i));
    }
    rep(i,dex) rep(j,dex) rep(k,dex) rep(l,dex) mindist[i][j][k][l] = IINF;
    sort(M.begin(),M.end());
    sort(R.begin(),R.end());
    int tmp_a = Index[sp.second][sp.first];
    int tmp_b = Index[R[0].second][R[0].first];
    int tmp_c = Index[R[1].second][R[1].first];
    int tmp_d = Index[R[2].second][R[2].first];
    mindist[tmp_a][tmp_b][tmp_c][tmp_d] = 0;
    priority_queue<Data> Q;
    Q.push(Data(sp,R[0],R[1],R[2],0));
    while( !Q.empty() ){
      Data data = Q.top(); Q.pop();
      tmp_a = Index[data.hero.second][data.hero.first];
      tmp_b = Index[data.rock[0].second][data.rock[0].first];
      tmp_c = Index[data.rock[1].second][data.rock[1].first];
      tmp_d = Index[data.rock[2].second][data.rock[2].first];
      if( mindist[tmp_a][tmp_b][tmp_c][tmp_d] < data.step ) continue;
      if( data.rock[0] == M[0] && data.rock[1] == M[1] && data.rock[2] == M[2] ) {
        cout << data.step << endl;
        break;
      }
      rep(i,4){
        Data tmp = data;
        tmp.hero.first += dx[i], tmp.hero.second += dy[i];
        if( G[tmp.hero.second][tmp.hero.first] == '#' ) continue;
        if( tmp.hero == tmp.rock[0] || tmp.hero == tmp.rock[1] || tmp.hero == tmp.rock[2] ) {
          if( tmp.hero == tmp.rock[0] ) tmp.rock[0].first += dx[i], tmp.rock[0].second += dy[i];
          if( tmp.hero == tmp.rock[1] ) tmp.rock[1].first += dx[i], tmp.rock[1].second += dy[i];
          if( tmp.hero == tmp.rock[2] ) tmp.rock[2].first += dx[i], tmp.rock[2].second += dy[i];
          if( G[tmp.rock[0].second][tmp.rock[0].first] == '#' ) continue;
          if( G[tmp.rock[1].second][tmp.rock[1].first] == '#' ) continue;
          if( G[tmp.rock[2].second][tmp.rock[2].first] == '#' ) continue;
          sort(tmp.rock,tmp.rock+3);
          int hi = Index[tmp.hero.second][tmp.hero.first];
          int r1i = Index[tmp.rock[0].second][tmp.rock[0].first];
          int r2i = Index[tmp.rock[1].second][tmp.rock[1].first];
          int r3i = Index[tmp.rock[2].second][tmp.rock[2].first];
          if( mindist[hi][r1i][r2i][r3i] > data.step + 1 ) {
            mindist[hi][r1i][r2i][r3i] = data.step + 1;
            Q.push(Data(tmp.hero,tmp.rock[0],tmp.rock[1],tmp.rock[2],data.step+1));
          }
        } else {
          int hi = Index[tmp.hero.second][tmp.hero.first];
          int r1i = Index[tmp.rock[0].second][tmp.rock[0].first];
          int r2i = Index[tmp.rock[1].second][tmp.rock[1].first];
          int r3i = Index[tmp.rock[2].second][tmp.rock[2].first];
          if( mindist[hi][r1i][r2i][r3i] > data.step + 1 ) {
            mindist[hi][r1i][r2i][r3i] = data.step + 1;
            Q.push(Data(tmp.hero,tmp.rock[0],tmp.rock[1],tmp.rock[2],data.step+1));
          }
        }

      }
    }

  }
  return 0;
}

Measured memory_bytes: 48460