Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

var (
	sc = bufio.NewScanner(os.Stdin)
)

type Color int

const (
	ColorBlack Color = iota
	ColorRed
)

type Node struct {
	ID    int
	X, Y  int
	Color Color
	Nexts []*Node
}

func main() {
	for sc.Scan() {
		if sc.Text() == "0 0" {
			break
		}
		chunks := strings.Split(sc.Text(), " ")
		w, _ := strconv.Atoi(chunks[0])
		h, _ := strconv.Atoi(chunks[1])

		// Initialize map
		m := map[int]map[int]*Node{}
		for x := 1; x <= w; x++ {
			m[x] = map[int]*Node{}
			for y := 1; y <= h; y++ {
				m[x][y] = &Node{ID: x + y*w, X: x, Y: y}
			}
		}
		for x := 1; x <= w; x++ {
			for y := 1; y <= h; y++ {
				nexts := []*Node{}
				if n, ok := m[x-1][y]; ok {
					nexts = append(nexts, n)
				}
				if n, ok := m[x][y-1]; ok {
					nexts = append(nexts, n)
				}
				if n, ok := m[x+1][y]; ok {
					nexts = append(nexts, n)
				}
				if n, ok := m[x][y+1]; ok {
					nexts = append(nexts, n)
				}
				m[x][y].Nexts = nexts
			}
		}

		// Set colors
		queue := []*Node{}
		touchedIDs := map[int]struct{}{}
		for y := 1; y <= h; y++ {
			sc.Scan()
			for i, c := range sc.Text() {
				switch c {
				case '.', '@':
					n := m[i+1][y]
					n.Color = ColorBlack
					if c == '@' {
						queue = append(queue, n)
						touchedIDs[n.ID] = struct{}{}
					}
				case '#':
					m[i+1][y].Color = ColorRed
				}
			}
		}

		// Search
		visitedIDs := map[int]struct{}{}
		for {
			if len(queue) == 0 {
				break
			}
			n := queue[0]
			queue = queue[1:]
			visitedIDs[n.ID] = struct{}{}
			for _, next := range n.Nexts {
				if next.Color == ColorRed {
					continue
				}
				if _, ok := touchedIDs[next.ID]; !ok {
					queue = append(queue, next)
					touchedIDs[n.ID] = struct{}{}
				}
			}
		}
		fmt.Println(len(visitedIDs))
	}
}

C++: #include <algorithm>
#include <iostream>
#include <vector>
#include <string>
using namespace std;

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

int W, H;
vector<string> field;

int dfs(int y, int x) {
    int ans = 1; field[y][x] = '#';
    for (int k = 0; k < 4; k++) {
        int ny = y + dy[k], nx = x + dx[k];
        if (0 <= ny && ny < H && 0 <= nx && nx < W) {
            if (field[ny][nx] == '.') ans += dfs(ny, nx);
        }
    }
    return ans;
}

int main() {
    while (cin >> W >> H, W) {
        field.resize(H);
        for (int i = 0; i < H; i++) cin >> field[i];
        for (int y = 0; y < H; y++) for (int x = 0; x < W; x++) {
            if (field[y][x] == '@') cout << dfs(y, x) << endl;
        }
    }
    return 0;
}

C++: #include<iostream>
using namespace std;
typedef pair<int, int> pii;
pii dxdy[]={{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
char fld[21][21];
int used[20][20];
int W, H;
 
int rec(int i, int j){
 
   if(fld[i][j]=='#') return 0;
   if(used[i][j]) return 0;
   used[i][j]=1;
   int ret=0;
   for(pii dd: dxdy){
      int ni=i+dd.first;
      int nj=j+dd.second;
      if(!(0<=ni&&ni<H&&0<=nj&&nj<W)) continue;
      ret+=rec(ni, nj);
   }
 
   return ret+1;
}
 
int main(){
 
   while(1){
      cin>> W>> H;
      if(!(H||W)) break;
      int sx, sy;
      for(int i=0; i<H; i++){
         for(int j=0; j<W; j++){
            cin>> fld[i][j];
            if(fld[i][j]=='@'){
               sy=i;
               sx=j;
               fld[i][j]='.';
            }
         }
      }
 
      for(int i=0; i<20; i++)for(int j=0; j<20; j++) used[i][j]=0;
      cout<< rec(sy, sx)<< endl;
   }
 
   return 0;
}

C++: #include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;

typedef struct point {
  int x, y;
} POINT;

int W, H;
char str[20][21];
queue<POINT> que;

bool input() {
  int i;

  scanf("%d %d", &W, &H);
  if (!W && !H) return false;

  for (i = 0; i < H; i++) {
    scanf("%s", str[i]);
  }

  return true;
}

int main() {
  int i, j, cnt;
  POINT p, q;

  while (input()) {

    while (!que.empty()) que.pop();
    for (i = 0; i < H; i++) {
      for (j = 0; j < W; j++) {
        if (str[i][j] == '@') {
          p.x = j;
          p.y = i;
          que.push(p);
          i = H;
          j = W;
        }
      }
    }

    cnt = 0;
    while (!que.empty()) {
      p = que.front();
      que.pop();
      if (p.x < 0 || W <= p.x || p.y < 0 || H <= p.y) continue;
      if (str[p.y][p.x] == '#') continue;
      cnt++;
      str[p.y][p.x] = '#';
      q.x = p.x;
      q.y = p.y+1;
      que.push(q);
      q.x = p.x+1;
      q.y = p.y;
      que.push(q);
      q.x = p.x-1;
      q.y = p.y;
      que.push(q);
      q.x = p.x;
      q.y = p.y-1;
      que.push(q);
    }

    printf("%d\n", cnt);

  }

  return 0;
}

C++: #include<bits/stdc++.h>

using namespace std;

int n,m;
int cnt;
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
char t[20][20];

void fanc(int x,int y){
	cnt++;
	int ny,nx;
	t[y][x]=',';
	for(int i=0;i<4;i++){
		ny=y+dy[i];
		nx=x+dx[i];
		if(ny>=0&&nx>=0&&ny<m&&nx<n&&t[ny][nx]=='.'){
			fanc(nx,ny);
		}
	}
}

int main(){
	
	while(1){
		
		cin >> n >> m;
		
		if(n==0) break;
		
		int nx,ny;
		for(int i=0;i<m;i++){
			for(int j=0;j<n;j++){
				cin >> t[i][j];
				if(t[i][j]=='@'){
					ny=i;nx=j;
				}
			}
		}
		cnt=0;
		fanc(nx,ny);
		cout << cnt << endl;
	}
	return 0;
}

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

struct dsu {
  const int n;
  vector<int> p, sz;
  dsu(int _n) : n(_n), p(n, -1), sz(n, 1) {}
  int root(int v) { return p[v] == -1 ? v : v = root(p[v]); }
  void unite(int u, int v) {
    u = root(u), v = root(v);
    if (u == v) return;
    if (sz[u] < sz[v]) swap(u, v);
    p[v] = u;
    sz[u] += sz[v];
  }
  int size(int v) { return sz[root(v)]; }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int h, w;
  while (cin >> w >> h, w) {
    vector<string> s(h);
    for (auto&& e : s) {
      cin >> e;
    }
    dsu d(h * w);
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (s[i][j] != '#') {
          if (i + 1 < h and s[i + 1][j] != '#') {
            d.unite(i * w + j, (i + 1) * w + j);
          }
          if (j + 1 < w and s[i][j + 1] != '#') {
            d.unite(i * w + j, i * w + (j + 1));
          }
        }
      }
    }
    for (int i = 0; i < h; ++i) {
      for (int j = 0; j < w; ++j) {
        if (s[i][j] == '@') {
          cout << d.size(i * w + j) << '\n';
        }
      }
    }
  }
}

C++: #include<cstdio>
#include<cstdlib>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n) for (int i=0;i<(n);i++)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)

using namespace std;
int ans = 0;

void bfs(char **tile, int w, int h){
  ans++;
  tile[w][h] = '#';

  if(tile[w][h-1] == '.')
  bfs(tile, w, h-1);

  if(tile[w][h+1] == '.')
  bfs(tile, w, h+1);

  if(tile[w-1][h] == '.')
  bfs(tile, w-1, h);

  if(tile[w+1][h] == '.')
  bfs(tile, w+1, h);

  return;
}


int main(){
  int W,H,index_w,index_h;

  while(true){
    cin >> W >> H;
    if(W == 0 && H == 0) break;

    char **tile;
    tile = new char* [H+2];
    REP(i,H+2) tile[i] = new char[W+2];

    REP(i,H+2){
      REP(j,W+2){
        if(i == 0 || i == H+1 || j == 0 || j == W+1) tile[i][j] = '#'; //sentry
        else scanf(" %c",&tile[i][j]);

        if(tile[i][j] == '@') {
          index_h = j;
          index_w = i;
        }

      }
    }
    ans = 0;
    bfs(tile,index_w,index_h);
    
    REP(i,H) delete[] tile[i];
    delete[] tile;
    
    cout << ans << endl;
  }
  return 0;
}