#include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>
#include <bitset>
#include <cassert>
#include <ctime>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
// adjust problem by problem
const double EPS=1e-8;
const double PI=acos(-1.0);
#ifdef __GNUC__
int popcount(int n){return __builtin_popcount(n);}
int popcount(ll n){return __builtin_popcountll(n);}
#endif
#ifndef __GNUC__
template<class T> int popcount(T n){int cnt=0;while(n){if(n%2)cnt++;n/=2;}return cnt;}
#endif
template<class T>int SIZE(T a){return a.size();}
template<class T>string IntToString(T num){string res;stringstream ss;ss<<num;return ss.str();}
template<class T>T StringToInt(string str){T res=0;for(int i=0;i<SIZE(str);i++)res=(res*10+str[i]-'0');return res;}
template<class T>T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template<class T>T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> void PrintSeq(T &a,int sz){for(int i=0;i<sz;i++){cout<<a[i];if(sz==i+1)cout<<endl;else cout<<' ';}}
bool EQ(double a,double b){return abs(a-b)<EPS;}
void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}
vector<string> split(string str,char del){
  vector<string> res;
  for(int i=0,s=0;i<SIZE(str);i++){
    if(str[i]==del){if(i-s!=0)res.push_back(str.substr(s,i-s));s=i+1;}
    else if(i==SIZE(str)-1){res.push_back(str.substr(s));}
  }
  return res;
}

int W,H;
char field[20][20];
int dists[51][51][51][51];

struct Sit{
  int self;
  int rocks[3];
  int ccost;
  Sit(){}
  Sit(int s,int r1,int r2,int r3,int c){
    self=s;
    rocks[0]=r1;
    rocks[1]=r2;
    rocks[2]=r3;
    ccost=c;
  }
};

void solve(){
  for(int i=0;i<H;i++)for(int j=0;j<W;j++)cin>>field[i][j];
  int posToIdx[20][20];
  vector<pii> idxToPos;
  vector<pii> rocks;
  set<int> goals;
  int idx=0;
  int sy,sx;
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      if(field[i][j]!='#'){
        posToIdx[i][j]=idx++;
        idxToPos.push_back(pii(i,j));
      }
      else posToIdx[i][j]=-1;
      if(field[i][j]=='*'){
        rocks.push_back(pii(i,j));
        field[i][j]='.';
      }
      else if(field[i][j]=='_'){
        goals.insert(posToIdx[i][j]);
        field[i][j]='.';
      }
      else if(field[i][j]=='@'){
        sy=i;
        sx=j;
        field[i][j]='.';
      }
    }
  }
  queue<Sit> q;
  memset(dists,-1,sizeof(dists));
  q.push(Sit(posToIdx[sy][sx],posToIdx[rocks[0].first][rocks[0].second],posToIdx[rocks[1].first][rocks[1].second],posToIdx[rocks[2].first][rocks[2].second],0));
  dists[posToIdx[sy][sx]][posToIdx[rocks[0].first][rocks[0].second]][posToIdx[rocks[1].first][rocks[1].second]][posToIdx[rocks[2].first][rocks[2].second]]=0;
  while(q.size()){
    Sit sit=q.front();q.pop();
    int cy=idxToPos[sit.self].first;
    int cx=idxToPos[sit.self].second;
    // goal判定
    bool ok=true;
    for(int i=0;i<3;i++)
      if(!goals.count(sit.rocks[i]))ok=false;
    if(ok){
      cout<<sit.ccost<<endl;
      return;
    }
    char nowField[20][20];
    for(int i=0;i<4;i++){
      for(int i=0;i<H;i++)for(int j=0;j<W;j++)nowField[i][j]=field[i][j];
      for(int i=0;i<3;i++)nowField[idxToPos[sit.rocks[i]].first][idxToPos[sit.rocks[i]].second]='*';
      int ny=cy+dy[i];
      int nx=cx+dx[i];
      if(ny>=0&&nx>=0&&ny<H&&nx<W&&nowField[ny][nx]!='#'){
        int nSelfIdx=posToIdx[ny][nx];
        Sit nsit;
        nsit.self=nSelfIdx;
        if(nowField[ny][nx]=='.'){
          for(int j=0;j<3;j++)nsit.rocks[j]=sit.rocks[j];
          if(dists[nSelfIdx][nsit.rocks[0]][nsit.rocks[1]][nsit.rocks[2]]==-1){
            dists[nSelfIdx][nsit.rocks[0]][nsit.rocks[1]][nsit.rocks[2]]=sit.ccost+1;
            nsit.ccost=sit.ccost+1;
            q.push(nsit);
          }
        }
        else if(nowField[ny][nx]=='*'){
          int nny=ny+dy[i];
          int nnx=nx+dx[i];
          if(nowField[nny][nnx]!='.')continue;
          nowField[ny][nx]='.';
          nowField[nny][nnx]='*';
          int pos=0;
          for(int k=0;k<H;k++)
            for(int l=0;l<W;l++)
              if(nowField[k][l]=='*')
                nsit.rocks[pos++]=posToIdx[k][l];
          if(dists[nSelfIdx][nsit.rocks[0]][nsit.rocks[1]][nsit.rocks[2]]==-1){
            dists[nSelfIdx][nsit.rocks[0]][nsit.rocks[1]][nsit.rocks[2]]=sit.ccost+1;
            nsit.ccost=sit.ccost+1;
            q.push(nsit);
          }
        }
      }
    }
  }
}

int main(){

  while(cin>>W>>H&&(W|H))solve();
  
  return 0;
}