#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
// #define double long double
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef double Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};

bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;


// 道程がいらない場合
vector<Weight> dijkstra(const Graph &g, int s) {
  vector<Weight> dist(g.size(), INF);
  dist[s] = 0;
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst] < e.weight) continue;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}


typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {resize(2);}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; 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;
}

P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}

double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &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 L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &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 intersectSS2(const L &s, const L &t) {
  if (intersectSP(s,t[0]) || intersectSP(s,t[1]) ||
      intersectSP(t,s[0]) || intersectSP(t,s[1])) return 0;
  return intersectSS(s,t);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectLP(h,s[0]) || intersectLP(h,s[1]) ||
      intersectLP(s,h[0]) || intersectLP(s,h[1])) return 0;
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}

P crosspoint(const L &l, const L &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) {
    // sameline
    if (intersectSP(l,m[0]) && intersectSP(l,m[1])) return P(0.5)*(m[0]+m[1]);
    if (intersectSP(m,l[0]) && intersectSP(m,l[1])) return P(0.5)*(l[0]+l[1]);
    REP(i,2) REP(j,2)
      if (intersectSP(l,m[i]) && intersectSP(m,l[j])) return P(0.5)*(m[i]+l[j]);
  }
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

bool EQ(double a, double b) {
  return abs(a-b) < EPS;
}
bool EQP(const P &a, const P &b) {
  return norm(a-b) < EPS*EPS;
}

#define index_of(ps, p) \
  distance(ps.begin(), lower_bound(ps.begin(), ps.end(), p))
Graph arrangement(const vector<L>& segs, vector<P>& pt) {
  vector< vector<double> > V(segs.size());
  for (int i = 0; i < segs.size(); ++i) {
    pt.push_back( segs[i][0] );
    pt.push_back( segs[i][1] );
    V[i].push_back(0);
    V[i].push_back(1);
    for (int j = i+1; j < segs.size(); ++j) {
      L a = segs[i], b = segs[j];
      if (intersectSS(a, b)) {
        double D = cross(b[1]-b[0], a[1]-a[0]);
        if (abs(D) < EPS) continue;
        double t = cross(b[1]-b[0], b[0]-a[0]) / D;
        double s = cross(a[0]-b[0], a[1]-a[0]) / D;
        V[i].push_back(t);
        V[j].push_back(s);
        pt.push_back( a[0]+(a[1]-a[0])*t );
      }
    }
  }
  sort(pt.begin(), pt.end());
  pt.erase(unique(pt.begin(), pt.end(), EQP), pt.end());

  Graph g(pt.size());
  for (int i = 0; i < V.size(); ++i) {
    vector<double>& cut = V[i];
    sort(cut.begin(), cut.end());
    cut.erase(unique(cut.begin(), cut.end(), EQ), cut.end());
    for (int j = 0; j+1 < cut.size(); ++j) {
      P a = segs[i][0] + (segs[i][1] - segs[i][0]) * cut[j];
      P b = segs[i][0] + (segs[i][1] - segs[i][0]) * cut[j+1];
      int src = index_of(pt, a), dst = index_of(pt, b);
      // cout << g.size() << " " << src << " " << dst << " " << abs(a-b) << endl;
      g[src].push_back( Edge(src, dst, abs(a-b)) );
      g[dst].push_back( Edge(dst, src, abs(a-b)) );
    }
  }
  return g;
}

Graph segmentArrangement(const vector<L> &ss, vector<P> &ps) {
  int n = ss.size();
  REP(i,n) {
    ps.push_back( ss[i][0] );
    ps.push_back( ss[i][1] );
    for (int j = i+1; j < ss.size(); ++j)
      if (intersectSS(ss[i], ss[j]))
        ps.push_back( crosspoint(ss[i], ss[j]) );
  }
  sort(ALL(ps)); ps.erase(unique(ALL(ps)), ps.end());

  Graph g(ps.size());
  for (int i = 0; i < ss.size(); ++i) {
    int pre = -1;
    for (int j = 0; j < ps.size(); ++j)
      if (intersectSP(ss[i], ps[j])) {
        if (pre != -1) {
          double d = abs(ps[pre]-ps[j]);
          g[pre].push_back(Edge(pre,j,d));
          g[j].push_back(Edge(j,pre,d));
        }
        pre = j;
      }
  }
  return g;
}

vector<Edge> graph[300000];
int pid[1004][1004];

Graph segmentArrangement2(const vector<L> &ss, vector<P> &ps) {
  memset(pid,-1,sizeof(pid));
  REP(i,300000) graph[i].clear();
  int n = ss.size();
  REP(i,n) {
    int beg = ps.size();
    ps.push_back(ss[i][0]);
    ps.push_back(ss[i][1]);
    REP(j,n) {
      if (i == j) continue;
      if (intersectSS(ss[i],ss[j])) {
        int b = ps.size();
        if (i>j) {
          int a = pid[j][i];
          // cout << ps[a] << " "<< crosspoint(ss[i],ss[j]) << endl;
          graph[a].push_back(Edge(a,b,0));
          graph[b].push_back(Edge(b,a,0));
        } else {
          pid[i][j] = b;
        }
        ps.push_back(crosspoint(ss[i],ss[j]));
      }
    }
    vector<pair<P,int> > v(ps.size()-beg);
    for (int i=beg; i<ps.size(); ++i)
      v[i-beg] = make_pair(ps[i],i);
    sort(ALL(v));
    REP(i,v.size()-1) {
      int a = v[i].second, b = v[i+1].second;
      double c = abs(v[i].first-v[i+1].first);
      graph[a].push_back(Edge(a,b,c));
      graph[b].push_back(Edge(b,a,c));
    }
  }
  Graph g(ps.size());
  REP(i,ps.size()) {
    g[i] = graph[i];
  }
  return g;
}


int main() {
  int n;
  while(cin >> n, n) {
    vector<L> segs;
    REP(i,n) {
      P a, b;
      cin >> a.real() >> a.imag();
      cin >> b.real() >> b.imag();
      segs.push_back(L(a,b));
    }
    P s;
    cin >> s.real() >> s.imag();
    REP(i,n) {
      if (intersectSP(segs[i],s)) {
        segs.push_back(L(segs[i][0],s));
        segs.push_back(L(s,segs[i][1]));
        break;
      }
    }
    vector<P> pv;
    // Graph g = arrangement(segs,pv);
    Graph g = segmentArrangement2(segs,pv);
    int sid = -1;
    REP(i,pv.size()) {
      if (abs(pv[i]-s) < EPS) sid = i;
    }
    assert(sid != -1);
    // REP(i,g.size()) {
    //   cout << i << endl;
    //   FOR(it, g[i]) {
    //     cout << it->dst << " " << it->weight << endl;
    //   }
    // }
    // cout << sid << endl;
    vector<double> dis = dijkstra(g,sid);
    double ans = 0;
    REP(i,g.size()) {
      FOR(it, g[i]) {
        int a = it->src;
        int b = it->dst;
        double x = (dis[b]-dis[a]+it->weight) / 2;
        chmax(ans, dis[a] + x);
      }
    }
    cout << setprecision(10) << fixed << ans << endl;
    // printf("%.10Lf\n", ans);
  }
}

Measured memory_bytes: 25688