#include<bits/stdc++.h>
#define rep(i,n) for (int i=0;i<n;i++)
#define ll long long

#define ALL(x) x.begin(),x.end()

using namespace std;
struct Node{
    int x,y,r,c,id;
    vector<int> top;
    vector<int> bottom;

};
map<vector<deque<pair<int,int>>>,bool> mp;
bool finish;

map<vector<int>,bool> used;



void show(vector<int> &v){
    rep(i,v.size()) cerr<<v[i]<<" ";
    cerr<<endl;
}

void vecdel(vector<int> &v,int n){
    auto itr = v.begin();
   for(; itr != v.end(); ++itr) {
        if (*itr==n) break;;
    }
    v.erase(itr);
}

bool ismount(Node n1,Node n2){
    double dist=sqrt((n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y));
    return dist<(double)(n1.r+n2.r);
}

bool has(vector<int> &v,int n){
    return find(ALL(v),n)!=v.end();
}


int dfs(vector<Node> &forest,vector<int> &leaf,int start){
    int ret=0;
    int rem=0;
    rep(i,forest.size())
    {
       if (!has(forest[i].top,-1)){
            rem++;
        }
    }
    if (rem<2){
       finish=true;
     //  cerr<<"fini"<<endl;
       return  2*(forest.size()/2);   
    }
    
    if (used[leaf]==true){
    //    cerr<<"skip"<<endl;
       return -1;
    }
      used[leaf]=true;
//    show(leaf);
    for (int i=0;i<leaf.size();i++){
        for (int j=i+1;j<leaf.size();j++){
            int a=leaf[i];
            int b=leaf[j];
            if (forest[a].c==forest[b].c){
                vector<int> nleaf;
                auto nforest=forest;
                //copy(leaf.begin(), leaf.end(), back_inserter(nleaf));
                //vecdel(nleaf,a);
                //vecdel(nleaf,b);
                for (auto k:forest[a].bottom)
                    vecdel(nforest[k].top,a);
                for (auto k:forest[b].bottom)
                    vecdel(nforest[k].top,b);
                nforest[a].top.push_back(-1);
                nforest[b].top.push_back(-1);
                rep(i,nforest.size()){
                    if (nforest[i].top.size()==0)
                        nleaf.push_back(i);
                }

                sort(ALL(nleaf));
                ret=max(ret,dfs(nforest,nleaf,i)+2);  
                if (finish){
                    //cerr<<"fin"<<endl;
                    return 2*(forest.size()/2);
                }
            }
        }
    }
    return ret;
}



int main(){
    
    while (true){
        finish=false;
        mp.clear();
        used.clear();
        int n;
        cin>>n;
        if (n==0)
            break;
        vector<Node> forest(n);
        int x,y,r,c;
        rep(i,n){
            cin>>x>>y>>r>>c;
            forest[i]={x,y,r,c,i,{},{}};
        }
        bool f=true;
        while(f){
            f=false;
            rep(i,n){
                for (int j=0;j<i;j++){
                    if (ismount(forest[i],forest[j]) && !has(forest[i].top,j)){
                        forest[i].top.push_back(j);
                        forest[j].bottom.push_back(i);
                        f=true;
                    }
                }
            }  
        }
        f=true;
        while(f){
            f=false;
            rep(i,n){
                for (int j=0;j<i;j++){
                    for (int k=0;k<j;k++){
                        if (has(forest[i].top,j) && has(forest[j].top,k) && has (forest[i].top,k)){
                            vecdel(forest[i].top,k);
                            vecdel(forest[k].bottom,i);
                            f=true;
                        }
                    }
                }
            }  
        }
        vector<int> leaf;
        rep(i,forest.size()){
            if (forest[i].top.size()==0){
                leaf.push_back(forest[i].id);
            }
        }
        //show(leaf);        
        cout<<dfs(forest,leaf,0)<<endl;
    }



    return 0;
}


Measured memory_bytes: 26164