#include <bits/stdc++.h>

using namespace std;

const double EPS = 1e-8;

template<class T>
ostream& operator<<(ostream& os, const vector<T>& vs) {
    if (vs.empty()) return os << "[]";
    os << "[" << vs[0];
    for (int i = 1; i < vs.size(); i++) os << " " << vs[i];
    return os << "]";
}

bool EQ(double a, double b) { return abs(a - b) < EPS; }

struct Point {
    double x, y;
    Point() {}
    Point(double x, double y) : x(x), y(y) {}
    Point operator+(const Point& p) const { return Point(x + p.x, y + p.y); }
    Point operator-(const Point& p) const { return Point(x - p.x, y - p.y); }
    Point operator*(double k) const { return Point(k * x, k * y); }
    Point operator/(double k) const { return Point(x / k, y / k); }
};
double dot(const Point& a, const Point& b) { return a.x * b.x + a.y * b.y; }
double cross(const Point& a, const Point& b) { return a.x * b.y - a.y * b.x; }
double norm(const Point& a) { return sqrt(dot(a, a)); }
Point rot90(const Point& p) { return Point(-p.y, p.x); } // 反時計回りに90度回転 
ostream& operator<<(ostream& os, const Point& p) { return os << "(" << p.x << "," << p.y << ")"; }
istream& operator>>(istream& is, Point& p) { return is >> p.x >> p.y; }

int ccw(Point a, Point b, Point c){
    b = b - a; c = c - a;
    if (cross(b, c) > EPS) return +1;      // a,b,cの順に反時計周り
    if (cross(b, c) < -EPS) return -1;     // a,b,cの順に時計周り
    if (dot(b, c) < 0) return +2;          // c--a--b 直線
    if (norm(b) < norm(c)) return -2;      // a--b--c 直線
    return 0;                              // a--c--b 直線
}

struct Circle {
    Point p;
    double r;
    Circle() {}
    Circle(const Point& p, double r) : p(p), r(r) {}
};
bool contains(const Circle& c, const Point& p) { return norm(c.p - p) < c.r + EPS; }
bool contains(const Circle& a, const Circle& b) { return b.r + norm(a.p - b.p) < a.r + EPS; }
bool intersects(const Circle& a, const Circle& b) {
    if (contains(a, b) || contains(b, a)) return false;
    return norm(a.p - b.p) < a.r + b.r + EPS;
}
ostream& operator<<(ostream& os, const Circle& c) {
    return os << "Circle[" << c.p << "," << c.r << "]";
}
istream& operator>>(istream& is, Circle& c) {
    return is >> c.p >> c.r;
}

vector<Point> crosspoints(const Circle& a, const Circle& b) {
    if (!intersects(a, b)) return vector<Point>();
    double d = norm(b.p - a.p);
    double x = (d * d + a.r * a.r - b.r * b.r) / (2 * d);
    double y = sqrt(a.r * a.r - x * x);
    Point v = b.p - a.p;
    vector<Point> ret(2);
    Point e = v / d;
    ret[0] = a.p + e * x + rot90(e) * y;
    ret[1] = a.p + e * x - rot90(e) * y;
    return ret;
}

struct Line {
    Point a, b;
    Line() {}
    Line(const Point& a, const Point& b) : a(a), b(b) {}
};
ostream& operator<<(ostream& os, const Line& l) {
    return os << "Line(" << l.a << "," << l.b << ")";
}

Point projection(const Line& l, const Point& p) {
    Point u = (p - l.a), v = (l.b - l.a);
    return l.a + (v / norm(v)) * (dot(u, v) / norm(v));
}

vector<Line> tangent(const Circle& c, const Point& p) {
    /** pを通るcの接線を返す.
     *    返り値の2直線l, mについて l.a == m.a == p */
    double l1 = norm(c.p - p);
    double l2 = sqrt(l1 * l1 - c.r * c.r);
    double d1 = (l2 * l2) / l1;
    double d2 = (c.r * l2) / l1;
    Point u = (c.p - p) / norm(c.p - 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;
    vector<Line> ret(2);
    ret[0] = Line(p, a1);
    ret[1] = Line(p, a2);
    return ret;
}

vector<Line> common_tangent(const Circle& a, const Circle& b) {
    vector<Line> ret;
    vector<Point> ps;
    Point v = b.p - a.p;
    double d = norm(v);
    if (!EQ(a.r, b.r)) ps.push_back(a.p + v * a.r / (a.r - b.r));
    if (!intersects(a, b)) ps.push_back(a.p + v * a.r / (a.r + b.r));
    for (int i = 0; i < ps.size(); i++) {
        Point& p = ps[i];
        vector<Line> ts = tangent(a, p);
        ret.insert(ret.end(), ts.begin(), ts.end());
    }
    if (EQ(a.r, b.r)) {
        ret.push_back(Line(a.p + rot90(v) / d * a.r, b.p + rot90(v) / d * b.r));
        ret.push_back(Line(a.p - rot90(v) / d * a.r, b.p - rot90(v) / d * b.r));
    }
    return ret;
}

int N;
vector<Circle> js; // jewels
vector<double> ms; // magnets' strength

bool input() {
    cin >> N;
    if (N == 0) return false;
    js.clear(); js.resize(N);
    ms.clear(); ms.resize(N);
    for (int i = 0; i < N; i++) {
        cin >> js[i] >> ms[i];
    }
    return true;
}

double dist(const Line& l, const Point& p) {
    Point a = projection(l, p);
    return norm(a - p);
}

bool check(const Line& l, int index) {
    Circle a = js[index];
    Circle b = js[index]; b.r += ms[index];
    if (dist(l, a.p) + EPS < a.r) {
        return false;
    }
    return dist(l, b.p) < b.r + EPS;
}

int count(const Line& l) {
    int ret = 0;
    for (int i = 0; i < N; i++) {
        if (check(l, i)) ret++;
    }
    return ret;
}

void solve() {
    vector<Line> ls;
    for (int i = 0; i < N; i++) {
        for (int j = i + 1; j < N; j++) {
            vector<Circle> as;
            as.push_back(js[i]);
            as.push_back(Circle(js[i].p, js[i].r + ms[i]));
            vector<Circle> bs;
            bs.push_back(js[j]);
            bs.push_back(Circle(js[j].p, js[j].r + ms[j]));
            for (int k = 0; k < 2; k++) {
                for (int l = 0; l < 2; l++) {
                    if (intersects(as[k], bs[l])) {
                        vector<Point> ps = crosspoints(as[k], bs[l]);
                        ls.push_back(Line(ps[0], ps[1]));
                    } else {
                        vector<Line> ts = common_tangent(as[k], bs[l]);
                        ls.insert(ls.end(), ts.begin(), ts.end());
                    }
                }
            }
        }
    }
    int ans = 1;
    for (int i = 0; i < ls.size(); i++) {
        ans = max(ans, count(ls[i]));
    }
    cout << ans << endl;
}

int main() {
    while (input()) solve();
    return 0;
}

Measured memory_bytes: 2788