#include <iostream>
#include <vector>
#include <map>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <complex>
#include <unordered_map>
#include <algorithm>
#include <queue>
#include <functional>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())

typedef complex<double> point;
namespace std {
bool operator < (point p, point q) {
  if (real(p) != real(q)) return real(p) < real(q);
  return imag(p) < imag(q);
}
};
istream &operator>>(istream &is, point &p) {
  double x, y;
  is >> x >> y;
  p = point(x, y);
  return is;
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &x) {
  for (auto &a: x) os << a << " ";
  return os;
}

double dot(point p, point q)   { return real(conj(p) * q); }
double cross(point p, point q) { return imag(conj(p) * q); }
double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS) return -1;
  if (x > +EPS) return +1;
  return 0;
}
struct segment { point p, q; segment(point a, point b) : p(a), q(b) {} };
vector<point> intersect(segment S, segment T) {
  double a = cross(S.q - S.p, T.q - T.p);
  double b = cross(T.p - S.p, T.q - T.p); 
  double c = cross(S.q - S.p, S.p - T.p);
  if (a < 0) { a *= -1; b *= -1; c *= -1; }
  if (sign(b) < 0 || sign(a-b) < 0 ||
      sign(c) < 0 || sign(a-c) < 0) return {};      // disjoint
  if (sign(a) != 0) return {S.p + (S.q - S.p)*b/a}; // properly crossing
  if (sign(a) == 0) {                               // same line
    vector<point> ps;
    if (sign(dot(S.p - T.p, S.q - T.p)) <= 0) ps.push_back(T.p);
    if (sign(dot(S.p - T.q, S.q - T.q)) <= 0) ps.push_back(T.q);
    if (sign(dot(T.p - S.p, T.q - S.p)) <  0) ps.push_back(S.p);
    if (sign(dot(T.p - S.q, T.q - S.q)) <  0) ps.push_back(S.q);
    return ps;
  }
  return {};
}

struct planar_graph {
  vector<point> ps;
  struct edge { int src, dst; double th; int rev; bool visited; };
  vector<vector<edge>> adj;

  typedef long long ll;
  unordered_map<ll, vector<int>> hash; // store only unique vertices
  int add_vertex(point p) {
    ll h = ((ll)(real(p)*1000)) << 32 | (ll)(imag(p)*1000);
    for (auto i: hash[h]) 
      if (sign(abs(ps[i] - p)) == 0) return i;
    hash[h].push_back(ps.size());
    ps.push_back(p);
    adj.push_back({});
    return hash[h].back();
  }
  void add_edge(int i, int j) {
    adj[i].push_back({i, j, arg(ps[j] - ps[i])});
    adj[j].push_back({j, i, arg(ps[i] - ps[j])});
  }
  void complete() { // sort edges, and assign reverse edges
    vector<unordered_map<int,int>> hash(adj.size());
    for (int i = 0; i < adj.size(); ++i) {
      sort(all(adj[i]), [](edge a, edge b) { return a.th < b.th; });
      for (int j = 0; j < adj[i].size(); ++j) 
        hash[i][adj[i][j].dst] = j;
    }
    for (int i = 0; i < adj.size(); ++i) 
      for (int j = 0; j < adj[i].size(); ++j) 
        adj[i][j].rev = hash[adj[i][j].dst][i];
  }
  bool traverse(point p) {
    for (int i = 0; i < adj.size(); ++i)
      for (auto &e: adj[i]) e.visited = false;
    for (int i = 0; i < adj.size(); ++i) {
      for (int j = 0; j < adj[i].size(); ++j) {
        if (adj[i][j].visited) continue;
        int in = false, s = i, k = j;
        do {
          edge &e = adj[s][k];
          e.visited = true;
          point a = ps[e.src] - p, b = ps[e.dst] - p;
          if (imag(a) > imag(b)) swap(a, b);
          if (imag(a) <= 0 && 0 < imag(b))
            if (cross(a, b) < 0) in = !in;
          if (sign(cross(a, b)) == 0 && dot(a, b) <= 0) return true;
          s = e.dst; k = e.rev + 1;
          if (k >= adj[s].size()) k = 0;
        } while (!(s == i && k == j));
        if (in) return true;
      }
    }
    return false;
  }
};
planar_graph segment_arrangement(vector<segment> segs) {
  planar_graph g;
  vector<vector<int>> on(segs.size());
  for (int i = 0; i < segs.size(); ++i) {
    on[i].push_back( g.add_vertex(segs[i].p) );
    on[i].push_back( g.add_vertex(segs[i].q) );
    for (int j = i+1; j < segs.size(); ++j) {
      vector<point> is = intersect(segs[i], segs[j]);
      for (auto q: is) {
        on[i].push_back( g.add_vertex(q) );
        on[j].push_back( g.add_vertex(q) );
      }
    }
  }
  for (int i = 0; i < on.size(); ++i) {
    sort(all(on[i]), [&](int u, int v) { return g.ps[u] < g.ps[v]; });
    for (int j = 0; j+1 < on[i].size(); ++j) 
      if (on[i][j] != on[i][j+1]) 
        g.add_edge(on[i][j], on[i][j+1]);
  }
  g.complete();
  return g;
}

int main() {
  for (int m; cin >> m && m > 0; ) {
    vector<segment> segs;
    for (int i = 0; i < m; ++i) {
      point p, q;
      cin >> p >> q;
      segs.push_back({p, q});
    }
    auto g = segment_arrangement(segs);
    if (g.traverse(point(0.0, 0.0))) cout << "yes" << endl;
    else                             cout << "no" << endl;
  }
}

Measured memory_bytes: 3872