#include <stdio.h>
#define DISK_NUM 24
#define COLOR_NUM 4

/* int 型をビット表示 (デバッグ用) */
/*
void showBit(int x){
	int i;
	for (i = 31; i >= 0; i--) printf("%d", (x>>i) & 1);
	printf("\n");
}
*/

/* 円盤 */
typedef struct Disk{
	int x, y, r, c;
	int u;  /* i 番目の円盤がこの円盤の上にあるか否かをビットの桁で表す */
} Disk;

/* 二つの円盤が重なっているかを返す */
int isCollide(Disk a, Disk b){
	if ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) < (a.r + b.r) * (a.r + b.r)) return 1;
	return 0;
}

int B[DISK_NUM];

int n;
Disk d[DISK_NUM];
int f;  /* 円盤が存在するかのフラグ */

int dp[1<<DISK_NUM];  /* f をキーとしたメモ化再帰 */
#define unknown -1

int search(){
	int max = 0, m, i, j;
	int list;

	if (dp[f] != unknown) return dp[f];

	/* 取ることのできる円盤の一覧を生成する */
	list = f;
	for (i = 0; i < n; i++) if ((list & B[i]) != 0 && (d[i].u & f) != 0) list ^= B[i];

	/* 全ての円盤の組み合わせを調べる */
	for (i = 1; i < n; i++){
		if ((list & B[i]) == 0) continue;

		f ^= B[i];  /* 取る */
		for (j = 0; j < i; j++){
			if ((list & B[j]) == 0) continue;

			/* 色が同じなら取り除ける */
			if (d[i].c == d[j].c){
				f ^= B[j];  /* 取る */
				m = 2 + search();
				if (m > max) max = m;
				f ^= B[j];  /* 戻す */
			}
		}
		f ^= B[i];  /* 戻す */
	}

	return dp[f] = max;
}

int main(void){
	int i, j;

	for (i = 0; i < DISK_NUM; i++) B[i] = 1 << i;

	while (scanf("%d", &n) == 1 && n > 0 && n <= DISK_NUM){
		/* 入力 */
		for (i = 0; i < n; i++){
			scanf("%d%d%d%d", &(d[i].x), &(d[i].y), &(d[i].r), &(d[i].c));
			/* 重なりの状態を調べる (番号が小さいほうが上) */
			d[i].u = 0;
			for (j = 0; j < i; j++){
				if (isCollide(d[i], d[j])){
					d[i].u |= B[j];  /* d[j] が d[i] の上にある */
				}
			}
		}

		/* 初期化 */
		f = 0;
		for (i = 0; i < n; i++) f |= B[i];
		for (i = 0; i < (1<<n); i++) dp[i] = unknown;

		printf("%d\n", search());
	}

    return 0;
}