#include <set>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cassert>
#include <algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-8;
const double PI=acos(-1);

struct point{
	double x,y;
	point():x(0),y(0){}
	point(double x,double y):x(x),y(y){}
	point operator+(const point &a)const{ return point(x+a.x,y+a.y); }
	point operator-(const point &a)const{ return point(x-a.x,y-a.y); }
	bool operator==(const point &a)const{ return abs(x-a.x)<EPS && abs(y-a.y)<EPS; }
	bool operator!=(const point &a)const{ return abs(x-a.x)>EPS || abs(y-a.y)>EPS; }
};

point operator*(double c,const point &a){ return point(c*a.x,c*a.y); }

inline double dot(const point &a,const point &b){ return a.x*b.x+a.y*b.y; }

inline double cross(const point &a,const point &b){ return a.x*b.y-a.y*b.x; }

inline point rot(const point &a,double theta){ return point(a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta)); }

inline double arg(const point &a){ double t=atan2(a.y,a.x); return t<0?t+2*PI:t; }

struct segment{
	point a,b;
	segment(){}
	segment(const point &a,const point &b):a(a),b(b){}
};

typedef vector<point> polygon;

enum{CCW=1,CW=-1,ON=0};
inline int ccw(const point &a,const point &b,const point &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

inline bool intersect(const segment &S1,const segment &S2){
	if(max(S1.a.x,S1.b.x)+EPS<min(S2.a.x,S2.b.x)
	|| max(S1.a.y,S1.b.y)+EPS<min(S2.a.y,S2.b.y)
	|| max(S2.a.x,S2.b.x)+EPS<min(S1.a.x,S1.b.x)
	|| max(S2.a.y,S2.b.y)+EPS<min(S1.a.y,S1.b.y)) return false;
	return ccw(S1.a,S1.b,S2.a)*ccw(S1.a,S1.b,S2.b)<=0
		&& ccw(S2.a,S2.b,S1.a)*ccw(S2.a,S2.b,S1.b)<=0;
}

inline bool cover(const segment &S,const point &p){
	return abs(cross(S.a-p,S.b-p))<EPS && dot(S.a-p,S.b-p)<EPS;
}

inline point get_intersect(const segment &S1,const segment &S2){
	double a1=cross(S1.b-S1.a,S2.b-S2.a);
	double a2=cross(S1.b-S1.a,S1.b-S2.a);
	if(abs(a1)<EPS){
		if(cover(S1,S2.a)) return S2.a;
		if(cover(S1,S2.b)) return S2.b;
		if(cover(S2,S1.a)) return S1.a;
		return S1.b;
	}
	return S2.a+a2/a1*(S2.b-S2.a);
}

bool is_perm(vector<int> a){
	sort(a.begin(),a.end());
	return unique(a.begin(),a.end())-a.begin()==a.size();
}

vector<int> simulate(point p,const polygon &F,double theta){
	int n=F.size();
	vector<int> res;
	bool used[8]={};
	while(res.size()<n){
		point v(cos(theta),sin(theta));
		segment S(p,p+200*v);

		int i0=-1;
		segment e; // 反射する辺
		point q; // 反射する点
		rep(i,n){
			e=segment(F[i],F[(i+1)%n]);
			if(intersect(S,e)){
				q=get_intersect(S,e);
				if(q!=p){
					i0=i;
					break;
				}
			}
		}

		assert(i0!=-1);
		if(used[i0]) return res; // 同じ辺に二回反射したらダメ
		used[i0]=true;

		if(q==e.a || q==e.b) return res; // 角に当たったらダメ

		res.push_back(i0);

		// 反射角を求める
		double phi=arg(e.b-e.a);
		point dir=rot(q-p,-phi);
		dir.y*=-1;
		dir=rot(dir,phi);
		theta=arg(dir);

		p=q;
	}

	return res;
}

void dfs(point s,int cnt,int used,polygon G,vector<double> &theta){
	int n=G.size();

	if(cnt==n-1){
		int i;
		for(i=0;used&(1<<i);i++);
		theta.push_back(arg(G[i]-s));
		theta.push_back(arg(G[(i+1)%n]-s));
		return;
	}

	rep(i,n) if(!(used&(1<<i))) {
		theta.push_back(arg(G[i]-s));
		theta.push_back(arg(G[(i+1)%n]-s));

		segment e(G[i],G[(i+1)%n]);
		polygon H(n);
		rep(j,n){
			point p=G[j];
			// p を e に対称な位置に移す
			double phi=arg(e.b-e.a);
			point tmp=rot(p-e.a,-phi);
			tmp.y*=-1;
			H[j]=rot(tmp,phi)+e.a;
		}
		dfs(s,cnt+1,used|(1<<i),H,theta);
	}
}

bool eq(double a,double b){ return abs(a-b)<EPS; }

int main(){
	for(int n;scanf("%d",&n),n;){
		point s; scanf("%lf%lf",&s.x,&s.y);
		polygon F(n);
		rep(i,n) scanf("%lf%lf",&F[i].x,&F[i].y);

		vector<double> theta;
		dfs(s,0,0,F,theta);
		sort(theta.begin(),theta.end());
		theta.erase(unique(theta.begin(),theta.end(),eq),theta.end());
		theta.push_back(theta[0]+2*PI);

		vector<double> phi;
		rep(i,(int)theta.size()-1) phi.push_back((theta[i]+theta[i+1])/2);

		set< vector<int> > ans;
		// TLE が厳しいので 1 つ置きにシミュレーション. 2 つが同じ結果ならスキップしたものも同じ結果
		vector<int> prev;
		static bool skip[200000];
		rep(i,phi.size()) skip[i]=false;
		rep(i,phi.size()/2){
			vector<int> hit=simulate(s,F,phi[2*i]);
			if(hit.size()==n && is_perm(hit)){
				ans.insert(hit);
				if(hit==prev) skip[2*i-1]=true;
			}
			prev=hit;
		}
		rep(i,phi.size()/2+1){
			if(2*i+1<phi.size() && !skip[2*i+1]){
				vector<int> hit=simulate(s,F,phi[2*i+1]);
				if(hit.size()==n && is_perm(hit)){
					ans.insert(hit);
				}
			}
		}

		printf("%d\n",ans.size());
	}

	return 0;
}

Measured memory_bytes: 6244