#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:512000000")
using namespace std;
void solve(__attribute__((unused)) bool);
void precalc();
clock_t start;
int main() {
  start = clock();
  int t = 1;
  cout.sync_with_stdio(0);
  cin.tie(0);
  precalc();
  cout.precision(10);
  cout << fixed;
  int testNum = 1;
  while (t--) {
    solve(true);
  }
  cout.flush();
  return 0;
}
template <typename T>
T binpow(T q, T w, T mod) {
  if (!w) return 1 % mod;
  if (w & 1) return q * 1LL * binpow(q, w - 1, mod) % mod;
  return binpow(q * 1LL * q % mod, w / 2, mod);
}
template <typename T>
T gcd(T q, T w) {
  while (w) {
    q %= w;
    swap(q, w);
  }
  return q;
}
template <typename T>
T lcm(T q, T w) {
  return q / gcd(q, w) * w;
}
template <typename T>
void make_unique(vector<T>& a) {
  sort(a.begin(), a.end());
  a.erase(unique(a.begin(), a.end()), a.end());
}
template <typename T>
void relax_min(T& cur, T val) {
  cur = min(cur, val);
}
template <typename T>
void relax_max(T& cur, T val) {
  cur = max(cur, val);
}
void precalc() {}
map<int, int> val_index;
vector<int> values;
struct Dsu {
  vector<int> dsu;
  vector<int> color;
  vector<int> type;
  void add_val() {
    int new_id = dsu.size();
    dsu.push_back(new_id);
    color.push_back(0);
    type.push_back(0);
  }
  int find_set(int v) {
    if (dsu[v] == v) {
      return v;
    }
    int p = dsu[v];
    int res = find_set(dsu[v]);
    color[v] = type[v] ^ color[p];
    type[v] = color[res] ^ color[v];
    return dsu[v] = res;
  }
  bool merge(int q, int w, int edge_type) {
    int Q = q, W = w;
    q = find_set(q);
    w = find_set(w);
    if (q == w) {
      return false;
    }
    if ((color[Q] ^ color[W]) != edge_type) {
      type[w] = 1;
    } else {
      type[w] = 0;
    }
    dsu[w] = q;
    return true;
  }
};
const int L = 30;
void solve(__attribute__((unused)) bool read) {
  vector<Dsu> comps(L);
  int Q;
  if (read) {
    cin >> Q;
  } else {
    Q = 200000;
  }
  auto get_index = [&](int val) {
    if (val_index.count(val)) {
      return val_index[val];
    }
    val_index[val] = values.size();
    values.push_back(val);
    for (auto& dsu : comps) {
      dsu.add_val();
    }
    return val_index[val];
  };
  auto same_colors = [&](int i, int l, int r) {
    return comps[i].find_set(l) == comps[i].find_set(r) &&
           comps[i].color[l] == comps[i].color[r];
  };
  auto different_colors = [&](int i, int l, int r) {
    return comps[i].find_set(l) == comps[i].find_set(r) &&
           comps[i].color[l] != comps[i].color[r];
  };
  int last_ans = 0;
  while (Q--) {
    int t, l, r;
    if (read) {
      cin >> t >> l >> r;
    } else {
      t = rand() % 2 + 1;
      l = rand() % (1 << 30) + 1;
      r = rand() % (1 << 30) + 1;
    }
    l ^= last_ans;
    r ^= last_ans;
    if (l > r) {
      swap(l, r);
    }
    --l;
    l = get_index(l);
    r = get_index(r);
    if (t == 1) {
      int x;
      cin >> x;
      x ^= last_ans;
      bool need_process = true;
      for (int i = 0; i < L; ++i) {
        int bit = (bool)(x & (1 << i));
        if (bit == 0 && different_colors(i, l, r) ||
            bit == 1 && same_colors(i, l, r)) {
          need_process = false;
          break;
        }
      }
      if (!need_process) {
        continue;
      }
      for (int i = 0; i < L; ++i) {
        int bit = (bool)(x & (1 << i));
        comps[i].merge(l, r, bit);
      }
    } else {
      last_ans = 0;
      for (int i = 0; i < L; ++i) {
        if (comps[i].find_set(l) == comps[i].find_set(r)) {
          if (different_colors(i, l, r)) {
            last_ans ^= (1 << i);
          }
        } else {
          last_ans = -1;
          break;
        }
      }
      if (read) {
        cout << last_ans << "\n";
      }
      if (last_ans == -1) {
        last_ans = 1;
      }
    }
  }
}
