#include <bits/stdc++.h>
  
using namespace std;
  
#define rep(i,n) REP(i,0,n)
#define REP(i,s,e) for(int i=(s); i<(int)(e); i++)
#define pb push_back
#define all(r) (r).begin(),(r).end()
#define rall(r) (r).rbegin(),(r).rend()
#define fi first
#define se second
  
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
#define X real()
#define Y imag()

const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
typedef complex<double> P;
typedef complex<double> point;
namespace std {
	bool operator < (const P& a, const P& b) {
		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);
	}
};

typedef vector<P> G;
typedef vector<P> polygon;

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) > 0)   return +1;       // counter clockwise
	if (cross(b, c) < 0)   return -1;       // clockwise
	if (dot(b, c) < 0)     return +2;       // c--a--b on line
	if (norm(b) < norm(c)) return -2;       // a--b--c on line
	return 0;
}
//------------------------------------------------------------------------------------------
//---------????????????????????¢???-------------------------------------------------------------------
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 intersectSP(const L &s, const P &p) {
	return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
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 + 2.0 * (projection(l, p) - p);
}
double distanceLP(const L &l, const P &p) {
	return abs(p - projection(l, p));
}
double distanceLL(const L &l, const L &m) {
	return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const L &l, const L &s) {
	if (intersectLS(l, s)) return 0;
	return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const L &s, const P &p) {
	const P r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}
double distanceSS(const L &s, const L &t) {
	if (intersectSS(s, t)) return 0;
	return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
			min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}
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]);
}

//?????????????????????????????????
bool PinC(const P& p, const C& c) {
	return abs(p-c.p) < c.r+EPS;
}

//?????¨?????????????????¢???(??????????????£??????????????£?????????)
int pos_S_C(const L&s, const C&c){
	if(abs(distanceSP(s,c.p)-c.r)<EPS)	return 1;	//??\?????????
	if(distanceSP(s,c.p) > c.r+EPS) 	return 0;	//????????£????????????
	if(PinC(s[0], c) && PinC(s[1], c))	return 2;	//????????????
	if(PinC(s[0], c)||PinC(s[1], c))	return 3;	//?????´???????????????
	return 4;	//????????????
}

//point???theta???????????¢
point spinP(const point& p, double theta){
	return p*complex<double>(cos(theta),sin(theta));
}

//?????¨??´????????????(???????¨?)
vector<P> croossPoint(C c, L l) {
	int hit = pos_S_C(l, c);
	if(hit == 0) return {};
	
	double R = c.r;
	P sub = c.p;
	double theta;

	l[0] -= sub;
	l[1] -= sub;

	theta = atan2(imag(l[1]-l[0]), real(l[1]-l[0]));

	l[0] = spinP(l[0], -theta);
	l[1] = spinP(l[1], -theta);

	assert(abs(imag(l[0]-l[1])) < EPS);

	vector<P> ret;
	if(abs(abs(l[0].Y) - R) < EPS) ret.pb({0.0, l[0].Y});
	else {
		double y = l[0].Y;
		double x = sqrt(R*R-y*y);
		ret.pb({x, y});
		ret.pb({-x, y});
	}

	rep(i, ret.size()) {
		ret[i] = spinP(ret[i], theta);
		ret[i] += sub;
	}
	return ret;
}

//?????¨?§??????¨??????????????´????????????
L makeLine_p_theta(const P& p, double theta, double len = 1.0) {
	return {p, p + P{len*cos(theta), len*sin(theta)}};
}

//???????§????theta??§?????\???
L cTang(C c, double theta) {
	L l = makeLine_p_theta({c.r*cos(theta), c.r*sin(theta)}, theta+PI/2.0);
	l[0] += c.p;
	l[1] += c.p;
	return l;
}

// //????????±?????\???
// vector<L> comonTang(C c1, C c2) {
// 	vector<L> ret;
// 	if(c1.r > c2.r) swap(c1, c2);
		
// }
vector<L> comonTang(C c1, C c2) {
	vector<L> ret;
	if(c1.r > c2.r) swap(c1, c2);
	P sub = c1.p;
	double theta;
	c1.p -= sub;
	c2.p -= sub;
	theta = atan2(c2.p.Y, c2.p.X);

	c2.p = spinP(c2.p, -theta);
	int signX = 0;
	if(c2.p.X > 0) signX = 1;
	if(c2.p.X < 0) signX = -1;

	double x = abs(c2.p.X), r1 = c1.r, r2 = c2.r;
	if(x*x > (r2 - r1) * (r2 - r1)) {
		double theta2 = asin((r2-r1)/x);
		ret.pb({spinP({0, r1}, theta2), spinP({sqrt(x*x-(r2-r1)*(r2-r1)), r1}, theta2)});
		ret.pb({spinP({0, -r1}, -theta2), spinP({sqrt(x*x-(r2-r1)*(r2-r1)), -r1}, -theta2)});
	}
	if(x > r1+r2) {
		double theta3 = PI / 2 - acos((r1+r2)/x);
		double len = sqrt((r1*x)*(r1*x)/(r1+r2)/(r1+r2)-r1*r1) + sqrt((r2*x)*(r2*x)/(r1+r2)/(r1+r2)-r2*r2);
		ret.pb({spinP({0, r1}, -theta3), spinP({len, r1}, -theta3)});
		ret.pb({spinP({0, -r1}, -theta3), spinP({len, -r1}, theta3)});
	}
	

	for(auto& l : ret) {
		if(signX == -1) l[1] = {-l[1].X, l[1].Y};
		l[0] = spinP(l[0], theta);
		l[1] = spinP(l[1], theta);
		l[0] += sub;
		l[1] += sub;
	}
	return ret;
}


int main(){
	int n;
	while(cin >> n && n) {
		vector<C> c;
		vector<int> m(n);
		rep(i, n) {
			double x, y, r;
			cin >> x >> y >> r >> m[i];
			c.pb({{x, y}, r});
		}
		ll ans = 1LL;
		auto check = [&](const L& l) {
			ll tmp = 0LL;
			rep(k, n){
				double dist = distanceLP(l, c[k].p);
				if(dist > c[k].r - EPS && dist < c[k].r+m[k] + EPS) tmp++;
			}
			ans = max(ans, tmp);
		};
		rep(i, n) rep(j, i) {
			auto ls = comonTang(c[i], c[j]);
			for(auto& l : ls) check(l);
			ls = comonTang({c[i].p, c[i].r+m[i]}, c[j]);
			for(auto& l : ls) check(l);
			ls = comonTang(c[i], {c[j].p, c[j].r + m[j]});
			for(auto& l : ls) check(l);
			ls = comonTang({c[i].p, c[i].r+m[i]}, {c[j].p, c[j].r + m[j]});
		}
		cout << ans << endl;
	}
}

Measured memory_bytes: 3512