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

#define MAX_V 100000

//
typedef complex<double> P;
const double eps = 1e-8;

bool equals(double a, double b) {
  return abs(a-b) < eps;
}

namespace std {
  bool operator < (const P &a, const P &b) {
    if(a.real() != b.real()) return a.real() < b.real();
    if(a.imag() != b.imag()) return a.imag() < b.imag();
    return false;
  }
};

double dot(P a, P b) {
  return a.real()*b.real() + a.imag()*b.imag();
}

double cross(P a, P b) {
  return a.real()*b.imag() - a.imag()*b.real();
}

int ccw(P p, P a, P b) {
  a -= p;
  b -= p;
  if(cross(a, b) > eps) return 1;
  if(cross(a, b) < -eps) return -1;
  if(dot(a, b) < -eps) return 2;
  if(norm(b) - norm(a) > eps) return -2;
  return 0;
}

bool isIntersect(P a1, P a2, P b1, P b2) {
  return ( ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
           ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0 );
}

P getCrossP(P a1, P a2, P b1, P b2) {
  P a = a2 - a1;
  P b = b2 - b1;
  return a1 + a * cross(b, b1 - a1) / cross(b, a);
}

struct Edge {
  int to; double w;
  Edge() {}
  Edge(int to, double w) : to(to), w(w) {}
};

typedef vector<vector<Edge> > Graph;

Graph segmentArrangement(const vector<P> &s1, const vector<P> &s2,
                         vector<P> &ps) {
  int m = s1.size();
  for(int i = 0; i < m; ++i) {
    ps.push_back(s1[i]);
    ps.push_back(s2[i]);
    for(int j = i+1; j < m; ++j) {
      if(equals(cross(s1[i] - s2[i], s1[j] - s2[j]), 0.0)) continue;
      if(!isIntersect(s1[i], s2[i], s1[j], s2[j])) continue;
      ps.push_back(getCrossP(s1[i], s2[i], s1[j], s2[j]));
    }
  }
  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());//

  int n = ps.size();
  Graph g(n);
  for(int i = 0; i < m; ++i) {
    vector<pair<double, int> > v;
    for(int j = 0; j < n; ++j) {
      if(!ccw(s1[i], s2[i], ps[j])) {
        v.push_back(make_pair(norm(s1[i] - ps[j]), j));
      }
    }
    sort(v.begin(), v.end());
    for(int j = 0; j+1 < v.size(); ++j) {
      int a = v[j].second, b = v[j+1].second;
      //double w = abs(ps[a] - ps[b]);
      double w = acos(dot(ps[a], ps[b])/abs(ps[a])/abs(ps[b]));
      if(ccw(P(0,0), ps[a], ps[b]) == -1) w *= -1;
      g[a].push_back((Edge){b,  w});
      g[b].push_back((Edge){a, -w});
    }
  }
  return g;
}

Graph G;


void solve();


int main() {
  for(int n; cin >> n && n; ) {
    vector<P> a(n), b(n);
    for(int i = 0; i < n; ++i) {
      cin >> a[i].real() >> a[i].imag()
          >> b[i].real() >> b[i].imag();
    }
    vector<P> ps;
    G = segmentArrangement(a, b, ps);
    /*
    for(int i = 0; i < G.size(); ++i) {
      cout << i <<":";
      for(int j = 0; j < G[i].size(); ++j) {
        if(j) cout << ",";
        cout << G[i][j].to;
      }
      cout << endl;
    }
    */
    solve();
  }
  return 0;
}


bool visited[MAX_V];
double mem[MAX_V];
bool noteq(double a,double b){
  return ( fabs(a-b) > eps);
}
bool dfs(int pos,double sum){
  if(visited[pos]) {
    return noteq(sum,mem[pos]);
  }
  visited[pos]=true;
  mem[pos]=sum;
  for(int i=0;i<(int)G[pos].size();i++){
    Edge e=G[pos][i];
    if( dfs(e.to,sum+e.w) ) return true;
  }
  return false;
}
void initd(){
  for(int i=0;i<MAX_V;i++){
    visited[i]=false;
    mem[i]=0;
  }
}
void solve(){
  initd();
  for(int i = 0; i < G.size(); ++i) {
    if(visited[i]) continue;
    if(dfs(i,0)){
      cout<<"yes"<<endl;
      return;
    }
  }
  cout<<"no"<<endl;
}

Measured memory_bytes: 3600