#include <iostream>
#include <cstdio>
#include <iomanip>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#include <utility>
#include <numeric>
#include <algorithm>
#include <functional>
#include <cctype>
#include <complex>
#include <string>
#include <sstream>
#include <fstream>
#include <cassert>
using namespace std;

typedef long long ll;
//typedef pair<int, int> P;
#define ISEQ(c) (c).begin(), (c).end()
#define REP(i,n) for(int i=0;i<(int)(n);++i)

#define DUMP(x)  cerr << #x << " = " << (x)
#define DUMPLN(x)  DUMP(x) <<endl
#define DEBUG(x) DUMP(x) << LINE() << " " << __FILE__
#define DEBUGLN(x) DEBUG(x)<<endl
#define LINE()    cerr<< " (L" << __LINE__ << ")"
#define LINELN()    LINE()<<endl
#define CHECK(exp,act)  if(exp!=act){DUMPLN(exp);DEBUGLN(act);}
#define STOP(e)  CHECK(e,true);if(!(e)) exit(1);

namespace Ps{
	typedef  double D;
	typedef complex<D> P;
	const D EPS = 1e-9;
	const D INF = 1e20;

#define X real()
#define Y imag()

	template<typename T> int sig(T a,T b=0){return a<b-EPS?-1:a>b+EPS?1:0;}
	template<typename T> bool eq(T a,T b){ return sig(abs(a-b))==0;}
	template<typename T> D norm(T a){ return a*a;}
	// a×b
	D cross(const P& a,const P& b){
		return imag(conj(a)*b);
	}
	// a・b
	D dot(const P&a,const P& b) {
		return real(conj(a)*b);
	}

	int ccw(const 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;
	}

	//浮動小数点modで非負の値のみかえす．
	D pfmod(D v,D MOD){
		return fmod(fmod(v,MOD)+MOD,MOD);
	}

	//[0,PI)
	D AbsArg(D a){
	  	D ret=pfmod(max(a,-a),2*M_PI);
	  	return min(ret,2*M_PI-ret);
	}
	
}
using namespace Ps;


namespace Ls{
	struct L : public vector<P> {
	  L(const P &a, const P &b) {
	    push_back(a); push_back(b);
	  }
	};

	//直線へ射影した時の点
	P projection(const L &l, const P &p) {
	  D t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
	  return l[0] + t*(l[0]-l[1]);
	}

	D distanceLP(const L &l, const P &p) {
	  return abs(p - projection(l, p));
	}

}
using namespace Ls;

namespace std{
	bool operator < (const P& a,const P& b){
    		return a.X != b.X ? a.X < b.X : a.Y < b.Y;
  	}
  	bool operator == (const P& a,const P& b){
    		return eq(a,b);
   	}
};

namespace Cs{
	int INF=1<<28;
	struct C {
 		 P o; D r;
 		 C(const P &o,D r) : o(o), r(r) { }
	};

	// 包含関係
	enum RELATION{INCOMPARABLE=0,SAME=1,CONTAIN=2,OVER=4};
	pair<RELATION,int> cRel(const C& c1,const C& c2){
		D d=abs(c1.o-c2.o);
		if(eq(c1.o,c2.o) && eq(c1.r,c2.r))return make_pair(SAME,INF);// c1 == c2
		if(sig(d,c1.r-c2.r)<0)return make_pair(OVER,0); // c2 ⊆ c1
		if(sig(d,c2.r-c1.r)<0)return make_pair(CONTAIN,0); // c1 ⊆ c2
		if(sig(d,c1.r-c2.r)==0)return make_pair(OVER,1);// c2 ⊆ c1,1点で接する
		if(sig(d,c2.r-c1.r)==0)return make_pair(CONTAIN,1);// c1 ⊆ c2,1点で接する
		if(sig(d,c1.r+c2.r)==0)return make_pair(INCOMPARABLE,1);// 1点で接する
		if(sig(d,c1.r+c2.r)<0)return make_pair(INCOMPARABLE,2);//  2点で接する
		return make_pair(INCOMPARABLE,0);// 交わらない
	}

	// 点p を通る 円c の接点
	vector<L> ContactCP(const C& c,const P& p){
		vector<L> res;
		P dir =p-c.o;D d=abs(dir);
		if(sig(c.r,d)==0){
			res.push_back(L(p,p+dir*P(0,1)));return res;
		}
		if(sig(c.r,d)>0)return res;

		D th=acos(c.r/d),ph=arg(dir);
		res.push_back(L(p,c.o+polar(c.r,ph+th)));res.push_back(L(p,c.o+polar(c.r,ph-th)));
		return res;
	}
	//角度 arg の 円c の接線
	L contactCP(const C& c,D arg){
		P p=polar(c.r,arg);return L(c.o+p-p*P(0,1),c.o+p+p*P(0,1));
	}

	//2円 c1,c2の共通接線
	vector<L> ContactCC(const C& c1,const C& c2){
		pair<RELATION,int> rel=cRel(c1, c2);
		vector<L> res;
		if(rel.first==SAME)return res;
		P dir=c2.o - c1.o;D t=arg(dir);
		//external
		if(rel.first==INCOMPARABLE || rel.second>0){
			D a=acos((c2.r-c1.r)/abs(dir));
			res.push_back(contactCP(c1,t+a));
			if(sig(a)!=0)res.push_back(contactCP(c1,t-a));
		}
		//internal
		if(rel.first==INCOMPARABLE && rel.second<2){
			D a=acos((c2.r+c1.r)/abs(dir));
			res.push_back(contactCP(c1,t+a));
			if(sig(a)!=0)res.push_back(contactCP(c1,t-a));
		}
		return res;
	}
}
using namespace Cs;

int main() {
	// ifstream cin("in");
	// ofstream coutf( "out" );
	while(true){
		int N;cin >> N;if(N==0)break;
		vector<C> cs1,cs2,cs;
		REP(i,N){
			D x,y,r,m;cin >> x >> y >>r >> m;
			cs1.push_back(C(P(x,y),r));cs2.push_back(C(P(x,y),r+m));
			cs.push_back(C(P(x,y),r));cs.push_back(C(P(x,y),r+m));
		}

		int Mv=0;if(N==1)Mv=max(Mv,1);
		REP(i,2*N)REP(j,2*N){
			vector<L> ls=ContactCC(cs[i],cs[j]);
			REP(k,ls.size()){
				int c=0;
				REP(s,N){
					D d=distanceLP(ls[k],cs2[s].o);
					if(sig(cs1[s].r,d)<=0 && sig(d,cs2[s].r)<=0){
						c++;
					}
				}
				Mv=max(Mv,c);
			}
		}
		cout << Mv <<endl;
	}	
}

Measured memory_bytes: 1392