#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define FOR(i, a, n) for (int i = (a); i < (n); ++i)
#define REP(i, n) FOR(i, 0, n)
using namespace std;

using T = long double;
const T INF = 1e10;
const T EPS = 1e-10;
const T PI = acos(-1.0);
T torad(int deg) {return (T)(deg) * PI / 180;}
T todeg(T ang) {return ang * 180 / PI;}
template <typename T> inline bool eq(T p, T q) { return abs(p - q) < EPS; }
inline int sgn(T x) { return (T(0) < x) - (x < T(0)); }

/* Point */
using P = complex<T>;
#define x real()
#define y imag()
inline T dot(P v, P w) { return (conj(v) * w).x; }
inline T cross(P v, P w) { return (conj(v) * w).y; }
inline T orient(P a, P b, P c) { return cross(b - a, c - a); }
inline bool isOrth(P v, P w) { return dot(v, w) == 0; }
inline bool isPara(P v, P w) { return cross(v, w) == 0; }
inline P unit(P v) { return v / abs(v); }
inline P translate(P p, P v) { return p + v; }
inline P scale(P p, P c, T k) { return c + (p - c) * k; }
inline P rot(P p, T a) { return p * polar(T(1), a); }
inline P rot90(P p) { return {-p.y, p.x}; }
inline P linearTransform(P p, P q, P fp, P fq, P r) { return fp + (r - p) * (fq - fp) / (q - p); }
bool cmpX(const P& a, const P& b) { return a.x != b.x ? a.x < b.x : a.y < b.y; }
bool cmpY(const P& a, const P& b) { return a.y != b.y ? a.y < b.y : a.x < b.x; }
namespace std {
    istream& operator>>(istream& is, P& p) { T xx, yy; is >> xx >> yy; p = P(xx, yy); return is; }
    bool operator < (const P& a, const P& b) { return cmpX(a, b); }
}

/* Line */
struct L : array<P, 2> {
    P v; T c;
    L() = default;
    explicit L(P a, P b) : array<P, 2>({a, b}), v(b - a), c(cross(v, a)) {}
    T side(P p) { return cross(v, p) - c; }
    P proj(P p) { return p - rot90(v) * side(p) / norm(v); }
    P refl(P p) { return p - rot90(v) * T(2) * side(p) / norm(v); }
    bool onLine(P p) { return abs(side(p)) < EPS; }
    bool onSegment(P p) { return onLine(p) && dot(this->operator[](0) - p, this->operator[](1) - p) <= EPS; }
    friend istream& operator>>(istream& is, L& l) { P p, q; is >> p >> q; l = L(p, q); return is; }
    friend ostream& operator<<(ostream& os, const L& l) { return os << '{' << l[0] << ", " << l[1] << '}'; }
};

/* Circle */
struct C : P {
    T r;
    C() = default;
    C(P p, T r) : P(p), r(r) {}
    friend istream& operator>>(istream& is, C& c) { P p; T r; is >> p >> r; c = C(p, r); return is; }
    friend ostream& operator<<(ostream& os, const C& c) { return os << '(' << c.x << ", " << c.y << ", " << c.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) - EPS) return -2;  // a--b--c on line or a==b
    return 0;                                // a--c--b on line or a==c or b==c
}

int isInterCC(C a, C b) {
    T d = abs(b - a);
    if (a == b && a.r == b.r) return 0;         // ∞ cp (A = B)
    if (a.r + d - b.r < -EPS) return +1;        // 0 cp (A in B)
    if (b.r + d - a.r < -EPS) return -1;        // 0 cp (B in A)
    if (abs(a.r + d - b.r) < EPS) return +2;    // 1 cp (A in B)
    if (abs(b.r + d - a.r) < EPS) return -2;    // 1 cp (B in A)
    if (abs(a.r + b.r - d) < EPS) return 3;     // 1 cp (outside)
    if (a.r + b.r - d < -EPS) return 4;         // 0 cp (outside)
    return 5;                                   // 2 cp
}

vector<P> tangentPoints(C c, P p) {
    if (eq(abs(p - c), c.r)) return vector<P>{p};
    vector<P> res;
    T t = acos(c.r / abs(p - c));
    P q = (p - c) / abs(p - c) * c.r;
    res.push_back(c + q * polar(T(1), t));
    res.push_back(c + q * polar(T(1), -t));
    sort(res.begin(), res.end(), cmpX);
    return res;
}
vector<L> tangentLines(C c1, C c2, bool inner) {
    if (abs(isInterCC(c1, c2)) <= 1) return vector<L>();
    if (inner) c2.r = -c2.r;
    vector<L> res;
    P d = c2 - c1;
    T dr = c1.r - c2.r, d2 = norm(d), h2 = d2 - dr * dr;
    if (d2 == 0 || h2 < 0) { assert(h2 != 0); return res; }
    for (T sign : {-1, 1}) {
        P v = (d * dr + rot90(d) * sqrt(h2) * sign) / d2;
        res.emplace_back(c1 + v * c1.r, c2 + v * c2.r);
    }
    return res;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    while (cin >> N, N) {
        vector<C> cs(N);
        vector<int> m(N);
        REP (i, N) cin >> cs[i] >> m[i];
        REP (i, N) cs.emplace_back(cs[i], cs[i].r + m[i]);

        if (N == 1) {
            cout << 1 << endl;
            continue;
        }

        auto count = [&](L& l) -> int {
            int res = 0;
            REP (i, N) {
                T d = abs(cs[i] - l.proj(cs[i]));
                res += (d >= cs[i].r - EPS && d <= cs[i].r + m[i] + EPS);
            }
            return res;
        };
        int ans = 0;
        REP (i, cs.size()) FOR (j, i + 1, cs.size()) {
            for (auto l : tangentLines(cs[i], cs[j], true)) {
                ans = max(ans, count(l));
            }
            for (auto l : tangentLines(cs[i], cs[j], false)) {
                ans = max(ans, count(l));
            }
        }
        cout << ans << endl;
    }
}


Measured memory_bytes: 3372