#include<algorithm>
#include<complex>
#include<cstdio>
#include<iostream>
#include<queue>

using namespace std;

#define rep(i, n) for (int i = 0; i < int(n); ++i)
template<class T> T at(vector<T> v, int i) {return v[i % v.size()];}

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

typedef long double D;
typedef complex<D> P;
struct L{P a, b;};
typedef vector<P> Pol;

const D EPS = 1e-8;

// テヲツッツ氾ィツシツεゥツ鳴「テヲツ閉ー
int sig(D a, D b = 0) {return a < b - EPS ? -1 : a > b + EPS ? 1 : 0;}
bool near(P a, P b) {return !sig(norm(a - b));}
namespace std {
  bool operator<(P a, P b) {return sig(a.X, b.X) ? a.X < b.X : a.Y < b.Y;}
}

// テ・ツケツウテヲツ鳴ケテヲツ?ケ
D sr(D a) {return sqrt(max(a, (D)0));}

// テ・ツ、ツ姪ァツゥツ?
D det(P a, P b) {return a.X * b.Y - a.Y * b.X;}

// テァツキツ堙・ツ按?」ツ?ョテ」ツδ凖」ツつッテ」ツδ暗」ツδォ
P vec(L a) {return a.b - a.a;}

// ティツキツ敕ゥツ崢「
D dLP(L l, P p) {return abs(det(vec(l), p - l.a) / vec(l));}

// テ・ツ??
struct C{P c; D r;};

// 2テ・ツ??」ツ?ョテ、ツスツ催ァツスツョテゥツ鳴「テ、ツソツ?
enum RELATION{SAME = 1, CONTAIN = 2, OVER = 4, NO_CROSS = 8, ONE_CROSS = 16, ONE_CONTAIN_CROSS = 32, ONE_OVER_CROSS = 64, TWO_CROSS = 128};
int cRel(C c1, C c2) {
  D d = abs(c1.c - c2.c);
  if (near(c1.c, c2.c) && !sig(c1.r, c2.r)) return SAME;
  if (sig(d, c1.r - c2.r) < 0) return OVER;
  if (sig(d, c2.r - c1.r) < 0) return CONTAIN;
  if (!sig(d, c1.r - c2.r)) return ONE_OVER_CROSS;
  if (!sig(d, c2.r - c1.r)) return ONE_CONTAIN_CROSS;
  if (!sig(d, c1.r + c2.r)) return ONE_CROSS;
  if (sig(d, c1.r + c2.r) > 0) return NO_CROSS;
  return TWO_CROSS;
}

// テ、ツコツ、テァツつケ
pair<P, P> pCC(C a, C b) {
  D x = (norm(a.c - b.c) + a.r * a.r - b.r * b.r) / (2 * abs(a.c - b.c));
  P e = (b.c - a.c) / abs(b.c - a.c);
  P y = e * P(0, sr(a.r * a.r - x * x));
  return make_pair(a.c + e * x - y, a.c + e * x + y);
}

// テ、ツコツ古・ツ??」ツ?ョテ・ツ?アテゥツ?堙ヲツ篠・テァツキツ?
vector<L> tCC(C c1, C c2) {
  vector<L> res;
  pair<P, P> pcross1, pcross2;
  D d2 = norm(c2.c - c1.c);

  int rel = cRel(c1, c2);
  if (rel & (SAME | CONTAIN | OVER)) return res;
  
  if (rel & (ONE_CONTAIN_CROSS | ONE_OVER_CROSS | ONE_CROSS)) {
    P p = pCC(c1, c2).first;
    res.push_back((L){p, p + (p - c1.c) * P(0, 1)});
    if (rel & (ONE_CONTAIN_CROSS | ONE_OVER_CROSS)) return res;
  }

  //external
  pcross1 = pCC((C){c2.c, sqrt(d2 - (c2.r - c1.r) * (c2.r - c1.r) + c2.r * c2.r)}, c1);
  pcross2 = pCC((C){c1.c, sqrt(d2 - (c2.r - c1.r) * (c2.r - c1.r) + c1.r * c1.r)}, c2);
  res.push_back((L){pcross1.second, pcross2.first});
  res.push_back((L){pcross1.first, pcross2.second});
  if (rel & (TWO_CROSS | ONE_CROSS)) return res;

  //internal
  P In((c2.r * c1.c + c1.r * c2.c) / (c1.r + c2.r));
  pcross1 = pCC((C){In, sqrt(norm(c1.c - In) - c1.r * c1.r)}, c1);
  pcross2 = pCC((C){In, sqrt(norm(c2.c - In) - c2.r * c2.r)}, c2);
  res.push_back((L){pcross1.first, pcross2.first});
  res.push_back((L){pcross1.second, pcross2.second});
  return res;
}

int main() {
  while (true) {
    int n;
    cin >> n;
    if (n == 0) break;
    C c[2 * n];
    D m[n];
    rep (i, n) cin >> c[i].c.X >> c[i].c.Y >> c[i].r >> m[i];
    rep (i, n) {
      c[i + n] = c[i];
      c[i + n].r += m[i];
    }
    int res = 1;
    rep (i, 2 * n) rep (j, i) {
      vector<L> vl = tCC(c[i], c[j]);
      rep (ii, vl.size()) {
	int r = 0;
	rep (k, n) {
	  D d = dLP(vl[ii], c[k].c);
	  if (sig(c[k].r, d) <= 0 && sig(d, c[k].r + m[k]) <= 0) ++r;
	}
	res = max(res, r);
      }
    }
    cout << res << endl;
  }
  return 0;
}

Measured memory_bytes: 1272