#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
using namespace std;

#define MAX_H 20
#define MAX_W 20
#define MAX_G 10

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

struct S {
    int y, x, t;
    S(int y, int x, int t) : y(y), x(x), t(t) {}
};

#define INF (1<<28)

string field[MAX_H];
int number[MAX_H][MAX_W];
int graph[MAX_G][MAX_G];
int dp[MAX_G][1<<MAX_G]; 
int h, w;
int garbage_count;

int solve(int v, int s) {
    if (dp[v][s] != INF) return dp[v][s];
    if (s == ((1<<garbage_count)-1)) return 0;
    int min_cost = INF;
    for (int i = 0; i < garbage_count; i++) {
        if (s & (1<<i)) continue;
        min_cost = min(min_cost, solve(i, (s + (1<<i))) + graph[v][i]);
    }
    return dp[v][s] = min_cost;
}

int main() {
    while (cin >> w >> h) {
        if (w == 0 && h == 0) break;
        memset(graph, -1, sizeof(graph));
        memset(number, -1, sizeof(number));
        for (int i = 0; i < MAX_G; i++) for (int j = 0; j < (1<<MAX_G); j++) dp[i][j] = INF;
        for (int i = 0; i < h; i++) 
            cin >> field[i];
        
        int cur = 1;
        for (int i = 0; i < h; i++) 
            for (int j = 0; j < w; j++) {
                if (field[i][j] == 'o') number[i][j] = 0;
                if (field[i][j] == '*') number[i][j] = cur++;
            }
        garbage_count = cur;

        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (field[i][j] == 'o' || field[i][j] == '*') {
                    bool visited[h][w]; memset(visited, 0, sizeof(visited));
                    queue<S> q;
                    q.push(S(i, j, 0)); visited[i][j] = true;
                    int remain_garbage = garbage_count;
                    while (!q.empty()) {
                        S s = q.front(); q.pop();
                        if (field[s.y][s.x] == 'o' || field[s.y][s.x] == '*') {
                            graph[number[i][j]][number[s.y][s.x]] = s.t;
                            remain_garbage--;
                            //if (remain_garbage == 0) break;
                        }
                        for (int k = 0; k < 4; k++) {
                            int ny = s.y + dy[k];
                            int nx = s.x + dx[k];
                            if (0 <= ny && ny < h && 0 <= nx && nx < w && !visited[ny][nx] && field[ny][nx] != 'x') {
                                visited[ny][nx] = true;
                                q.push(S(ny, nx, s.t+1));
                            }
                        }
                    }
                }
            }
        }

        bool possible = true;
        for (int i = 0; i < garbage_count; i++) 
            for (int j = 0; j < garbage_count; j++) 
                if (graph[i][j] == -1) {
                    possible = false;
                    break;
                }

//        for (int i = 0; i < garbage_count; i++) {
//            for (int j = 0; j < garbage_count; j++) {
//                cout << graph[i][j] << ' ';
//            }
//            cout << endl;
//        }

        if (!possible) cout << -1 << endl;
        else cout << solve(0, 0) << endl;
    }
    return 0;
}

Measured memory_bytes: 1272