#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cassert>
#include<iomanip>
#include<queue>
#include<cstdio>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define EPS (1e-10)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define pow2(a) ((a)*(a))

using namespace std;

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

class Point
{
  public:
  double x,y;

  Point(double x = -inf,double y = -inf): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}

  bool operator < (const Point& p) const
  {
    return !equals(x,p.x)?x<p.x:y<p.y;
  }

  bool operator == (const Point& p)const
  {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }

};

struct Segment
{
  Point p1,p2;
  Segment(Point p1 = Point(-inf,-inf),Point p2 = Point(-inf,-inf)):p1(p1),p2(p2){}
  bool operator == (const Segment& p)const
  {
    return p.p1 == p1 && p.p2 == p2;
  }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a)
{
  os << "(" << a.x << "," << a.y << ")";
}

ostream& operator << (ostream& os,const Segment& a)
{
  os << "( " << a.p1 << " , " << a.p2 << " )";
}

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

int ccw(Point p0,Point p1,Point p2)
{
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool merge_if_able(Segment &s, Segment t) {
  if (abs(cross(s.p2-s.p1, t.p2-t.p1)) > EPS) return false;
  if (ccw(s.p1, t.p1, s.p2) == +1 ||
      ccw(s.p1, t.p1, s.p2) == -1) return false; // not on the same line
  if (ccw(s.p1, s.p2, t.p1) == -2 ||
      ccw(t.p1, t.p2, s.p1) == -2) return false; // separated
  s = Segment(min(s.p1, t.p1), max(s.p2, t.p2));
  return true;
}
void merge_segments(vector<Segment>& segs) {
  for (int i = 0; i < segs.size(); ++i)
    if (segs[i].p2 < segs[i].p1)
      swap(segs[i].p2, segs[i].p1);
  for (int i = 0; i < segs.size(); ++i)
    for (int j = i+1; j < segs.size(); ++j)
      if (merge_if_able(segs[i], segs[j]))
        segs[j--] = segs.back(), segs.pop_back();
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}
Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) return m.p1; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m.p1 +   (m.p2 - m.p1) * (B / A);
}

struct Edge
{
  int from,to;
  double cost;
  Edge(int from=inf,int to=inf,double cost=inf):from(from),to(to),cost(cost){}
  bool operator < (const Edge& a)const
  {
    return cost < a.cost;
  }
};
typedef vector<Edge> vE;
typedef vector<vE> vvE;

Point star,dest;
vector<vector<Edge> > segmentArrangement(vector<Segment> vs,vector<Point> &ps)
{
/*
端点もいれたいなら
ここであらかじめ端点だけpsにいれる
*/
  rep(i,vs.size())
    REP(j,i+1,vs.size())
      if(intersectSS(vs[i],vs[j]))
        ps.push_back(Point(crosspoint(vs[i],vs[j])));

  //
  ps.push_back(star);
  ps.push_back(dest);
  //

  sort(ps.begin(),ps.end());  
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  vector<vector<Edge> > ret(ps.size());

  for(int i=0;i<vs.size();i++)
    {
      vector<pair<double,int> > list;
      rep(j,ps.size())
	if(intersectSP(vs[i],ps[j]))
	  list.push_back(pair<double,int>(norm(vs[i].p1-ps[j]),j));

      sort(list.begin(),list.end());

      //for(int j=0;j<list.size()-1;++j) is not good
      for(int j=0;j+1<list.size();++j)
	{
	  int from = list[j].second, to = list[j+1].second;
	  double cost = abs(ps[from]-ps[to]);
	  ret[from].push_back(Edge(from,to,cost));
	  ret[to].push_back(Edge(to,from,cost));
	}
    }  
  return ret;
}


//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

struct Pox
{
  int prev,cur;
  double cost;
  Pox(int prev=inf,int cur=inf,double cost=inf):prev(prev),cur(cur),cost(cost){}
  bool operator < (const Pox& a)const
  {
    return cost > a.cost;
  }
};

int n;

double calcCost(Point A,Point B,Point C)
{
  double a = sqrt(pow2(B.x-C.x)+pow2(B.y-C.y));
  double b = sqrt(pow2(A.x-C.x)+pow2(A.y-C.y));
  double c = sqrt(pow2(A.x-B.x)+pow2(A.y-B.y));
  //cout << a << ",x," << b << ",x," << c << endl;
  return acos((c*c+a*a-b*b)/(2.0*c*a))*180/M_PI;
}

void dijkstra(vvE &G,vector<Point> &ps)
{
  int sp,ep;
  sp = ep = inf;
  rep(i,ps.size())
    if(ps[i] == star)sp = i;
    else if(ps[i] == dest)ep = i;
  //cout << "sp = " << sp << " ep = " << ep << endl;

  assert(sp != inf);
  assert(ep != inf);

  int N = ps.size();
  double mincost[N][N];
  rep(i,N)rep(j,N)mincost[i][j] = (i==j?0:inf);  

  priority_queue<Pox> Q;
  Q.push(Pox(sp,sp,0));

  //cout << "dijkstra----" << endl;
  while(!Q.empty())
    {
      Pox pox = Q.top(); Q.pop();
      //cout << "(" << pox.prev << "," << pox.cur << "," << pox.cost << ")" << endl;
      if(pox.cur == ep)
	{
	  printf("%.12lf\n",pox.cost);
	  //cout << setiosflags(ios::fixed) << setprecision(10) << pox.cost << endl;
	  return;
	}

      int prev = pox.prev;
      int cur = pox.cur;
      double cost = pox.cost;

      rep(i,G[cur].size())
	{
	  int next = G[cur][i].to;
	  if(prev == next)continue;
	  Point e = ps[prev] - ps[cur];
	  e = e/abs(e);
	  e = e*1000;




	  double arg = 180 - calcCost(ps[prev],ps[cur],ps[next]);
	  //cout << "arg =  " << arg << endl;
	  if(intersectSP(Segment(ps[prev]-e,ps[cur]+e),ps[next]))arg = 0;
	  double ncost = cost + arg;
	  if(prev == cur)ncost = 0;
	  //cout << "from " << cur << " to " << next << " the cost = " << ncost << endl;
	  if(!equals(ncost,mincost[cur][next]) && mincost[cur][next] > ncost)
	    {
	      mincost[cur][next] = ncost;
	      Q.push(Pox(cur,next,ncost));
	    }
	}

    }
  cout << -1 << endl;
}

void compute(vector<Segment>& vec)
{
  vector<Point> ps;
  vvE G = segmentArrangement(vec,ps);
  /*
  cout << "ps--------" << endl;
  rep(i,ps.size())cout << "ps[" << i << "] = " << ps[i] << endl;
  cout << endl;

  cout << "G---------" << endl;
  rep(i,G.size())
    {
      rep(j,G[i].size())
	{
	  cout << "(" << G[i][j].from << "," << G[i][j].to << ") ";
	}
      cout << endl;
    }
  cout << endl;
  */
  dijkstra(G,ps);
}

int main()
{
  while(cin >> n,n)
    {
      vector<Segment> vec(n); 
      rep(i,n)
	{
	  cin >> vec[i].p1.x >> vec[i].p1.y >> vec[i].p2.x >> vec[i].p2.y;
	  //vec[i].p1 = vec[i].p1 + 1000;
	  //vec[i].p2 = vec[i].p2 + 1000;
	}
      merge_segments(vec);
      cin >> star.x >> star.y >> dest.x >> dest.y;
      compute(vec);
    }
  return 0;
}
 

Measured memory_bytes: 1388