/*
  CTU Open Contest 2002
  =====================
  Sample solution for the problem: holes

  Michal Sevcenko, Oct 2002
*/

#include <set>
#include <map>
#include <list>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

class point {
public:
	int x, y;
	point(int x = 0, int y = 0): x(x), y(y) {}
	bool operator ==(const point& p) const { return x == p.x && y == p.y; }
	bool operator <(const point& p) const 
	{ return x < p.x || (x == p.x && y < p.y); }
};

class vertical_cut {
public:
	point top, bottom;
	vertical_cut() {}
	vertical_cut(point top, point bottom): top(top), bottom(bottom)
	{ if (bottom.y < top.y) swap(this->top, this->bottom); }
	bool operator ==(const vertical_cut& c) const { return top == c.top && bottom == c.bottom; }
	bool operator <(const vertical_cut& c) const { return (top < c.top || (top == c.top && bottom < c.bottom)); }
};

class horizontal_cut {
public:
	point left, right;
	horizontal_cut() {}
	horizontal_cut(point left, point right): left(left), right(right)
	{ if (right.x < left.x) swap(this->left, this->right); }
	bool operator ==(const horizontal_cut& c) const { return left == c.left && right == c.right; }
	bool operator <(const horizontal_cut& c) const { return (left < c.left || (left == c.left && right < c.right)); }
};

list<vertical_cut> vcuts;
list<horizontal_cut> hcuts;

vector<vector<short> > matrix;
vector<vector<bool> > v_matrix, h_matrix;

template<class C> void init_matrix(C& buffer, point size)
{
	buffer.clear();
	buffer.resize(size.x);
	for (int x=0; x<size.x; ++x)
		buffer[x].resize(size.y);
}

point remap_cuts()
{
	set<int> xs, ys;
	map<int,int> xmap, ymap;
	point size;

	list<vertical_cut>::iterator vit;
	for (vit=vcuts.begin(); vit!=vcuts.end(); ++vit)
	{
		xs.insert(vit->top.x);
		ys.insert(vit->top.y);
		ys.insert(vit->bottom.y);
	}
	list<horizontal_cut>::iterator hit;
	for (hit=hcuts.begin(); hit!=hcuts.end(); ++hit)
	{
		xs.insert(hit->left.x);
		xs.insert(hit->right.x);
		ys.insert(hit->left.y);
	}
	int i;
	set<int>::iterator sit;
	for (sit=xs.begin(), i=1; sit != xs.end(); ++sit, ++i)
		xmap[*sit] = i;
	size.x = i+2;
	for (sit=ys.begin(), i=1; sit != ys.end(); ++sit, ++i)
		ymap[*sit] = i;
	size.y = i+2;
	
	init_matrix(matrix, size);
	init_matrix(v_matrix, size);
	init_matrix(h_matrix, size);

	for (vit=vcuts.begin(); vit!=vcuts.end(); ++vit)
	{
		vit->top.x = xmap[vit->top.x];
		vit->bottom.x = xmap[vit->bottom.x];
		vit->top.y = ymap[vit->top.y];
		vit->bottom.y = ymap[vit->bottom.y];
		for (int i=vit->top.y; i<vit->bottom.y; ++i)
			v_matrix[vit->top.x][i] = true;
	}
	for (hit=hcuts.begin(); hit!=hcuts.end(); ++hit)
	{
		hit->left.x = xmap[hit->left.x];
		hit->right.x = xmap[hit->right.x];
		hit->left.y = ymap[hit->left.y];
		hit->right.y = ymap[hit->right.y];
		for (int i=hit->left.x; i<hit->right.x; ++i)
			h_matrix[i][hit->left.y] = true;
	}
	for (i=0; i<size.x; ++i)
	{
		h_matrix[i][0] = true;
		h_matrix[i][size.y-1] = true;
	}
	for (i=0; i<size.y; ++i)
	{
		v_matrix[0][i] = true;
		v_matrix[size.x-1][i] = true;
	}

	return size;
}

void flood_fill(int x, int y, short color)
{
	if (matrix[x][y]) return;
	matrix[x][y] = color;
	if (!v_matrix[x][y])
		flood_fill(x-1,y,color);
	if (!v_matrix[x+1][y])
		flood_fill(x+1,y,color);
	if (!h_matrix[x][y])
		flood_fill(x,y-1,color);
	if (!h_matrix[x][y+1])
		flood_fill(x,y+1,color);
}

void flood_fill2(int x, int y, int color,int limit)
{
	if (matrix[x][y] > limit || matrix[x][y] == 1) return;
	matrix[x][y] = color;
	flood_fill2(x-1,y,color,limit);
	flood_fill2(x+1,y,color,limit);
	flood_fill2(x,y-1,color,limit);
	flood_fill2(x,y+1,color,limit);
}


void doit(int n)
{
	vcuts.clear();
	hcuts.clear();
	int i;
	for (i=0; i<n; i++)
	{
		int x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		// vertical cut?
		if (x1 == x2)
			vcuts.push_back(vertical_cut(point(x1,y1), point(x2,y2)));
		else
		// horizonal cut?
		if (y1 == y2)
			hcuts.push_back(horizontal_cut(point(x1,y1), point(x2,y2)));
		else
			throw "general slope cut";
	}
	point size = remap_cuts();
	flood_fill(0,0,1);
	
	int c=2;
	int x,y;
	for (x=1; x<size.x-1; ++x)
	for (y=1; y<size.y-1; ++y)
		if (!matrix[x][y])
			flood_fill(x,y,c++);

	int c1 = c++;
	for (x=1; x<size.x-2; ++x)
	for (y=1; y<size.y-2; ++y)
		flood_fill2(x,y,c++,c1);

	set<int> distinct;
	for (x=1; x<size.x-2; ++x)
	for (y=1; y<size.y-2; ++y)
		distinct.insert(matrix[x][y]);

	cout << "There are " << (distinct.size() - 1) << " holes." << endl;
}

int main()
{
	int n;
	try {
		while (true)
		{
			cin >> n;
			if (n == 0) break;
			doit(n);
		}
	} catch (exception& e) {
		cerr << e.what() << endl;
	}
	return 0;
}
