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

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
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>

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

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

#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); }
};

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;
}

bool intersectSS(const Line &s, const Line &t) {
  return ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
    ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0;
}

struct Koma {
  int index;
  Point p;
  Point q;
  Koma(int index, int x0, int y0, int x1, int y1) : index(index), p(x0, y0), q(x1, y1) {;}
  bool operator<(const Koma &rhs) const {
    if (p.real() != rhs.p.real()) { return p.real() < rhs.p.real(); }
    return p.imag() < rhs.p.imag();
  }
};

int n;
int order[100];
Line waku[100];

bool HitCheck(const Line &line) {
  REP(i, 2 * n) {
    if (intersectSS(line, waku[i])) { return true; }
  }
  return false;
}

bool Up(const Line &line, const Koma &koma) {
  if (line[0].real() <= koma.p.real() && koma.q.real() <= line[1].real() &&
      koma.q.imag() <= line[0].imag()) {
    return true;
  }
  return false;
}

void calc(int &index, set<Koma> komas) {
  if (komas.empty()) { return; }
  Koma koma = *komas.begin();
  order[koma.index] = index++;
  komas.erase(komas.begin());
  if (komas.empty()) { return; }
  Line line(Point(koma.p.real(), koma.q.imag()), Point(500, koma.q.imag()));
  while (HitCheck(line)) {
    line[1] = Point(line[1].real() - 1.0, line[1].imag());
  }
  //cout << line[0] << " " << line[1] << endl;
  set<Koma> upper;
  set<Koma> lower;
  FORIT(it, komas) {
    if (Up(line, *it)) { upper.insert(*it); }
    else { lower.insert(*it); }
  }
  calc(index, upper);
  calc(index, lower);
}

int main() {
  bool first = true;
  while (scanf("%d", &n), n) {
    if (!first) { puts(""); }
    first = false;
    set<Koma> komas;
    REP(i, n) {
      int x0, x1, y0, y1;
      scanf("%d %d %d %d", &x0, &y0, &x1, &y1);
      if (x1 < x0) { swap(x0, x1); }
      if (y1 < y0) { swap(y0, y1); }
      komas.insert(Koma(i, x0, y0, x1, y1));
      waku[2 * i + 0] = Line(Point(x0 + 0.5, y0 + 0.5), Point(x0 + 0.5, y1 - 0.5));
      waku[2 * i + 1] = Line(Point(x1 - 0.5, y0 + 0.5), Point(x1 - 0.5, y1 - 0.5));
    }
    int index = 1;
    calc(index, komas);
    REP(i, n) {
      printf("%d\n", order[i]);
    }
  }
}

Measured memory_bytes: 0