//include
//------------------------------------------
#include <vector>
#include <list>
#include <map>
#include <climits>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <queue>
#include <random>
#include <cctype>
#include <complex>

using namespace std;


/*
 *
 *
 *   ~~~~Below My Answer~~~~
 *
 *
 **/

#define REP(i, a, b) for(int i=(a);i<(b);++i)
#define RFOR(i, a, b) for(int i=(b)-1;i>=(a);--i)
#define rep(i, n)  REP(i,0,n)
#define RREP(i, n) for(int i = n-1;i >= 0;i--)
#define FORLL(i, a, b) for(LL i=LL(a);i<LL(b);++i)
#define RFORLL(i, a, b) for(LL i=LL(b)-1;i>=LL(a);--i)
#define REPLL(i, n) for(LL i=0;i<LL(n);++i)
#define RREPLL(i, n) for(LL i=LL(n)-1;i>=0;--i)
#define FOREACH(x, v) for(auto &(x) : (v))
#define FORITER(x, v) for(auto (x) = (v).begin(); (x) != (v).end(); ++(x))

//
//int n; //枚数
//int x[25],y[25],r[25],c[25]; //円盤
//int b[25]; //各円盤の上に重なっている円盤（ビット管理）
//
////円盤iと円盤jが重なっているかの判定
//bool intersects(int i,int j){
//    int dist1 = pow(x[i]-x[j],2) + pow(y[i]-y[j],2);
//    int dist2 = pow(r[i]+r[j],2);
//
//    return dist2 > dist1;
//}
//
////DP用
//char dp[1<<24];
//
//int main(void){
//    while(scanf("%d",&n),n){
//        rep(i,n){
//            scanf("%d%d%d%d",&x[i],&y[i],&r[i],&c[i]);
//
//            //円盤iの上に重なっている円盤を全て探す
//            b[i] = 0;
//            rep(j,i) if(intersects(i,j)) b[i] |= (1<<j);
//        }
//
//        int ans = 0;
//        int to = (1<<n);
//        memset(dp,-1,sizeof(dp));
//        dp[0] = 0;
//
//        rep(i,to){
//            if(dp[i] == -1) continue;
//
//            ans = max(ans,(int)dp[i]);
//
//            //消せる円盤のペア(j,k)を探す
//            rep(j,n-1){
//                //すでに円盤jは消えている or 円盤jの上の円盤が邪魔して消せない
//                if((i & (1<<j)) != 0 || (i & b[j]) != b[j]) continue;
//
//                REP(k,j+1,n){
//                    //jとkの色が違う or すでに円盤kは消えている or 円盤kの上の円盤が邪魔
//                    if(c[j] != c[k] || (i & (1<<k)) != 0 || (i & b[k]) != b[k]) continue;
//
//                    int next = i | (1<<j) | (1<<k); //next = 円盤jとkを消した状態(ビット管理)
//                    dp[next] = max((int)dp[next],dp[i]+2);
//                }
//            }
//        }
//
//        printf("%d\n",ans);
//    }
//}



//重なってればTrueを返す
bool intersects(int i, int j, vector<int> &x, vector<int> &y, vector<int> &r) {
    int dist1 = pow(x[i] - x[j], 2) + pow(y[i] - y[j], 2);
    int dist2 = pow(r[i] + r[j], 2);
    return dist2 > dist1;
}

int main() {

    while (true) {
        int N;
        cin >> N;

        if (N == 0) break;

        vector<int> x(N), y(N), r(N), c(N);
        vector<int> b(N);
        for (int i = 0; i < N; ++i) {
            cin >> x[i] >> y[i] >> r[i] >> c[i];

            //i番目の円に重なっている円盤jがあれば右からj番目を1にする
            //1なら重なっている
            b[i] = 0;
            for (int j = 0; j < i; j++) {
                if (intersects(i, j, x, y, r)) {
                    b[i] |= (1 << j);
                }
            }
        }

        //2^Nの状態を管理する
        //dp[i]のNビットの右からi番目が1なら円盤iは既に使用されている
        vector<int> dp(1 << N, -1);

        int ans = 0;
        int to = (1 << N);
        dp[0] = 0;

        //すべての状態を全て試す
        for (int i = 0; i < to; i++) {
            //状態iにたどり着けないなら
            if (dp[i] == -1) continue;

            //状態iにおける消した数を確定する
            ans = max(ans, dp[i]);

            //円盤のペア(j, k)を探す
            //jの方が、z軸で上にくる
            //kの方が、z軸で下に来る
            for (int j = 0; j < N - 1; j++) {
                //円盤jが使われている
                //円盤jと重なるものが全て使われてなくなっているか
                if ((i & (1 << j)) != 0 || (i & b[j]) != b[j]) continue;


                //円盤kを探す
                for (int k = j + 1; k < N; k++) {

                    //色が異なっている
                    //円盤kが既に使われている
                    //円盤kと重なるものは全て使用されてなくなっているか
                    if (c[j] != c[k] || (i & (1 << k)) != 0 || (i & b[k]) != b[k]) continue;

                    //円盤jと円盤kを使う
                    int next = i | (1 << j) | (1 << k);
                    dp[next] = max(dp[next], dp[i] + 2);

                }

            }

        }

        cout << ans << endl;

    }

    return 0;
}






















































Measured memory_bytes: 68428