#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>

using namespace std;
typedef long long ll;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

#include <complex>
#include <vector>

typedef complex<double> Point;
typedef vector<Point> Polygon;

//static const double EPS = 1e-8;
static const double INF = 1e+0;

#define CURR(P, i) (P[i])
#define NEXT(P, i) (P[(i + 1) % P.size()])

struct Line : public vector<Point> {
  Line() {;}
  Line(Point a, Point b) { push_back(a); push_back(b); }
};

struct Circle {
  Point p;
  double r;
  Circle() {;}
  Circle(Point p, double r) : p(p), r(r) {;}
};

namespace std {
  bool operator<(const Point &lhs, const Point &rhs) {
    return lhs.real() == rhs.real() ? lhs.imag() < rhs.imag() : lhs.real() < rhs.real();
  }
}

inline double cross(const Point &a, const Point &b) {
  return imag(conj(a) * b);
}

inline double dot(const Point &a, const Point &b) {
  return real(conj(a) * b);
}

inline int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0) { return 1; }
  if (cross(b, c) < 0) { return -1; }
  if (dot(b, c) < 0) { return 2; }
  if (norm(b) < norm(c)) { return -2; }
  return 0;
}


vector<Line> tangentCP(const Circle &c, const Point &p) {
  vector<Line> ret;
  Point vect = c.p - p;
  double d = abs(vect);
  double l = sqrt(norm(vect) - c.r * c.r);
  if (!(l == l)) { return ret; }
  Point v1 = vect * Point(l / d,  c.r / d);
  Point v2 = vect * Point(l / d, -c.r / d);
  ret.push_back(Line(p - v1 * INF, p + v1 * INF));
  if (l > EPS) {
    ret.push_back(Line(p - v2 * INF, p + v2 * INF));
  }
  return ret;
}

vector<Line> tangentCC(const Circle &c1, const Circle &c2) {
  vector<Line> ret;
  if (abs(c1.p - c2.p) - (c1.r + c2.r) > -EPS) {
    Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
    ret = tangentCP(c1, center);
  }
  if (fabs(c1.r - c2.r) > EPS) {
    Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
    vector<Line> nret = tangentCP(c1, out);
    ret.insert(ret.end(), nret.begin(), nret.end());
  } else {
    Point vect = c2.p - c1.p;
    vect /= abs(vect);
    Point q1 = c1.p + vect * Point(0, 1) * c1.r;
    Point q2 = c1.p + vect * Point(0, -1) * c1.r;
    ret.push_back(Line(q1 - vect * INF, q1 + vect * INF));
    ret.push_back(Line(q2 - vect * INF, q2 + vect * INF));
  }
  return ret;
}

Point projection(const Line &l, const Point &p) {
  double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}

double distanceLP(const Line &l, const Point &p) {
  return abs(p - projection(l, p));
}

Circle circle[2][100];

int main() {
  int n;
  while (scanf("%d", &n), n) {
    REP(i, n) {
      double x, y, r, m;
      scanf("%lf %lf %lf %lf", &x, &y, &r, &m);
      circle[0][i] = Circle(Point(x, y), r);
      circle[1][i] = Circle(Point(x, y), r + m);
    }
    int ans = 1;
    REP(i, n) {
      REP(j, n) {
        if (i == j) { continue; }
        REP(l, 2) {
          REP(r, 2) {
            vector<Line> tangent = tangentCC(circle[l][i], circle[r][j]);
            FORIT(it, tangent) {
              int sum = 0;
              REP(k, n) {
                double dist = distanceLP(*it, circle[0][k].p);
                if (dist - circle[0][k].r > -3 * EPS && circle[1][k].r - dist > -3 * EPS) {
                  sum++;
                } else {
                  assert(k != i && k != j);
                }
              }
              assert(sum >= 2);
              ans = max(ans, sum);
            }
          }
        }
      }
    }
    cout << ans << endl;
  }
}

Measured memory_bytes: 1012