#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include"bits/stdc++.h"

using namespace std;

#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,m,n) for(int i=(m);i<(n);i++)

const bool DEBUG = false;

const double EPS = 1e-8;
typedef complex<double> point;
istream &operator>>(istream &is, point &p) {
	double a, b;
	is >> a >> b;
	p = point(a, b);
	return is;
}
point operator*(const point&p, const double &d) {
	return point(real(p)*d, imag(p)*d);
}
namespace std {
	bool operator < (const point& a, const point& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
}

//直線or線分
struct Line : public vector<point> {
	Line(const point &a, const point &b) {
		push_back(a); push_back(b);
	}
};
typedef vector<Line>Lines;


double cross(const point& a, const point& b) {
	return real(a)*imag(b) - imag(a)*real(b);
}
double dot(const point& a, const point& b) {
	return real(a)*real(b) + imag(a)*imag(b);
}
int ccw(point a, point b, point c) {
	b = b - a; c = c - a;
	if (cross(b, c) > EPS)   return +1;       // counter clockwise
	if (cross(b, c) < -EPS)   return -1;       // clockwise
	if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}
//交差判定
bool intersectLL(const Line &l1, const Line &l2) {
	return abs(cross(l1[1] - l1[0], l2[1] - l2[0])) > EPS || //non-parallel
		abs(cross(l1[1] - l1[0], l2[0] - l1[0])) < EPS; //same line
}
bool intersectLS(const Line &l, const Line &s) {
	return cross(l[1] - l[0], s[0] - l[0])* // s[0] is left of l
		cross(l[1] - l[0], s[1] - l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const Line &l, const point &p) {
	return abs(cross(l[1] - p, l[0] - p)) < EPS;
}
//端点に乗ってたらfalse
bool intersectSP_without_endpoint(const Line &s, const point &p) {
	if (abs(s[0] - p) < EPS || abs(s[1] - p) < EPS)return false;
	return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS; //triangle inequality
}

bool intersectSP(const Line &s, const point &p) { //verified on 2020/04/03 https://onlinejudge.u-aizu.ac.jp/status/users/Mojumbo/submissions/1/1157/judge/4316978/C++14
	return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS; //triangle inequality
}
bool connectSS(const Line &s, const Line &t) {
	if (intersectSP(s, t[0]) || intersectSP(s, t[1]) || intersectSP(t, s[0]) || intersectSP(t, s[1]))return true;
	else return false;
}
bool isSamePoint(const point &p1, const point &p2) {
	return abs(p1 - p2)<EPS;
}
bool connectSS_with_endpoint(const Line &s, const Line &t) {
	REP(i, 2)REP(j, 2) {
		//if(isSamePoint(s[i],t[j]))return true;
		if (s[i] == t[j])return true;
	}
	return false;
}
bool intersectSS(const Line &s, const Line &t) {
	return ccw(s[0], s[1], t[0])*ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0])*ccw(t[0], t[1], s[1]) <= 0;
}
bool intersectSS_strict(const Line &s, const Line &t) {
	//端点が線分上に乗っている場合はfalseにする
	if (connectSS(s, t))return false;
	return ccw(s[0], s[1], t[0])*ccw(s[0], s[1], t[1]) <= 0 &&
		ccw(t[0], t[1], s[0])*ccw(t[0], t[1], s[1]) <= 0;
}

bool isOn(const Line &l, const point &p) {
	if (l[0] == p || l[1] == p)return false;
	point d = l[1] - l[0];
	point p0 = (p - l[0]) / d;
	return p0.imag() == 0.0&&0.0<p0.real() && p0.real()<1.0;
}
bool intersect(const Line &l0, const Line &l1, point &p) {
	if (connectSS_with_endpoint(l0, l1) || isOn(l0, l1[0]) || isOn(l0, l1[1]) || isOn(l1, l0[0]) || isOn(l1, l0[1]))return false;
	point d = l0[1] - l0[0];
	point p0 = (l1[0] - l0[0]) / d;
	point p1 = (l1[1] - l0[0]) / d;
	if (p0.imag()*p1.imag() >= 0)return false;
	double t = p0.imag() / (p0.imag() - p1.imag());
	double s = p0.real()*(1 - t) + p1.real()*t;
	if (s <= 0.0 || 1.0 <= s)return false;
	p = l0[0] + d * s;
	return true;
}

//距離,交点
//射影 直線lにpから下した垂線との交点

point projection(const Line &l, const point &p) { //verified on 2020/04/03 https://onlinejudge.u-aizu.ac.jp/status/users/Mojumbo/submissions/1/1157/judge/4316978/C++14
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + (l[0] - l[1])*t;
}
//射影 直線lを対象軸としてpと線対称にある点
point reflection(const Line &l, const point &p) {
	return p + (projection(l, p) - p) * 2;
}
double distancePP(const point& a, const point& b) {
	return sqrt(norm(a - b));
}
double distanceLP(const Line &l, const point &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const Line&l, const Line &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const Line &l, const Line &s) {
	if (intersectLS(l, s))return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const Line &s, const point &p) {
	const point r = projection(s, p);
	if (intersectSP(s, r))return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const Line &s, const Line &t) { //verified on 2020/04/03 https://onlinejudge.u-aizu.ac.jp/status/users/Mojumbo/submissions/1/1157/judge/4316978/C++14
	if (intersectSS(s, t))return 0;
	return min({ distanceSP(s,t[0]),distanceSP(s,t[1]),distanceSP(t,s[0]),distanceSP(t,s[1]) });
}
point crosspoint(const Line &l, const Line &m) {
	double A = cross(l[1] - l[0], m[1] - m[0]);
	double B = cross(l[1] - l[0], l[1] - m[0]);
	if (abs(A) < EPS&&abs(B) < EPS)return m[0];//same line
	if (abs(A) < EPS)assert(false); // Precondition not satisfied
	return m[0] + B / A * (m[1] - m[0]);
}
double dist(point &p1, point &p2) {
	return abs(p1 - p2);
}

//線分同士の交点で分割して端点以外の共有点を持たないようにする
void splitSegments(Lines &ls) {
	//端点が線分上に乗っている場合の分割
	for (int i = 0; i < (int)ls.size(); i++){
		int mx = ls.size();
		for (int j = i + 1; j < (int)ls.size(); j++) {
			if (j >= mx)break;
			for (int k = 0; k < 2; k++) {
				//if(isOn(ls[i],ls[j][k])){
				if (intersectSP_without_endpoint(ls[i], ls[j][k])) {
					ls.push_back(Line(ls[i][0], ls[j][k]));
					ls[i][0] = ls[j][k];
					break;
				}
				//else if(isOn(ls[j],ls[i][k])){
				else if (intersectSP_without_endpoint(ls[j], ls[i][k])) {
					ls.push_back(Line(ls[j][0], ls[i][k]));
					ls[j][0] = ls[i][k];
					break;
				}
			}
		}
	}
	//cerr << "split-1" << endl;
	//線分が交差している場合の分割
	for (int i = 0; i < (int)ls.size(); i++) {
		Line li = ls[i];
		int mx = ls.size();
		for (int j = i + 1; j < (int)ls.size(); j++) {
			point cross_p;
			if (j >= mx)break;
			//if (intersect(ls[i], ls[j], cross_p)) {
			if (intersectSS_strict(ls[i], ls[j])) {
				cross_p = crosspoint(ls[i], ls[j]);
				ls.push_back(Line(ls[i][0], cross_p));
				ls[i][0] = cross_p;
				ls.push_back(Line(ls[j][0], cross_p));
				ls[j][0] = cross_p;
			}
		}
	}
}

//線分の集合(split済み)を連結成分に分解する(union-find)

struct Equiv {
	vector<int>links;
	//大きさ1の同値類をn個作る
	Equiv(int n) :links(n) {
		for (int i = 0; i < n; i++) {
			links[i] = i;
		}
	}
	//xの属する同値類の代表元を返す
	int find(int x) {
		int xx = links[x];
		if (xx == x)return x;
		return links[x] = find(xx);
	}
	void unify(int x, int y) {
		int xx = find(x), yy = find(y);
		if (xx <= yy)links[yy] = xx;
		else links[xx] = yy;
	}
};

typedef vector<Lines>vLines;
vLines connectedComponent(const Lines &ls) {
	vLines ret;
	Equiv equiv(ls.size());
	for (int i = 0; i < (int)ls.size(); i++) {
		for (int j = 0; j < i; j++) {
			if (connectSS_with_endpoint(ls[i], ls[j])) {
				equiv.unify(i, j);
			}
		}
	}
	//cerr << "connected-1" << endl;
	for (int i = 0; i < (int)ls.size(); i++) {
		if (equiv.find(i) == i) {
			Lines newLs;
			newLs.push_back(ls[i]);
			for (int j = i + 1; j < (int)ls.size(); j++) {
				if (equiv.find(j) == i)newLs.push_back(ls[j]);
			}
			ret.push_back(newLs);
		}
	}
	return ret;
}
//左手法でのトレース
//偏角でソートされた隣接点のvectorを得る
typedef pair<double, point>doublePoint;
typedef vector<doublePoint> vDoublePoint;
typedef map<point, vDoublePoint> adjPoint;
typedef vector<point>points;
//移動前の点と隣接点のリストから移動先を決定
point findNext(const vDoublePoint &vdp, const point &p) {
	for (int i = 0; i < (int)vdp.size() - 1; i++) {
		if (p == vdp[i].second) {
			return vdp[i + 1].second;
		}
	}
	return vdp[0].second;
}
//左手法でトレースして通った点の列を返す
points trace(const Lines &ls) {
	adjPoint aPoint;
	//隣接点(偏角付き)のリストを作成
	for (int i = 0; i < (int)ls.size(); i++) {
		aPoint[ls[i][0]].push_back(doublePoint(arg(ls[i][1] - ls[i][0]), ls[i][1]));
		aPoint[ls[i][1]].push_back(doublePoint(arg(ls[i][0] - ls[i][1]), ls[i][0]));
	}
	//x座標最小の点の計算と隣接点リストのソート
	point minPoint(INT_MAX, INT_MAX);
	adjPoint::iterator it;
	for (it = aPoint.begin(); it != aPoint.end(); ++it) {
		point p = it->first;
		minPoint = min(minPoint, p);
		vDoublePoint &vdp = it->second;
		sort(vdp.begin(), vdp.end());
	}
	points ret;
	ret.push_back(minPoint);
	//最初の移動先
	point curP = aPoint[minPoint][0].second;
	point lastP = minPoint;
	//トレースの繰り返し
	while (curP != minPoint) {
		if (DEBUG)cerr << curP << endl;
		ret.push_back(curP);
		point nextP = findNext(aPoint[curP], lastP);
		//if(isSamePoint(curP,nextP))break;
		lastP = curP;
		curP = nextP;
	}
	//開始点を最後にも追加
	ret.push_back(minPoint);
	return ret;
}

bool isInside(const points &ps) {
	Line l0(point(0, 0), point(51.0, 1.0 / 20000.0));
	int count = 0;
	for (int i = 0; i < (int)ps.size() - 1; i++) {
		point dummy;
		Line l1(ps[i], ps[i + 1]);
		if (intersect(l0, l1, dummy))count++;
	}
	return (count & 1) == 1;
}


//円
struct Circle {
	point p; double r;
	Circle(const point &p_, double r_) : p(p_), r(r_) { }
};

//凸包
vector<point> convex_hull(vector<point> ps) {
	int n = ps.size(), k = 0;
	sort(ps.begin(), ps.end());
	vector<point> ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) // upper-hull
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}

//2点を通る半径Rの円の中心
pair<point, point> get_circle_from_2points(point &p1, point &p2, double R) {
	double d = dist(p1, p2);
	double x1 = p1.real(), x2 = p2.real();
	double y1 = p1.imag(), y2 = p2.imag();
	if (p1.imag() == p2.imag()) {
		double x = (x1 + x2) / 2.0;
		double dy = sqrt(R - d * d / 4);
		return { { x,y1 + dy },{ x,y1 - dy } };
	}
	else {
		double m = (x1 - x2) / (y2 - y1);
		double t = sqrt(R*R - d * d / 4);
		double dx = sqrt((t*t) / (m*m + 1));
		double dy = sqrt(t*t - dx * dx);
		double gx = (x1 + x2) / 2;
		double gy = (y1 + y2) / 2;
		if (m > EPS) {
			return { { gx + dx,gy + dy },{ gx - dx,gy - dy } };
		}
		else {
			return { { gx + dx,gy - dy },{ gx - dx,gy + dy } };
		}
	}
}
//長方形
struct Square {
	double lx, ly, rx, ry;
	Square(double lx_, double ly_, double rx_, double ry_) :lx(lx_), ly(ly_), rx(rx_), ry(ry_) {};
	bool include(point &p) {
		return p.real() + EPS >= lx && p.real() - EPS <= rx && p.imag() + EPS >= ly && p.imag() - EPS <= ry;
	}
};

struct Polygon : public vector<point> {
	//0->OUT, 1->ON, 2->IN
	int contains(const point &p) {
		bool in = false;
		int N = this->size();
		for (int i = 0; i < N; i++) {
			point a = this->at(i) - p;
			point b = this->at((i + 1) % N) - p;
			if (imag(a) > imag(b)) {
				std::swap(a, b);
			}
			if (imag(a) <= 0 && 0 < imag(b))
				if (cross(a, b) < 0)in = !in;
			if (cross(a, b) == 0 && dot(a, b) <= 0)return 1;
		}
		return in ? 2 : 0;
	}
};
clock_t START, END;
bool trapAll() {
	int N; cin >> N;
	if (N == 0) {
		END = clock();
		double t = (double)(END - START) / CLOCKS_PER_SEC;
		//cerr << "elapsed time" << t << "[sec]" << endl;
		exit(0);
	}
	Lines ls;
	REP(i, N) {
		double x1, y1, x2, y2;
		cin >> x1 >> y1 >> x2 >> y2;
		point p1(x1, y1);
		point p2(x2, y2);
		ls.push_back(Line(p1, p2));
	}
	splitSegments(ls);
	// for(auto l:ls){
	// 	cerr<<l[0]<<" "<<l[1]<<endl;
	// }
	//cerr << "splitted" << endl;
	vLines vls = connectedComponent(ls);
	for (auto lines : vls) {
		//if(isInside(trace(lines)))return true;
		Polygon poly;
		points ps = trace(lines);
		for (auto p : ps) {
			poly.push_back(p);
		}
		if (poly.contains(point(0, 0)))return true;
	}
	return false;
}

void solve() {
	if (trapAll())cout << "yes" << endl;
	else cout << "no" << endl;
	if (DEBUG)cerr << "+++++++++++++" << endl;
}
signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	START = clock();
	while (true)
		solve();

}


Measured memory_bytes: 6452