#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <algorithm>
#include <cmath>
#include <climits>
#include <cstdio>
#include <complex>
using namespace std;

typedef long long LL;
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<vector<int> > vii;
typedef vector<vector<string> > vss;
typedef pair<int, int> pii;
#define x first
#define y second
#define INF 0x7fffffff
//#define INFLL 0x7fffffffffffffff
#define INFLL LLONG_MAX
#define SIZE(v) int((v).size())
#define ALL(v) (v).begin(), (v).end()
#define FOR(i,x) for(int i=0;i<x;i++)
#define FORic(i,y,x) for(int i=y;i<=x;i++)
#define FORdc(i,y,x) for(int i=y;i>=x;i--)
#define FILL(a,v) memset(a, v, sizeof(a))
#define PI 3.14159265358979323846

const double EPS = 1e-7;
typedef complex<double> P; /* _ */
typedef vector<P> G; /* ½p` */
struct L { P p, q; L(P p, P q) : p(p), q(q) {} }; /* üª */
typedef pair<P,double> C; /* ~ */

// complexÉå¬ÖWªKvÈê
namespace std{
	bool operator < (const P &a, const P &b){ return make_pair(real(a),imag(a)) < make_pair(real(b),imag(b)); }
}

// àÏEOÏEpx
double dot(P a, P b) { return real(conj(a)*b); }
double cross(P a, P b) { return imag(conj(a)*b); }
double angle(P a, P b) { return arg(conj(a)*b); }

// _pÆ´_Ì£yÌñæzðßé
// iüÍp1-p2ðøÉæêÎ2_ÔÌ£yÌñæzÆÈéj
double pLen2(P p){
	return real(p)*real(p)+imag(p)*imag(p);
}

// ½Ë(distSPÅgp)
P proj(L l, P p) {
	double t = dot(p-l.p, l.p-l.q) / sqrt(pLen2(l.p-l.q));
	return l.p + t*(l.p-l.q);
}

// ¼ülÆüªsªð··é©ð»è·é
bool lsIntersect(L l, L s) {
  return abs(cross(l.q-l.p, s.p-l.p)*cross(l.q-l.p, s.q-l.p)) < EPS;
}

// üªaÆüªbªð··é©ð»è·é
bool ssIntersect(L a, L b){
	if(abs(imag((a.q-a.p)/(b.q-b.p)))<EPS) return false;
	return cross(a.q-a.p, b.p-a.p)*cross(a.q-a.p, b.q-a.p) < 0 &&
    	   cross(b.q-b.p, a.p-b.p)*cross(b.q-b.p, a.q-b.p) < 0;
}

// _pª¼ülãÉ¶Ý·é©ð»è
bool lpIntersect(L l, P p){
	return abs(imag((p-l.p)/(l.q-l.p)))<EPS;
}

// _pªüªlãÉ¶Ý·é©ð»è·éi¸x¤j
bool spIntersect(L l, P p){
	//return abs( abs(l.p-p)+abs(l.q-p)-abs(l.q-l.p) ) < EPS; // ¸xðCÉµÈ¢Èç±êH
	if(lpIntersect(l, p)){
		if((real(l.p)-real(p))*(real(l.q)-real(p))<=0){
		if((imag(l.p)-imag(p))*(imag(l.q)-imag(p))<=0){
			return true;
		}}
	}
	return false;
}

// üªaÆüªbÌð_ðvZ·éDæÉð·»èªK{D
P ssCrosspoint(L a, L b){
	double A = cross(a.q-a.p, b.q-b.p);
	double B = cross(a.q-a.p, a.q-b.p);
	return b.p + B/A * (b.q-b.p);
}

// ¼üaÆ¼übª¯êÌàÌ©ð»è·é
bool sameLine(L a, L b){
	return lpIntersect(a,b.p)&&lpIntersect(a,b.q);
}

// üªlÆ_pÌ£ðßé
double distLP(L l, P p){
	return abs(cross(l.q-l.p,p-l.p))/abs(l.q-l.p);
}

// ¼üÆ¼üÌ£ðßéiÀsÌj
double distLL(L l, L m) {
	return sameLine(l, m) ? 0.0 : distLP(l, m.p);
}

// ¼ülÆüªsÌ£ðßé
double distLS(L l, L s) {
	if (lsIntersect(l, s)) return 0.0;
	return min(distLP(l, s.p), distLP(l, s.q));
}

// üªsÆ_pÌ£ðßé
double distSP(L s, P p) {
	P r = proj(s, p);
	if (spIntersect(s, r)) return abs(r - p);
	return min(abs(s.p - p), abs(s.q - p));
}

// üªsÆüªtÌ£ðßé
double distSS(L s, L t) {
  if (ssIntersect(s, t)) return 0;
  return min(min(distSP(s, t.p), distSP(s, t.q)),
             min(distSP(t, s.p), distSP(t, s.q)));
}

// üªaÆüªbªI[o[bvµÄ¢é©ð»è·é
bool ssOverlap(L a, L b){
	if(spIntersect(a,b.p)&&lpIntersect(a,b.q)) return true;
	if(spIntersect(a,b.q)&&lpIntersect(a,b.p)) return true;
	if(spIntersect(b,a.p)&&lpIntersect(b,a.q)) return true;
	if(spIntersect(b,a.q)&&lpIntersect(b,a.p)) return true;
	return false;
}

// üªÌWresÅüªlÆdÈéüªð}[WµCresðXV·é
void mergeLine(vector<L> &res, L l){
	int n = res.size();
	vector<L>::iterator it = res.begin();
	while(it!=res.end()){
		if(ssOverlap((*it), l)){
			P dir(l.q-l.p);
			double m = 0.0, M = 1.0;
			m = min(m, real((it->p-l.p)/dir));
			M = max(M, real((it->p-l.p)/dir));
			m = min(m, real((it->q-l.p)/dir));
			M = max(M, real((it->q-l.p)/dir));
			l = L(l.p+m*dir,l.p+M*dir);
			it = res.erase(it);
		} else {
			it++;
		}
	}
	res.push_back(l);
}

// ¤ÊÚüðÔ·
vector<L> getCommonTangent(C c1, C c2){
	vector<L> ans;
	if(c1.second > c2.second) swap(c1, c2);
	P dir = c1.first-c2.first;
	double dist = abs(c1.first-c2.first);
	dir = dir/dist*c2.second;
	if(dist + c1.second < c2.second - EPS) return ans;

	for(int sgn=-1;sgn<=1;sgn+=2){
		double cs = (c2.second+sgn*c1.second)/dist;
		P d = P(cs, sqrt(1-cs*cs));
		ans.push_back(L(c2.first+dir*d, c2.first+dir*d*P(1,1)));
		if(imag(d) > EPS)
			ans.push_back(L(c2.first+dir*conj(d), c2.first+dir*conj(d)*P(1,1)));
		if(dist+EPS < c1.second+c2.second) break;
	}
	return ans;
}

// ½p`gÌÊÏðßé
double polygonArea(G g){
	double res = 0.0;
	for(int i=0;i<g.size();i++)
		res += cross(g[i],g[(i+1)%g.size()]);
	return abs(0.5*res);
}

// _pª½p`gÌàÉ é©Ç¤©ð»è·é
bool contains(G g, P p){
	bool in = false;
	for(int i=0;i<g.size();i++){
		P a(g[i]-p), b(g[(i+1)%g.size()]-p);
		if(imag(a) > imag(b)) swap(a,b);
		if(imag(a)<=0&&0<imag(b))
			if(cross(a,b)<0) in = !in;
		if(abs(cross(a,b))<EPS&&dot(a,b)<EPS) return true; // üãÉpª¶Ý
	}
	return in;
}



int main(){
	int n;
	while(cin>>n){
		if(!n) break;
		vi x, y, r, m;
		FOR(i, n){
			int tx,ty,tr,tm;
			cin>>tx>>ty>>tr>>tm;
			x.push_back(tx);
			y.push_back(ty);
			r.push_back(tr);
			m.push_back(tm);
		}
		if(n==1){
			cout<<1<<endl;
			continue;
		}
		vector<L> all;
		FORic(i, 0, n-2){
			FORic(j, i+1,n-1){
				vector<L> l[4];
				l[0] = getCommonTangent(C(P(x[i], y[i]), r[i]     ), C(P(x[j], y[j]), r[j]     ));
				l[1] = getCommonTangent(C(P(x[i], y[i]), r[i]+m[i]), C(P(x[j], y[j]), r[j]     ));
				l[2] = getCommonTangent(C(P(x[i], y[i]), r[i]     ), C(P(x[j], y[j]), r[j]+m[j]));
				l[3] = getCommonTangent(C(P(x[i], y[i]), r[i]+m[i]), C(P(x[j], y[j]), r[j]+m[j]));
				FOR(k, 4){
					FOR(s,SIZE(l[k])){
						all.push_back(l[k][s]);
					}
				}
			}
		}
		
		int ans = 0;
		FOR(i, SIZE(all)){
			int count = 0;
			FOR(j, n){
				double d = distLP(all[i], P(x[j],y[j]));
				if(r[j]<d+EPS && d-EPS<r[j]+m[j]) count++;
				if(i==18){
					//cout<<"dist "<<d<<endl;
				}
			}
			//cout<<"a["<<i<<"]"<<count;
			//cout<<": ("<<all[i].p.real()<<","<<all[i].p.imag()<<"), ";
			//cout<<"("<<all[i].q.real()<<","<<all[i].q.imag()<<")"<<endl;
			ans = max(ans, count);
		}
		cout<<ans<<endl;
	}
	return 0;
}

Measured memory_bytes: 1696