#include <iostream>
#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)
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 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) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

L l[12];
L tl[12];
double dp[12][2];

int main() {
  int n;
  while(cin >> n, n) {
    REP(i,n) {
      cin >> l[i][0].real() >> l[i][0].imag();
      cin >> l[i][1].real() >> l[i][1].imag();
    }
    REP(i,n)REP(j,2)dp[i][j] = INF;
    dp[0][0] = dp[0][1] = 0;
    double ans = INF;
    REP(i,n-1) {
      for (int j=i+1; j<n; ++j) {
        REP(ki,3) {
          if (i != 0 && ki == 2) continue;
          REP(kj,3) {
            if (j != n-1 && kj == 2) continue;
            REP(S,1<<(j-i-1)) {
              REP(k,n) tl[k] = l[k];
              REP(k,j-i-1) {
                if (S>>k&1) {
                  for (int h=i+k+2; h<=j; ++h) {
                    tl[h][0] = reflection(tl[i+1+k],tl[h][0]);
                    tl[h][1] = reflection(tl[i+1+k],tl[h][1]);
                  }
                }
              }
              L seg;
              if (ki == 2 && kj == 2) {
                // probably unnecessary
                continue;                
              } else if (ki == 2) {
                P pp = projection(tl[i], tl[j][kj]);
                seg = L(pp,tl[j][kj]);
              } else if (kj == 2) {
                P pp = projection(tl[j], tl[i][ki]);
                seg = L(tl[i][ki], pp);
              } else {
                seg = L(tl[i][ki], tl[j][kj]);
              }
              bool ok = 1;              
              double now = -1;
              for (int k=i; k<=j; ++k) {
                if (intersectSS(seg,tl[k])) {
                  double tmp = norm(crosspoint(seg,tl[k])-seg[0]);;
                  if (tmp < now) ok = 0;
                  else now = tmp;
                } else {
                  ok = 0;
                }
              }
              if (ok) {
                double len = abs(seg[0]-seg[1]);
                // if (i==0&&j==2&&ki==1&&kj==0) {
                //   cout << bitset<3>(S) << " " << len << endl;
                // }
                if (ki == 2) {
                  chmin(dp[j][kj], len);
                } else if (kj == 2) {
                  chmin(ans, dp[i][ki] + len);
                } else {
                  chmin(dp[j][kj], dp[i][ki] + len);
                }
                if (j == n-1 && kj != 2) {
                  chmin(ans, dp[j][kj]);
                }
              }
            }
          }
        }
      }
    }
    printf("%.10f\n", ans);
  }
}

Measured memory_bytes: 1272