#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)
using namespace std;
typedef long long LL;

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

// 誤差を加味した符号判定
int sign(double x){ return x > EPS ? 1 : x < -EPS ? -1 : 0; }

// 内積・外積
double dot(P a, P b){return real(conj(a) * b);}
double cross(P a, P b){return imag(conj(a) * b);}

// OAとOBのなす符号付き角度 [-pi, pi]
// example : (1, 0), (0, 1) -> pi/2
double angle(P a, P b){return arg(conj(a) * b);}

// aをc中心にb[rad]回転
P rotate(P a, double b, P c = P()){return (a - c) * polar(1.0, b) + c;}

int ccw(P a, P b, P c) {
    b -= a; c -= a;
    if (cross(b, c) > +EPS)   return +1; // 反時計回り
    if (cross(b, c) < -EPS)   return -1; // 時計回り
    if (dot(b, c) < -EPS)     return +2; // c--a--b の順番で一直線上
    if (norm(b) + EPS < norm(c)) return -2; // a--b--c の順番で一直線上
    return 0;                         // 点が線分ab上にある
}

enum{ OUT, ON, IN };

// Pointの比較をしたいときだけ定義する．
namespace std{
    bool operator < (const P& a, const P& b) {
        return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
    }
};

typedef vector<P> L;
P vec(L l){return l[1] - l[0];}

// 線分と点の交差判定(端点の処理に注意)(端点は含むけれども誤差に注意)
// verify : AOJ1279, AOJ2506
bool iSP(L s, P p) {return ccw(s[0], s[1], p) == 0;}

// 直線と直線の交点
// Verified: AOJ2579
// size()によって場合分け
// *4 : 直線が重なる  *1 : 交点が1つ存在 *0 : 直線が交差しない
vector<P> pLL(L l, L m){
    double A = cross(vec(l), vec(m));
    double B = cross(vec(l), l[1] - m[0]);
    if(sign(A) == 0 && sign(B) == 0) return {l[0], l[1], m[0], m[1]}; // 二直線が重なっている
    if(sign(A) == 0) return{}; // 直線が交わらない
    return {m[0] + vec(m) * B / A};
}

vector<P> pSS(L l, L m){
    vector<P> res;
    auto find = [&](P p){ 
        for(P r : res) if(sign(abs(r - p)) == 0)
                return true;
        return false;
    };
    for(P p : pLL(l, m))
        if(iSP(l,p) && iSP(m,p) && !find(p)) // 片方が直線の場合は適宜変えること
            res.push_back(p);
    return res;
}

// 入力
// ss : 線分のリスト
//
// 出力
// ps : グラフの頂点番号に対応する点が入る
// 返り値 : 上の説明のグラフ
//
// Verified
// AOJ 2113
typedef vector<int> Node;
typedef vector<Node> Graph;
Graph segment_arrangement(const vector<L> &ss, vector<P> &ps) {
    for (int i = 0; i < ss.size(); i++) {
        ps.push_back( ss[i][0] );
        ps.push_back( ss[i][1] );
        for (int j = i+1; j < ss.size(); j++){
            auto cp = pSS(ss[i], ss[j]);
            if (!cp.empty()) {
                assert(cp.size() == 1);
                ps.push_back( cp.back() );
            }
        }
    }
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());

    Graph g(ps.size());
    for (int i = 0; i < ss.size(); i++) {
        vector<int> on;
        for (int j = 0; j < ps.size(); j++){
            if (iSP(ss[i], ps[j])){
                on.push_back(j);
            }
        }
        for (int j = 0; j + 1 < on.size(); j++) {
            for(int k = j + 1; k < on.size(); k++) {
                int a = on[j], b = on[k];
                g[a].push_back( b );
                g[b].push_back( a );
            }
        }
    }
    return g;
}

// 線分併合
//
// 線分のリストからオーバーラップするものたちをまとめ,新しい線分のリストを作る.
// 元々の線分のリストにおける順番は破壊される．
//
// not verified
void merge_segments(vector<L>& segs) {
    auto merge_if_able = [](L& s, L t){
        if (abs(cross(s[1]-s[0], t[1]-t[0])) > EPS) return false;
        //if (sign(cross(vec(s), vec(t))) != 0) return false;
        if (ccw(s[0], t[0], s[1]) == +1 ||
                ccw(s[0], t[0], s[1]) == -1) return false; // not on the same line
        if (ccw(s[0], s[1], t[0]) == -2 ||
                ccw(t[0], t[1], s[0]) == -2) return false; // separated
        s = { min(s[0], t[0]), max(s[1], t[1]) };
        return true;
    };
    for (int i = 0; i < segs.size(); ++i)
        if (segs[i][1] < segs[i][0])
            swap(segs[i][1], segs[i][0]);
    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();
}
P input() {
    double x, y;
    cin >> x >> y;
    return {x, y};
}
typedef tuple<double, int, int> T;
const int MAX = 500;
const double INF = 1e64;

int main(){
    int n;
    while(cin >> n && n > 0){
        vector<L> lines(n);
        REP(i, n) {
            P a = input();
            P b = input();
            lines[i] = {a, b};
        }

        merge_segments(lines);
        //assert(size == lines.size());

        vector<P> ps;
        Graph G = segment_arrangement(lines, ps);
        /*
        REP(i, G.size()){
            cout << i << ":";
            for(int v : G[i]) cout << v << " ";
            cout << endl;
        }
        */
        assert(ps.size() < MAX);

        REP(i, ps.size()) REP(j, i) {
            assert(abs(ps[i] - ps[j]) > EPS);
        }

        auto find = [](const vector<P>& pv, P p) -> int {
            for(int i = 0; i < pv.size(); i++) {
                auto q = pv[i];
                if(abs(p - q) < EPS) {
                    return i;
                }
            }
            return -1;
        };
        
        P sp = input();
        P gp = input();
        int s = find(ps, sp);
        int g = find(ps, gp);

        /*
        if(s == g) {
            cout << 0 << endl;
            continue;
        }
        */

        assert(s != -1 && g != -1);

        priority_queue<T, vector<T>, greater<T>> que;
        double dist[MAX][MAX] = {};
        REP(i, MAX) REP(j, MAX) dist[i][j] = INF;
        for(int u : G[s]) {
            dist[s][u] = 0.0;
            que.push(T(0.0, s, u));
        }
        double ans = INF;
        while(!que.empty()) {
            T t = que.top(); que.pop();
            double d;
            int u, v;
            tie(d, u, v) = t;
            if(v == g) {
                ans = d;
                break;
            }
            for(int w : G[v]) if(u != w) {
                P p = ps[v] - ps[u];
                P q = ps[w] - ps[v];
                double th = abs(angle(p, q)) / M_PI * 180.0;
                double nd = d + th;
                if(dist[v][w] > nd) {
                    dist[v][w] = nd;
                    que.push(T(nd, v, w));
                }
            }
        }
        if(ans == INF) {
            cout << -1 << endl;
        } else {
            printf("%.12f\n", ans);
        }
    }

    return 0;
}

Measured memory_bytes: 3368