#include<complex>
#include<vector>
#include<iostream>
#include<stack>
#include<cmath>

#define CIRCLE_SAME 0x01
#define CIRCLE_CONTAIN 0x02
#define CIRCLE_NO_CROSS 0x04
#define CIRCLE_ONE_CROSS 0x08
#define CIRCLE_ONE_INSIDE_CROSS 0x10
#define CIRCLE_TWO_CROSS 0x20

#define REP(i,n) for(int i = 0; i < (int)(n); ++i)

#define sc second
#define fr first

using namespace std;

typedef double elem;
typedef complex<elem> point, vec;
typedef pair<point, point> line, seg, pp;

const double eps = 1.0e-8;
const double pi = acos(-1.0);
point base(0,0);

// oÍ
ostream &operator<<(ostream &os, const pair<point,point> &p){
  os << p.fr << "-" << p.sc;
  return os;
}

// lZ
inline elem sq(elem a){ return a*a; }
inline elem cq(elem a){ return a*a*a; }

// pxÏ·
elem rad(elem deg){ return (deg/180)*pi; }
elem deg(elem rad){ return (rad*180)/pi; }

// ®¬_Ìô¢AÈÇ
bool eq(elem a, elem b){ return abs(a-b) < eps; }
bool lt(elem a, elem b){ return !eq(a,b) && a < b; }
bool leq(elem a, elem b){ return eq(a,b) || a < b; }
bool gt(elem a, elem b){ return !eq(a,b) && a > b; }
bool geq(elem a, elem b){ return eq(a,b) || a > b; }
bool ltz(elem a){ return lt( a, 0 ); }
bool gtz(elem a){ return gt( a, 0 ); }
bool eqv(vec a, vec b){ return eq( abs(b-a),0); }
bool is_zv(vec v){ return eq(abs(v),0); }
elem emax(elem a, elem b){ return gt(a,b)?a:b; }
elem emin(elem a, elem b){ return lt(a,b)?a:b; }

// _Iy[^
bool far(point a, point b){ return gtz( abs(b-a) ); }
bool near(point a, point b){ return leq( abs(b-a), 0 ); }
elem dot(vec a, vec b){ return (a.real() * b.real() + a.imag() * b.imag() ); }
elem cross(vec a, vec b){ return ( a.real() * b.imag() - a.imag() * b.real() ); }

// a©çbÜÅvñèÌpxAàpA]ñ]
elem varg(vec a, vec b){
  elem ret=arg(a)-arg(b);
  if(lt(ret,0))ret+=2*pi;
  if(gt(ret,2*pi))ret-=2*pi;
  if(eq(ret,2*pi))ret=0;
  return ret;
}
elem arg(vec a, vec b){ return acos( dot(a,b) / ( abs(a) * abs(b) ) ); }
point rot(point p, elem theta){ return p * polar((elem)1.0, theta); }
point rotdeg(point p, elem deg){ return p * polar((elem)1.0, rad(deg)); }

// ñ_Ô£A¼üÆ_ÌÅZ£AüªÆ_ÌÅZ£
elem dist(point a, point b){ return abs(a-b); }
elem dist_l(line l, point x){ return abs(cross(l.sc-l.fr,x-l.fr)) / abs(l.sc-l.fr); }
elem dist_seg(seg s, point x)
{
  if( ltz( dot(s.sc-s.fr,x-s.fr) ) ) return abs(x-s.fr);
  if( ltz( dot(s.fr-s.sc,x-s.sc) ) ) return abs(x-s.sc);
  return dist_l(s,x);
}

// PÊxNgA@üxNgAPÊ@üxNg
vec uvec(vec a){ return a / abs(a); }
vec nmr(vec a){ return a * vec(0,-1); }
vec nml(vec a){ return a * vec(0,1); }
vec unmr(vec a){ return uvec( nmr(a) ); }
vec unml(vec a){ return uvec( nml(a) ); }

struct circle{
  point c;
  elem r;
  circle():c(point(0,0)),r(0){}
  circle(point c, elem r):c(c),r(r){}
  bool incircle(point t){
    return leq( abs(t-c), r);
  }
};

// ð_ÆÊuÖWÖÌiÖ
elem circles_k(circle c1, circle c2){
  elem d = abs(c1.c-c2.c);
  return ( sq( c1.r ) - sq( c2.r ) + sq( d ) ) / ( 2 * sq( d ) );
}
elem circles_x(circle c1, circle c2){
  elem d = abs(c1.c-c2.c);
  elem k = circles_k(c1,c2);
  elem x = sqrt( sq(c1.r) - sq( d * k ) );
  return x;
}

// 2~ÌÊuÖW
int circles_relation(circle c1, circle c2){
  if(lt(c1.r,c2.r))swap(c1,c2);
  elem d=abs(c1.c-c2.c);
  if(near(c1.c,c2.c)&&eq(c1.r,c2.r))return CIRCLE_SAME;
  if((c1.incircle(c2.c))&&lt(d+c2.r,c1.r))return CIRCLE_CONTAIN;
  if(gt(d,c1.r+c2.r))return CIRCLE_NO_CROSS;
  elem x = circles_x( c1, c2 );
  if( eq( x, 0 ) ){
    if(c1.incircle(c2.c))return CIRCLE_ONE_INSIDE_CROSS;
    return CIRCLE_ONE_CROSS;
  }else CIRCLE_TWO_CROSS;
}

// CÓÌñÂÌ~Ìð_
int intersection_circles(circle c1, circle c2, pp &p)
{
  if( !( circles_relation( c1, c2 ) & (CIRCLE_ONE_INSIDE_CROSS | CIRCLE_ONE_CROSS | CIRCLE_TWO_CROSS) ) )
    return 0;

  vec ab = c2.c - c1.c;
  elem k = circles_k( c1, c2 );
  point t = k * ab + c1.c;
  elem x = circles_x( c1, c2 );
  
  if( eq( x, 0 ) ){
    /* ð_ðêÂ¾¯Â */
    p.first = t; return 1;
  }else{
    /* ð_ðñÂÂ */
    vec abr = unmr( ab ); vec abl = unml( ab );
    vec vp1 = x * abr; vec vp2 = x * abl;
    p.first = vp1 + t; p.second = vp2 + t;
    return 2;
  }
}
// ñ~Ì¤ÊÚü(4{ÌÝ)
int circles_tangential( circle c1, circle c2, vector<line> &ret ){
  pair<point,point> pcross;
  elem r1 = c1.r;
  elem r2 = c2.r;
  elem D = abs(c2.c-c1.c);

  int rel = circles_relation( c1, c2 );
  intersection_circles(c1,c2,pcross);
  if( rel & ( CIRCLE_SAME | CIRCLE_CONTAIN ) ) return 0;
  if( rel & ( CIRCLE_ONE_INSIDE_CROSS ) ){
    point p=pcross.first;
    cout << " P : " << p << endl;
    vec v = p-c1.c;
    ret.push_back( line(p,p+unmr(v)) );
    return 1;
  }
  elem theta0 = varg(c2.c-c1.c,vec(1,0));
  point S2(D*(r1/(r1+r2)),0);
  elem theta1 = asin( (r2-r1)/D );
  elem theta2 = asin( (r1+r2)/D );
  point S1_1(rot(point(0,r1),theta1));
  point S1_2(rot(point(0,r1),-theta1-pi));
  vec u(1,0);
  S1_1 = rot(S1_1,theta0) + c1.c;
  S1_2 = rot(S1_2,theta0) + c1.c;
  S2 = rot(S2,theta0) + c1.c;
  // OÚü
  ret.push_back( line(S1_1, S1_1 + rot(u,theta0+theta1) ) );
  ret.push_back( line(S1_2, S1_2 + rot(u,theta0-theta1) ) );
  if( rel == CIRCLE_TWO_CROSS ) return 2;
  // àÚü
  ret.push_back( line(S2, S2 + rot(u,theta0+theta2) ) );
  if( rel == CIRCLE_ONE_CROSS ) return 3;
  ret.push_back( line(S2, S2 + rot(u,theta0-theta2) ) );
  return 4;
}

int main(){
  while(true){
    int n;
    int ans = 0;
    cin >> n;
    if(n==0)break;
    vector<circle> jewels;
    vector<elem> jewels_m;
    vector<circle> circles;
    for(int i = 0; i < n; ++i){
      elem x, y, r, m;
      cin >> x >> y >> r >> m;
      circles.push_back(circle(point(x,y),r));
      circles.push_back(circle(point(x,y),m+r));
      jewels.push_back(circle(point(x,y),r));
      jewels_m.push_back(m+r);
    }

    for(int i = 0; i < (int)circles.size(); ++i){
      for(int j = i+2; j < (int)circles.size(); ++j){
	if( j - i <= 1 )continue;
	vector<line> vl;
	circles_tangential( circles[i], circles[j], vl );
	for(int k = 0; k < vl.size(); ++k){
	  line l = vl[k];
	  int cnt = 0;
	  //cout << " LINE : " << vl[k] << endl;
	  for(int m = 0; m < jewels.size(); ++m){
	    elem d = dist_l(l,jewels[m].c);
	    if(leq(d,jewels_m[m])&&geq(d,jewels[m].r))++cnt;
	  }
	  ans = max(ans,cnt);
	}
	//cout << endl;
      }
    }
    if(n==1)ans=1;
    
    cout << ans << endl;
  }
  return 0;
}