#include <bits/stdc++.h>
using namespace std;

const long double EPS = 1e-10;
const int H = 500;
const int W = 500;
const int dy[4] = {-1,0,1,0};
const int dx[4] = {0,-1,0,1};

struct P{
  int x, y;
  P(int x=0, int y=0):x(x),y(y){}
};

struct state{  
  int x, y, cnt;
  state(int x=0, int y=0, int cnt=0):x(x),y(y),cnt(cnt){}
  bool operator < (const state &s) const {
    return cnt < s.cnt;
  }
};

int w, h, dis_go[H][W], dis_sp[H][W];
long double cnt_nowall;
P st, go;
vector<P> v;
bool wall[H][W];

void init_dis(){
  queue<state> q;
  state u, u2;

  cnt_nowall = 0;
  for(int i=1;i<h-1;i++){
    for(int j=1;j<w-1;j++){
      dis_go[i][j] = dis_sp[i][j] = -1;
      cnt_nowall += !wall[i][j];
    }
  }

  for(q.push(state(go.x, go.y, 0));!q.empty();){
    u = q.front();
    q.pop();
    for(int i=0;i<4;i++){
      u2 = state(u.x+dx[i], u.y+dy[i], u.cnt+1);
      if(!wall[u2.y][u2.x] && (dis_go[u2.y][u2.x] == -1 || dis_go[u2.y][u2.x] > u2.cnt)){
        dis_go[u2.y][u2.x] = u2.cnt;
        q.push(u2);
      }
    }
  }

  for(int i=0;i<v.size();i++){
    for(q.push(state(v[i].x, v[i].y, 0));!q.empty();){
      u = q.front();
      q.pop();
      for(int j=0;j<4;j++){
        u2 = state(u.x+dx[j], u.y+dy[j], u.cnt+1);
        if(!wall[u2.y][u2.x] && (dis_sp[u2.y][u2.x] == -1 || dis_sp[u2.y][u2.x] > u2.cnt)){
          dis_sp[u2.y][u2.x] = u2.cnt;
          q.push(u2);
        }
      }
    }
  }
}

long double a_ruiseki[H*W], b_ruiseki[H*W], g_ruiseki[H*W];

void calc_exp_init(){
  vector<state> pv;

  for(int i=1;i<h-1;i++){
    for(int j=1;j<w-1;j++){
      if(!wall[i][j]){
        pv.push_back(state(j, i, dis_go[i][j] - dis_sp[i][j]));
        if(dis_sp[i][j] == -1) pv[pv.size()-1].cnt = -2;
        else if(dis_go[i][j] == -1) pv[pv.size()-1].cnt = -1;
        else if(dis_go[i][j] < dis_sp[i][j]) pv[pv.size()-1].cnt = 0;
      }
    }
  }      
  fill(a_ruiseki, a_ruiseki+H*W, 0);
  fill(b_ruiseki, b_ruiseki+H*W, 0);
  fill(g_ruiseki, g_ruiseki+H*W, 0);

  sort(pv.begin(), pv.end());

  a_ruiseki[h*w-1] = 1.0;
  for(int i=0;i<pv.size();i++){
    if(pv[i].cnt == -2){  // dis_sp[i][j] == -1
      g_ruiseki[0] += (long double)dis_go[pv[i].y][pv[i].x] / cnt_nowall;

    } else if(pv[i].cnt == -1){ // dis_go[i][j] == -1
      b_ruiseki[h*w-1] += (long double)dis_sp[pv[i].y][pv[i].x] / cnt_nowall;
      a_ruiseki[h*w-1] -= (long double)1.0 / cnt_nowall;

    } else if(pv[i].cnt == 0){
      //b_ruiseki[h*w-1] += (long double)dis_sp[pv[i].y][pv[i].x] / cnt_nowall;
      g_ruiseki[1] += (long double)dis_go[pv[i].y][pv[i].x] / cnt_nowall;

    } else {
      b_ruiseki[pv[i].cnt] += (long double)dis_sp[pv[i].y][pv[i].x] / cnt_nowall;
      g_ruiseki[pv[i].cnt+1] += (long double)dis_go[pv[i].y][pv[i].x] / cnt_nowall;
      a_ruiseki[pv[i].cnt] -= (long double)1.0 / cnt_nowall;
    }
  }

  for(int i=0;i<h*w-1;i++){
    g_ruiseki[i+1] += g_ruiseki[i];
  }
  for(int i=h*w-1;i>0;i--){
    b_ruiseki[i-1] += b_ruiseki[i];
    a_ruiseki[i-1] += a_ruiseki[i];
  }
}

long double calc_exp(int base){
  long double a = 1.0, b = 0.0, exp_go = 0.0;
    
  /*
  for(int i=1;i<h-1;i++){
    for(int j=1;j<w-1;j++){
      if(!wall[i][j]){
        if(dis_go[i][j] == -1 || dis_sp[i][j] != -1 && dis_go[i][j] >= dis_sp[i][j] + base){
          a -= 1.0 / cnt_nowall;
          b += (long double)dis_sp[i][j] / cnt_nowall;
        } else {
          exp_go += (long double)dis_go[i][j] / cnt_nowall;
        }
      }
    }
  }
  */

  //printf("g %d: %.10Lf %.10Lf\n", base, g_ruiseki[base], exp_go);
  //printf("b %d: %.10Lf %.10Lf\n", base, b_ruiseki[base], b);
  //printf("a %d: %.10Lf %.10Lf\n", base, a_ruiseki[base], a);
  
  //return (b + exp_go) / a;
  return (b_ruiseki[base] + g_ruiseki[base]) / a_ruiseki[base];
}

long double solve(){
  long double ans = -1;

  init_dis();
  calc_exp_init();

  if(dis_go[st.y][st.x] != -1) ans = dis_go[st.y][st.x];

  int cnt = 0;

 
  for(int i=2;i<(h-2)*(w-2);i++){
    if(dis_sp[st.y][st.x] == -1 || dis_go[st.y][st.x] != -1 && dis_go[st.y][st.x] < dis_sp[st.y][st.x] + i){
      break;
    }  
    if(ans < -0.9) ans = calc_exp(i) + dis_sp[st.y][st.x];
    else ans = min(ans, calc_exp(i) + dis_sp[st.y][st.x]);
  }
  
  
  /*
  if(dis_sp[st.y][st.x] != -1){
    int le = 2, ri = dis_go[st.y][st.x] - dis_sp[st.y][st.x] + 1, mid1, mid2;
    long double res0, res1, res2;
    if(dis_go[st.y][st.x] == -1) ri = (h-2) * (w-2);
    while(ri - le >= 4){
      mid1 = (le * 2 + ri) / 3;
      mid2 = (le + ri * 2) / 3;
      res0 = calc_exp(le) + dis_sp[st.y][st.x];
      res1 = calc_exp(mid1) + dis_sp[st.y][st.x];
      res2 = calc_exp(mid2) + dis_sp[st.y][st.x];
      if(mid2 - mid1 <= 1) break;
      if(res0 >= res1 - EPS && res1 >= res2 - EPS) le = mid1;
      else ri = mid2;
    }
    for(int i=le;i<le+5;i++) {
      if(dis_go[st.y][st.x] != -1 && dis_go[st.y][st.x] < dis_sp[st.y][st.x] + i) break;
      if(ans < -0.9) ans = calc_exp(i) + dis_sp[st.y][st.x];
      else ans = min(ans, calc_exp(i) + dis_sp[st.y][st.x]);
    }
  }
  */

  return ans;
}

int main(){
  char c;
  while(cin >> w >> h){
    v.clear();
    int cnt = 0;
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        cin >> c;
        wall[i][j] = true;
        if(c == 's') st = P(j, i), wall[i][j] = false;
        else if(c == 'g') go = P(j, i);
        else if(c == '*') v.push_back(P(j, i)), cnt++;
        else if(c == '.') wall[i][j] = false;
      }
    }    

    printf("%.12Lf\n", solve());
  }
}

Measured memory_bytes: 18016