#include <algorithm>
#include <cmath>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#include <cassert>

using namespace std;

#include <bitset>

#define LOG(...) printf(__VA_ARGS__)
//#define LOG(...)
#define FOR(i,a,b) for(int i=(int)(a);i<(int)(b);++i)
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())
#define RSORT(c) sort((c).rbegin(),(c).rend())
#define CLR(a) memset((a), 0 ,sizeof(a))


typedef long long ll;
typedef unsigned long long ull;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vb> vvb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int dx[] = {-1,0,1,0}; const int dy[] = {0,1,0,-1};

const int MAXW = 20 + 2;
const int MAXH = 20 + 2;

#define INF 1e9

char field[MAXH][MAXW];

struct P{
    int p, cost, reach;

    bool operator > (const P& p) const {
        return cost > p.cost;
    }
};

struct Q{
    int x, y, cost;
};

struct Edge{
    int p, cost;
};

int main() {
    int w, h;
    while(cin >> w >> h, w|h){
        fill_n((char *)field, (MAXH) * (MAXW), 'X');

        int robot;
        vector<pii> gb;

        REP(y, h){
            REP(x, w) {
                char c;
                cin >> c;
                switch(c){
                    case 'o':
                        robot = gb.size();
                    case '*':
                        gb.push_back({x + 1, y + 1});
                        break;
                }
                field[y + 1][x + 1] = c;
            }
        }

        vector<vector<Edge>> E(gb.size() + 1);

        REP(i, gb.size()){
            pii p = gb[i];
            queue<Q> que;
            que.push({p.first, p.second, 0});
            bool reach[MAXH][MAXW] = {false};
            while(!que.empty()){
                Q q = que.front(); que.pop();
                reach[q.y][q.x] = true;

                REP(j, 4){
                    int sx = q.x + dx[j];
                    int sy = q.y + dy[j];
                    switch(field[sy][sx]){
                        case '*':
                            if(!reach[sy][sx]) {
                                REP(idx, gb.size()) {
                                    if (gb[idx].first == sx && gb[idx].second == sy) {
                                        E[i].push_back({idx, q.cost + 1});
                                        break;
                                    }
                                }
                            }
                        case '.':
                        case 'o':
                            if(!reach[sy][sx]) {
                                reach[sy][sx] = true;
                                que.push({sx, sy, q.cost + 1});
                            }
                            break;
                    }
                }
            }
        }
        if(E[robot].size() < gb.size() - 1){
            cout << -1 << endl;
            continue;
        }

        priority_queue<P, vector<P>, greater<P>> que;
        que.push({robot, 0, (1 << robot)});
        vvi G(gb.size() + 1, vi(1<<gb.size() , INF));
        G[robot][(1 << robot)] = 0;

        while(!que.empty()){
            P p = que.top(); que.pop();

//            LOG("%d, %d|||||| cost:%d reach:", gb[p.p].first, gb[p.p].second, p.cost);
//            cout << static_cast<bitset<10>>(p.reach) << endl;

            if(p.reach == (1 << gb.size()) - 1){
                cout << p.cost << endl;
                break;
            }

            for(Edge e : E[p.p]){
                int next_cost = p.cost + e.cost;
                int next_reach = p.reach | (1 << e.p);
                if (G[e.p][next_reach] > next_cost){
                    G[e.p][next_reach] = next_cost;
                    if(p.reach & (1<<e.p)) continue;
                    que.push({e.p, next_cost, next_reach});
                }
            }
        }

    }

}

Measured memory_bytes: 1316