#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 long double D;
	typedef complex<D> P;
	const D EPS = 3*1e-2;
	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> double norm(T a){ return a*a;}
	// a×b
	double cross(const P& a,const P& b){
		return imag(conj(a)*b);
	}
	// a・b
	double 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で非負の値のみかえす．
	double pfmod(double v,double MOD){
		return fmod(fmod(v,MOD)+MOD,MOD);
	}

	//[0,PI)
	double AbsArg(double a){
	  	double 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{
	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,1<<28);// 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<P> ContactCP(const C& c,const P& p){
		vector<P> res;
		D d=abs(c.o-p);
		if(sig(c.r,d)==0){
			res.push_back(p);return res;
		}
		if(sig(c.r,d)>0)return res;

		D theta=acos(c.r/d),phi=arg(p-c.o);
		res.push_back(c.o + polar(c.r,phi+ theta));res.push_back(c.o + polar(c.r,phi- theta));		
		return res;
	}

	//共通接線  仮定：2円は異なる．
	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;
		//external
		if(rel.first==INCOMPARABLE || rel.second>0){
			D th=arg(dir),a=acos((c2.r-c1.r)/abs(dir));
			res.push_back(L(c1.o + polar(c1.r,th+a),c2.o + polar(c2.r,th+a)));
			if(sig(a)!=0)res.push_back(L(c1.o + polar(c1.r,th-a),c2.o + polar(c2.r,th-a)));
		}
		//internal
		if(rel.first==INCOMPARABLE && rel.second<2){
			D th=arg(dir),a=acos((c2.r+c1.r)/abs(dir));
			res.push_back(L(c1.o + polar(c1.r,th+a),c2.o + polar(c2.r,th+a + M_PI)));
			if(sig(a)!=0)res.push_back(L(c1.o + polar(c1.r,th-a),c2.o + polar(c2.r,th-a + M_PI)));
		}
		return res;
	}

}
using namespace Cs;

namespace std{
  	bool operator == (const C& a,const C& b){
    	return cRel(a,b).first==SAME;
   	}
};


int main() {
	// ifstream cin("in");
	// ofstream cout( "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);
		//		cout <<"d: "<<i<<" "<<j <<" "<<s<<":"<<distanceLP(ls[k],cs1[s].o)<<endl;
					if(sig(cs1[s].r,d)<=0 && sig(d,cs2[s].r)<=0)c++;

				}
				Mv=max(Mv,c);
			}
		}

		cout << Mv <<endl;		
	}
}

Measured memory_bytes: 1284