#include<iostream>
#include<complex>
#include<vector>
#include<cmath>
#include<algorithm>
#include<cstdio>

using namespace std;

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

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

typedef complex<double> P;
typedef pair<P, P> L;
typedef vector<P> Pol;

const double INF = 1e40;
const double EPS = 1e-8;
const double PI = acos(-1);

int sig(double r) {return (r < -EPS) ? -1 : (r > EPS) ? 1: 0;}
bool eq(double a, double b) {return abs(a - b) < EPS;}
bool near(P a, P b) {return abs(b - a) < EPS;}

ostream &operator<<(ostream &os, const L &a) {
  os << a.first << "-" << a.second;
  return os;
}

double sq(double a) {return a * a;}

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

// ツ禿?静?
double dot(P a, P b) {return a.X * b.X + a.Y * b.Y;}
// ツ外ツ静?
double cross(P a, P b) {return a.X * b.Y - a.Y * b.X;}

// ツ静シツ閉ェabツづ可妥篠つキツづゥツ点xツづ個暗環置
enum CCW{FRONT = 1, RIGHT = 2, BACK = 4, LEFT = 8, ON = 16};
int ccw(const P a, P b, P x) {
  b -= a;
  x -= a;
  double cr = cross(b, x);
  if (eq(cr, 0)) {
    if (sig(dot(b, x)) < 0) return BACK;
    if (sig(abs(b) - abs(x)) < 0) return FRONT;
    return ON;
  }
  return (cr > 0) ? LEFT : RIGHT;
}

// ツ静シツ閉ェツづ個ベツクツトツδ?
P vec(L a) {return a.second - a.first;}

// ツ角ツ度
double arg(P a, P b) {return acos(dot(a, b) / (abs(a) * abs(b)));}
P polar(double r, double theta) {return P(r * cos(theta), r * sin(theta));}
P rot(P p, double theta) { return p * polar(1, theta);}

// ツ有ツ古シツ角ツ度
double varg(P a, P b) {
  double ret = arg(a) - arg(b);
  if (ret < 0) ret += 2 * PI;
  if (ret > 2 * PI) ret -= 2 * PI;
  if (eq(ret, 2 * PI)) ret = 0;
  return ret;
}

// ツ偲仰影
P proj(P a, P b) {return a * dot(a, b) / sq(abs(a));}
P perp(L l, P p) {return l.first + proj(vec(l), p - l.first);}
P refl(L l, P p) {return perp(l, p) * 2. - p;}
 
// ツ古ーツ債キツ板サツ津ィ ツ端ツ点ツづーツ甘慊づ?
bool iLL(L a, L b) {return !eq(cross(vec(a), vec(b)), 0);}
bool eqL(L a, L b) {return !iLL(a, b) && eq(cross(vec(a), b.first - a.first), 0);}
bool iLS(L a, L b) {return sig(cross(vec(a), b.first)) * sig(cross(vec(a), b.second)) <= 0;}
bool iSS(L a, L b) {
  int cwaf = ccw(a.first, a.second, b.first);
  int cwbf = ccw(b.first, b.second, a.first);
  int cwas = ccw(a.first, a.second, b.second);
  int cwbs = ccw(b.first, b.second, a.second);
  if ((cwaf | cwas | cwbf | cwbs) & ON) return true;
  return ((cwaf | cwas) & (cwbf | cwbs)) == (LEFT | RIGHT);
}

// ツ古ーツ点
P pLL(L a, L b) {
  P va = vec(a);
  P vb = vec(b);
  return a.first + va * (cross(vb, b.first - a.first) / cross(vb, va));
}

// ツ仰猟猟」
double dLP(L l, P x) {return abs(cross(vec(l), x - l.first)) / abs(vec(l));}
double dSP(L s, P x) {
  if (dot(vec(s), x - s.first) <= 0) return abs(x - s.first);
  if (dot(-vec(s), x - s.second) <= 0) return abs(x - s.second);
  return dLP(s, x);
}
double dLL(L a, L b) {return iLL(a, b) ? 0 : dLP(a, b.first);}
double dLS(L a, L b) {return iLS(a, b) ? 0 : min(dLP(a, b.first), dLP(a, b.second));}
double dSS(L a, L b) {return iSS(a, b) ? 0 : min(min(dSP(a, b.first), dSP(a, b.second)), min(dSP(b, a.first), dSP(b, a.second)));}

// ツ板シツ陳シツ静シツ猟債づ敖づ個古ーツ債キツ板サツ津ィ
bool iLH(L a, L b) {return iLL(a, b) && ccw(b.first, b.second, pLL(a, b)) & (ON | FRONT);}
bool iHH(L a, L b) {return iLH(a, b) && iLH(b, a);}
bool iHS(L a, L b) {return iLS(a, b) && iLH(b, a);}

// ツ単ツ暗環ベツクツトツδ?
P uline(P a) {return a / abs(a);}
// ツ法ツ静シツベツクツトツδ?
P nml(P a) {return a * P(0, 1);}
P nmr(P a) {return a * P(0, -1);}
// ツ単ツ暗環法ツ静シツベツクツトツδ?
P unml(P a) {return uline(nml(a));}
P unmr(P a) {return uline(nmr(a));}

// ツ陳シツ行
bool orth(P a, P b) {return eq(dot(a, b), 0);}
// ツ閉スツ行
bool prll(P a, P b) {return eq(cross(a, b), 0);}
 
// ツ静シツ閉ェツ拡ツ陳」
L expandLine(L l, double mag) {
  L ret = l;
  P vf(vec(l));
  P vs(-vs);
  ret.first = l.second + mag * vf;
  ret.second = l.first + mag * vs;
  return ret;
}

// ツ円
struct C{
  P c;
  double r;
  C() {}
  C(P c, double r) : c(c), r(r) {}
};

// ツ陛篠角ツソツーツトツづ可用ツつ「ツづゥツ氾、ツ較ツ甘鳴青?
// TODO ツづヲツつュツづュツつゥツづァツづア
bool isRight(P base, P isv) {return eq(cross(base, isv), 0) ? abs(isv) < abs(base) : cross(base, isv) < 0;}
bool isLeft(P base, P isv) {return eq(cross(base,isv), 0) ? abs(isv) < abs(base) : cross(base,isv) > 0;}
// ツ角ツ度ツつェツ督卍つオツつ「ツ湘ェツ債?づ債渉?渉伉つェツ暗ェツ津ィツづ?づ債づ按つ「
bool cmpArg(P a, P b) {return ccw(P(0, 0), a, b) == RIGHT;}

// 2ツ円ツづ個暗環置ツ甘鳴係
enum RELATION{SAME = 1, CONTAIN = 2, OVER = 4, NO_CROSS = 8, ONE_CROSS = 16, ONE_INSIDE_CROSS = 32, TWO_CROSS = 64};
int cRel(C c1, C c2) {
  double d = abs(c1.c - c2.c);
  if (near(c1.c, c2.c) && eq(d, 0)) return SAME;
  if (sig(d - (c1.r - c2.r)) < 0) return OVER;
  if (sig(d - (c2.r - c1.r)) < 0) return CONTAIN;
  if (eq(d, c1.r - c2.r)) return ONE_INSIDE_CROSS;
  if (eq(d, c1.r + c2.r)) return ONE_CROSS;
  if (sig(d - (c1.r + c2.r)) > 0) return NO_CROSS;
  return TWO_CROSS;
}

// ツ点ツつェツ円ツづ可甘慊づ慊づェツづゥツつゥ
bool iCP(C c, P p) {return sig(abs(p - c.c) - c.r) <= 0;}
// ツ古ーツ債キツ板サツ津ィ
bool iCL(C c, L l) {return sig(c.r - dLP(l, c.c)) >= 0;}
bool iCLs(C c, L l) {return sig(c.r - dLP(l, c.c)) > 0;}
bool iCS(C c, L s) {return sig(c.r - dSP(s, c.c)) >= 0 && sig(c.r - max(abs(s.first - c.c), abs(s.second - c.c))) <= 0;}

// ツ古ーツ点
pair<P, P> pCC(C a, C b) {
  double d = abs(b.c - a.c);
  double x = (sq(d) + sq(a.r) - sq(b.r)) / (2 * d);
  P e = uline(b.c - a.c), w = nml(e) * sqrt(max(sq(a.r) - sq(x), 0.));
  return make_pair(a.c + e * x - w, a.c + e * x + w);
}
pair<P, P> pCL(C c, L l) {
  P h = perp(l, c.c);
  double d = abs(h - c.c);
  double y = sqrt(max(sq(c.r) - sq(d), 0.0));
  P e = uline(vec(l));
  return make_pair(h - e * y, h + e * y);
}

// ツ点ツつゥツづァツ円ツづ鳴づ個静堋静シ firstツつェp->c.cツづ可妥篠つオツづ?債カツ堕、
pair<P, P> tCP(C c, P p) {
  double d2 = sq(abs(p - c.c));
  double x = sqrt(max(d2 - sq(c.r), 0.));
  P h = c.c + (p - c.c) * (c.r * c.r / d2);
  P w = nml(p - c.c) * (x * c.r / d2);
  return make_pair(h - w, h + w);
}

// ツ禿アツ円ツづ個仰、ツ津環静堋静シ
vector<L> tCC(C c1, C c2) {
  vector<L> res;
  pair<P, P> pcross, pcross2;
  double d = abs(c2.c - c1.c);

  int rel = cRel(c1, c2);
  if (rel & (SAME | CONTAIN | OVER)) return res;
  
  //external
  pcross = pCC(C(c1.c, sqrt(sq(d) - sq(c2.r - c1.r) + sq(c1.r))), c2);
  pcross2 = pCC(C(c2.c, sqrt(sq(d) - sq(c2.r - c1.r) + sq(c2.r))), c1);
  res.push_back(L(pcross2.second, pcross.first));
  res.push_back(L(pcross2.first, pcross.second));
  if (rel == TWO_CROSS) return res;
  
  if (rel & (ONE_INSIDE_CROSS | ONE_CROSS)) {
    P p = pCC(c1, c2).first;
    res.push_back(L(p, p + unmr(p - c1.c)));
    return res;
  }
  
  //internal
  P In((c2.r * c1.c + c1.r * c2.c) / (c1.r + c2.r));
  pcross = pCC(C(In, sqrt(sq(abs(c1.c - In)) - (c1.r * c1.r))), c1);
  res.push_back(L(In, pcross.first));
  res.push_back(L(In, pcross.second));
  return res;
}

vector<C> vc;

int main() {
  int n;
  for (;;) {
    cin >> n;
    if (n == 0) break;
    vc.clear();
    rep (i, n) {
      double x, y, r, m;
      cin >> x >> y >> r >> m;
      vc.push_back(C(P(x, y), r));
      vc.push_back(C(P(x, y), r + m));
    }
    int res = 1;
    rep (i, 2 * n) rep (j, 2 * n) {
      vector<L> t = tCC(vc[i], vc[j]);
      rep (k, t.size()) {
	int r = 0;
	rep (l, n) {
	  if (!iCLs(vc[2 * l], t[k]) && iCL(vc[2 * l + 1], t[k])) ++r;
	}
	res = max(res, r);
      }
    }
    cout << res << endl;
  }
}

Measured memory_bytes: 996