#include <iostream>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <vector>
#include <valarray>
#include <array>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <complex>
#include <random>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

typedef long double R;
typedef complex<R> P;

const R EPS = 1e-10;
const R PI = acos((R)(-1));

/*
 -1 -> neg
  0 -> near 0
  1 -> pos
  */
int sgn(R a) {
    if (a < -EPS) return -1;
    if (a > EPS) return 1;
    return 0;
}

/*
 -1 -> a > b
 0 -> a near b
 1 -> a < b
 */
int sgn(R a, R b) {
    return sgn(b-a);
}

bool near(P a, P b) {
    return !sgn(abs(a-b));
}

R cross(P a, P b) { return a.real()*b.imag() - a.imag()*b.real(); }
R dot(P a, P b) { return a.real()*b.real() + a.imag()*b.imag(); }

R ssqrt(R d) {
    d = max<R>(0, d);
    return sqrt(d);
}

R sacos(R d) {
    d = max<R>(-1, d);
    d = min<R>(1, d);
    return acos(d);
}



//?§???????[0, 2*PI)???
R radNorP(R x) {
    return fmod(fmod(x, 2*PI) + 2*PI, 2*PI);
}


struct L {
    P x, y;
    L() {};
    L(P x, P y) :x(x), y(y) {};
};

P vec(const L &l) {
    return l.y - l.x;
}

R abs(const L &l) {
    return abs(vec(l));
}

R distLP(const L &l, const P &p) {
    return abs(cross(vec(l), p-l.x)/abs(vec(l)));
}

struct C {
    P p;
    R r;
    C() {}
    C(P p, R r) : p(p), r(r) {}
};

//return number of cross point
int crossCC(const C &c, const C &d, R &l, R &r) {
    if (near(c.p, d.p) && !sgn(c.r, d.r)) {
        assert(false);
        return -1;
    }
    R di = abs(c.p - d.p);
    if (sgn(c.r+d.r, di) == 1) return 0;
    if (sgn(di, abs(c.r-d.r)) == 1) return 0;
    R bth = arg(d.p - c.p);
    R th = sacos((c.r*c.r + di*di - d.r*d.r) / (2*c.r*di));
    l = bth-th;
    r = bth+th;
    if (sgn(th) == 0) return 1;
    return 2;
}

int commonInternalTangent(const C &c, const C &d, L &l, L &r) {
    R di = abs(c.p - d.p);
    if (sgn(di, c.r + d.r) == 1) return 0;
    R th = sacos((c.r+d.r) / di);
    l.x = c.p + polar(c.r, arg(d.p-c.p)-th);
    l.y = l.x + polar<R>(1, arg(d.p-c.p)-th + PI/2);
    r.x = c.p + polar(c.r, arg(d.p-c.p)+th);
    r.y = r.x + polar<R>(1, arg(d.p-c.p)+th - PI/2);
    if (sgn(di, c.r+d.r) == 0) return 1;
    return 2;
}

int commonExternalTangent(const C &c, const C &d, L &l, L &r) {
    R di = abs(c.p - d.p);
    if (sgn(di, abs(c.r - d.r)) == 1) return 0;
    R th = sacos((c.r-d.r) / di);
    l.x = c.p + polar(c.r, arg(d.p-c.p)-th);
    l.y = l.x + polar<R>(1, arg(d.p-c.p)-th + PI/2);
    r.x = c.p + polar(c.r, arg(d.p-c.p)+th);
    r.y = r.x + polar<R>(1, arg(d.p-c.p)+th - PI/2);
    if (sgn(di, abs(c.r - d.r)) == 0) return 1;
    return 2;
}

const int MN = 55;

P p[MN];
R r[MN], m[MN];

bool solve() {
    int n;
    cin >> n;
    if (!n) return false;
    vector<C> c;
    for (int i = 0; i < n; i++) {
        R x, y;
        cin >> x >> y >> r[i] >> m[i];
        p[i] = P(x, y);
        c.push_back(C(p[i], r[i]));
        c.push_back(C(p[i], r[i]+m[i]));
    }

    int u = (int)c.size();

    vector<L> vl;
    for (int i = 0; i < u; i++) {
        P pp = c[i].p + P(c[i].r, 0);
        vl.push_back(L(pp, pp+P(0, 1)));
    }
    for (int i = 0; i < u; i++) {
        for (int j = i+1; j < u; j++) {
            L l, r;
            if (commonExternalTangent(c[i], c[j], l, r)) {
                vl.push_back(l); vl.push_back(r);
            }
            if (commonInternalTangent(c[i], c[j], l, r)) {
                vl.push_back(l); vl.push_back(r);
            }
        }
    }

    int ma = 0;
    for (L l: vl) {
        int sm = 0;
        for (int i = 0; i < n; i++) {
            R len = distLP(l, p[i]);
            if (sgn(r[i], len) != -1 && sgn(len, r[i]+m[i]) != -1) sm++;
        }
        ma = max(ma, sm);
    }
    printf("%d\n", ma);
    return true;
}

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

Measured memory_bytes: 4264