import std.stdio;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;


const EPS = 1e-10;

struct Point {
    double x, y;
    bool opEquals(in Point p) const {
        return abs(x - p.x) <= EPS && abs(y - p.y) <= EPS;
    }
    int opCmp(in Point p) const {
        double dx = x - p.x, dy = y - p.y;
        if (abs(dx) <= EPS) {
            if (abs(dy) <= EPS) return 0;
            return cast(int)(dy / abs(dy));
        } else {
            return cast(int)(dx / abs(dx));
        }
    }
    Point opBinary(alias op)(in Point p) const {
        static if (op == "+") {
            return Point(x + p.x, y + p.y);
        } else if (op == "-") {
            return Point(x - p.x, y - p.y);
        }
    }
    Point opBinary(alias op)(double k) const {
        static if (op == "*") {
            return Point(x * k, y * k);
        } else if (op == "/") {
            return Point(x / k, y / k);
        }
    }
}
double norm(in Point p) {
    return sqrt(p.x * p.x + p.y * p.y);
}

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

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

int ccw(Point a, Point b, Point c){
    b = b - a; c = c - a;
    if (cross(b, c) > EPS) return +1; 
    if (cross(b, c) < -EPS) return -1;
    if (dot(b, c) < 0) return +2;     
    if (b.norm < c.norm) return -2;  
    return 0;                       
}

double distance(in Point a, in Point b) {
    double dx = a.x - b.x,
           dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

struct Segment {
    Point a, b;
}

bool contains(in Segment s, in Point p) {
    Point u = s.a - p,
          v = s.b - p;
    return abs(cross(u, v)) < EPS && dot(u, v) < -EPS;
}

Point projection(in Segment s, in Point p) {
    Point u = s.b - s.a,
          v = p - s.a;
    double n = u.norm;
    return s.a + u * (dot(u, v) / (n * n));
}

double distance(in Segment s, in Point p) {
    auto ret = min(distance(p, s.a), distance(p, s.b));
    Point proj = s.projection(p);
    if (s.contains(proj)) {
        ret = min(ret, (p - proj).norm);
    }
    return ret;
}
double distance(in Point p, in Segment s) {
    return distance(s, p);
}

bool intersect(in Segment s, in Segment t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
           ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

double distance(in Segment s, in Segment t) {
    if (intersect(s, t)) return 0;
    return min( distance(s.a, t), distance(s.b, t),
                distance(s, t.a), distance(s, t.b) );
}

struct Line {
    Point a, b;
}
Point unit(in Line l) {
    /** l縺ョ蜊倅ス阪?繧ッ繝医Ν */
    return l.a * (1.0 / norm(l.b - l.a));
}
bool intersect(in Line m, in Line n) {
    double A = cross(m.b - m.a, n.b - n.a),
           B = cross(m.b - m.a, m.b - n.a);
    return (abs(A) > EPS || abs(B) < EPS);
}
Point intersection(in Line m, in Line n) {
    double A = cross(m.b - m.a, n.b - n.a),
           B = cross(m.b - m.a, m.b - n.a);
    if (abs(A) < EPS) {
        if (abs(B) < EPS) return m.a;
        else assert(0);
    }
    return n.a + (n.b - n.a) * B / A;
}

struct Circle {
    Point o;
    double r;
}

bool contains(in Circle c, in Point p) {
    /** 蜀?縺ォp縺悟性縺セ繧後ｋ縺? 
     *    p縺慶縺ョ蜻ィ荳翫↓縺ゅｋ縺ィ縺阪?蜷ォ縺セ繧後ｋ縺ィ縺ソ縺ェ縺?*/
    return distance(c.o, p) <= c.r + EPS;
}

Line[2] tangent(in Circle c, in Point p) {
    /** p繧帝?繧議縺ョ謗・邱壹ｒ霑斐☆.
     *    霑斐ｊ蛟、縺ョ2逶エ邱嗟, m縺ォ縺、縺?※ l.a == m.a == p */
    double l1 = distance(c.o, p);
    double l2 = sqrt(l1 * l1 - c.r * c.r);
    double d1 = (l2 * l2) / l1;
    double d2 = (c.r * l2) / l1;
    Point u = (c.o - p) / norm(c.o - p);
    Point b = p + u * d1;

    /* u縺ィ逶エ莠、縺吶ｋ蜊倅ス阪?繧ッ繝医Ν */
    Point o1 = Point(u.y, -u.x),
          o2 = Point(-u.y, u.x);

    Point a1 = b + o1 * d2,
          a2 = b + o2 * d2;
    return [ Line(p, a1), Line(p, a2) ];
}

struct Rectangle {
    Point v[4];
}
bool contains(in Rectangle r, in Point p) {
    /** 髟キ譁ケ蠖「r縺ォp縺悟性縺セ繧後ｋ縺? 
     *    r縺ョ蜻ィ荳翫↓p縺後≠繧九→縺阪?蜷ォ縺セ繧後ｋ縺ィ縺ソ縺ェ縺励※縺?↑縺?     *    蜃ク螟夊ァ貞ス「縺ォ荳?握蛹門庄閭ス */
    int c = ccw(p, r.v[0], r.v[1]);
    foreach (i; 0 .. 4) {
        if (c != ccw(p, r.v[i], r.v[(i + 1) % 4])) return false;
    }
    return true;
}

void main() {
    int N;
    Segment[] ss;

    bool input() {
        scanf("%d\n", &N);
        if (N == 0) return false;
        ss = new Segment[N];
        foreach (i; 0 .. N) {
            Point p, q;
            scanf("%lf %lf %lf %lf\n", &p.x, &p.y, &q.x, &q.y);
            ss[i] = Segment(p, q);
        }
        return true;
    }
    void solve() {
        int ans = N + 1;
        foreach (i; 0 .. N) {
            auto used = new RedBlackTree!(Point);
            foreach (j; i + 1 .. N) {
                if (ss[i].intersect(ss[j])) {
                    auto x = (cast(Line)ss[i]).intersection(cast(Line)ss[j]);
                    if (abs(x.x - 100) <= EPS || abs(x.x + 100) <= EPS) continue;
                    if (abs(x.y - 100) <= EPS || abs(x.y + 100) <= EPS) continue;
                    if (x in used) continue;
                    ans++;
                    used.insert(x);
                }
            }
        }
        writeln(ans);
    }
    while (input) solve;
}

Measured memory_bytes: 2136