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

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
struct S{
  int x, y;
  int cx[3];
  int cy[3];
  int SW;
  int cost;
  S(){
    SW = 0;
    cx[0] = cx[1] = cx[2] = 10;
    cy[0] = cy[1] = cy[2] = 10;
    cost = 0;
  }
  bool operator < (const S& s) const {
    if(x != s.x) return x < s.x;
    if(y != s.y) return y < s.y;
    REP(i, 3) if(cx[i] != s.cx[i]) return cx[i] < s.cx[i];
    REP(i, 3) if(cy[i] != s.cy[i]) return cy[i] < s.cy[i];
    return SW < s.SW;
  }
};
void print(S& s){
  printf("x = %d y = %d SW = %d cost = %d c = (%d, %d) (%d, %d) (%d, %d)\n", s.x, s.y, s.SW, s.cost, s.cx[0], s.cy[0], s.cx[1], s.cy[1], s.cx[2], s.cy[2]);
}
int main(){
  int H, W;
  while(cin >> H >> W && H){
    vector<string> grid(H);
    REP(i, H) cin >> grid[i];
    int WC = 0;
    int CC = 0;
    int wx[3], wy[3];
    S start;
    REP(y, H)REP(x, W){
      if(grid[y][x] == '@'){
        start.x = x, start.y = y;
      }
      if(grid[y][x] == 'w'){
        wx[WC] = x, wy[WC] = y;
        start.SW |= 1 << WC;
        WC++;
      }
      if(grid[y][x] == 'c'){
        start.cx[CC] = x;
        start.cy[CC] = y;
        CC++;
      }
    }
    set<S> setS;
    deque<S> que;
    que.push_back(start);
    setS.insert(start);
    bool NG = true;
    while(!que.empty()){
      S s = que.front(); que.pop_front();
      if(grid[s.y][s.x] == 'E'){
        cout << s.cost << endl;
        NG = false;
        break;
      }
      REP(r, 4){
        int nx = s.x + dx[r];
        int ny = s.y + dy[r];
        if(!valid(nx, ny, W, H)) continue;
        S next = s;
        bool move = true;
        REP(i, CC){
          if(nx == s.cx[i] && ny == s.cy[i]){
            move = false;
            //container move
            int xx = nx, yy = ny;
            while(true){
              xx += dx[r];
              yy += dy[r];
              if(grid[yy][xx] == '#'){
                xx -= dx[r];
                yy -= dy[r];
                goto C1;
              }
              REP(j, CC) if(i != j && s.cx[j] == xx && s.cy[j] == yy){
                xx -= dx[r];
                yy -= dy[r];
                goto C1;
              }
              REP(i, WC) if(s.SW >> i & 1 && wx[i] == xx && wy[i] == yy){
                next.SW ^= 1 << i;
                xx = 10;
                yy = 10;
                goto C1;
              }
            }
C1:
            next.cx[i] = xx, next.cy[i] = yy;
            //if(!get(next, cost)){
            if(!setS.count(next)){
              //set_x(next, true, cost);
              setS.insert(next);
              que.push_front(next);
            }
          }
        }
        // player move
        REP(i, WC) if(s.SW >> i & 1 && wx[i] == nx && wy[i] == ny) move = false;
        if(!move || grid[ny][nx] == '#') continue;
        next.x = nx, next.y = ny;
        if(!setS.count(next)){
          next.cost += 1;
          setS.insert(next);
          que.push_back(next);
        }
      }
    }
    if(NG) cout << -1 << endl;
  }
  return 0;
}

Measured memory_bytes: 6812