#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<ll>>;

double eps = 0.0000001;
// asin(1.) * 2
double pi = 3.14159265358979323846264338327950288;
using p2 = complex<double>;
// x: real
// y: imag

double det(p2 v1, p2 v2) {
  return v1.real() * v2.imag() - v1.imag() * v2.real();
}

double dot(p2 v1, p2 v2) {
  return v1.real() * v2.real() + v1.imag() * v2.imag();
}

double dist2(p2 v) { return dot(v, v); }

double dist(p2 v) { return sqrt(dist2(v)); }

bool same(double x, double y) { return fabs(x - y) < eps; }

double dist2(p2 l1, p2 l2) { return dot(l1 - l2, l1 - l2); }

double dist(p2 l1, p2 l2) { return sqrt(dist2(l1, l2)); }

int ccw(p2 a, p2 b, p2 c) {
  b -= a;
  c -= a;
  if (det(b, c) > eps)
    return 1;
  if (det(b, c) < -eps)
    return -1;
  if (dot(b, c) < -eps)
    return 2;
  if (dist2(b) < dist2(c))
    return -2;
  return 0;
}

auto p2comp = [](const p2 &l, const p2 &r) {
  if (fabs(l.real() - r.real()) > eps)
    return l.real() < r.real();
  return l.imag() < r.imag();
};

struct Line {
  p2 st, ed;

  Line(p2 st, p2 ed) : st(st), ed(ed) {}

  Line(double x1, double y1, double x2, double y2)
      : st(p2(x1, y1)), ed(p2(x2, y2)) {}

  Line(p2 st, double x, double y) : st(st), ed(p2(x, y)) {}

  Line(double x, double y, p2 ed) : st(p2(x, y)), ed(ed) {}

  double dist() { return sqrt(dist2(st, ed)); }

  bool isPalla(Line l) { return fabs(det(ed - st, l.ed - l.st)) < eps; }

  double x() { return ed.real() - st.real(); }

  double y() { return ed.imag() - st.imag(); }

  p2 v() { return ed - st; }
};

// l1.st + (l1.st - l1.ed) * r.first = l2.st + (l2.st - l2.ed) * r.second
// 方程式を満たす(r.first, r.second)を返す
// l1.isPalla(l2) => (nan, nan)
pair<double, double> interP(Line l1, Line l2) {
  double a = l1.x();
  double b = -l2.x();
  double c = l1.y();
  double d = -l2.y();
  double inv = 1. / (a * d - c * b);
  double e1 = -l1.st.real() + l2.st.real();
  double e2 = -l1.st.imag() + l2.st.imag();
  return make_pair((d * e1 - b * e2) * inv, (-c * e1 + a * e2) * inv);
}

bool intersec(Line l1, Line l2) {
  if (l1.isPalla(l2))
    return false;
  auto r = interP(l1, l2);
  return eps < r.first && r.first < 1. - eps && eps < r.second &&
         r.second < 1. - eps;
}

double inter_r(Line l, p2 c) { return dot(c - l.st, l.v()) / dist2(l.v()); }

double dist(Line l, p2 c) {
  double r = inter_r(l, c);
  if (r < -eps)
    return dist(l.st, c);
  if (r > 1. + eps)
    return dist(l.ed, c);
  return dist(l.st + l.v() * r, c);
}

p2 nearest(Line l, p2 c) {
  double r = inter_r(l, c);
  if (r < -eps)
    return l.st;
  if (1. + eps < r)
    return l.ed;
  return l.st + l.v() * r;
}

double dist(Line l1, Line l2) {
  if (intersec(l1, l2))
    return 0.;
  return min(min(dist(l1, l2.st), dist(l1, l2.ed)),
             min(dist(l2, l1.st), dist(l2, l1.ed)));
}

struct Poly {
  vector<p2> ps;
  double d;

  Poly(vector<p2> ps) : ps(ps) {
    d = 0;
    for (int i = 0; i < ps.size(); i++)
      d += dist(ps[i], ps[(i + 1) % ps.size()]);
  }

  // 頂点上/辺上は微妙
  bool include(p2 p) {
    // 半直線
    Line l(p, p2(-10000, -1));
    int c = 0;
    for (int i = 0; i < ps.size(); i++) {
      if (intersec(l, Line(ps[i], ps[(i + 1) % ps.size()])))
        c++;
    }
    return c % 2 == 1;
  }

  bool include(p2 p, bool on_vert, bool on_edge) {
    for (auto &q : ps)
      if (dist(p, q) < eps)
        return on_vert;
    for (int i = 0; i < ps.size(); i++) {
      if (ccw(ps[i], ps[(i + 1) % ps.size()], p) == 0)
        return on_edge;
    }
    return include(p);
  }

  bool intersecl(Line l) {
    for (int i = 0; i < ps.size(); i++) {
      if (intersec(l, Line(ps[i], ps[(i + 1) % ps.size()])))
        return true;
    }
    return false;
  }
};

vector<Line> star(p2 p, double deg, double r) {
  vector<p2> ps;
  double d = 2. / 5. * pi;
  for (int i = 0; i < 5; i++) {
    double theta = d * ((i * 3) % 5) + deg;
    ps.push_back(p2(-sin(theta) * r, cos(theta) * r) + p);
  }
  vector<Line> ls;
  for (int j = 0; j < 5; j++) {
    ls.push_back(Line(ps[j], ps[(j + 1) % 5]));
  }
  return ls;
}

struct N {
  int i;
  double d;
};

bool operator<(const N &l, const N &r) { return l.d < r.d; }

double dist(vector<Line> l1, vector<Line> l2) {
  double ret = numeric_limits<double>::infinity();
  for (auto &l : l1)
    for (auto &r : l2)
      ret = min(ret, dist(l, r));
  return ret;
}

int main() {
  while (true) {
    int n, s, t;
    cin >> n >> s >> t;
    if (n == 0)
      break;
    s--;
    t--;
    vector<vector<Line>> ls;
    for (int i = 0; i < n; i++) {
      double x, y, a, r;
      cin >> x >> y >> a >> r;
      ls.push_back(star(p2(x, y), a / 180. * pi, r));
    }
    multiset<N> q;
    q.insert(N{s, 0});
    vector<vector<double>> cost(n, vector<double>(n));
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        cost[j][i] = cost[i][j] = dist(ls[i], ls[j]);
      }
    }

    vector<bool> used(n);
    while (q.size()) {
      N now = *q.begin();
      q.erase(q.begin());
      if (used[now.i])
        continue;
      used[now.i] = true;
      if (now.i == t) {
        printf("%.20lf\n", now.d);
        break;
      }
      for (int i = 0; i < n; i++) {
        if (used[i])
          continue;
        q.insert(N{i, now.d + cost[now.i][i]});
      }
    }
  }
  return 0;
}


Measured memory_bytes: 3904