#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <typename T>
using PQ = priority_queue<T>;
template <typename T>
using GPQ = priority_queue<T, vector<T>, greater<T>>;
template <class L, class R>
ostream& operator<<(ostream& os, pair<L, R> p);
template <class L, class R>
ostream& operator<<(ostream& os, map<L, R> v) {
  os << "[";
  for (auto vv : v) os << vv << ",";
  return os << "]";
}
template <class T>
ostream& operator<<(ostream& os, vector<T> v) {
  os << "[";
  for (auto vv : v) os << vv << ",";
  return os << "]";
}
template <class T>
ostream& operator<<(ostream& os, set<T> v) {
  os << "[";
  for (auto vv : v) os << vv << ",";
  return os << "]";
}
template <class L, class R>
ostream& operator<<(ostream& os, pair<L, R> p) {
  return os << "(" << p.first << "," << p.second << ")";
}
template <typename T>
inline T sq(T a) {
  return a * a;
}
template <typename T>
T gcd(T a, T b) {
  if (a < b) return gcd(b, a);
  return b == 0 ? a : gcd(b, a % b);
}
template <typename T, typename U>
T mypow(T b, U n) {
  if (n == 0) return 1;
  if (n == 1) return b;
  if (n % 2 == 0) {
    return mypow(b * b, n / 2);
  } else {
    return mypow(b, n - 1) * b;
  }
}
ll pcnt(ll b) { return __builtin_popcountll(b); }
template <typename T>
T iceil(T n, T d) {
  return (n + d - 1) / d;
}
class UnionFind {
 public:
  set<int> node;
  map<int, int> par, diff, num;
  int find(int x) {
    if (!node.count(x)) return -1;
    if (par[x] == x) {
      return x;
    } else {
      int p = find(par[x]);
      diff[x] ^= diff[par[x]];
      return par[x] = p;
    }
  }
  void create(int v) {
    node.insert(v);
    par[v] = v;
    diff[v] = 0;
    num[v] = 1;
  }
  void unite(int x, int y, int w) {
    if (!node.count(x)) create(x);
    if (!node.count(y)) create(y);
    int px = find(x), py = find(y);
    if (px == py) return;
    w ^= diff[x] ^ diff[y];
    if (num[px] < num[py]) swap(px, py);
    num[px] += num[py];
    diff[py] = w;
    par[py] = px;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  bool ispar(int x) { return x == find(x); }
  int size(int x) { return num[find(x)]; }
  int weight(int x, int y) {
    if (!node.count(x) || !node.count(y) || !same(x, y)) return -1;
    return diff[x] ^ diff[y];
  }
};
int main() {
  int last = 0;
  UnionFind uf;
  int Q;
  cin >> Q;
  for (int q = 0; q < Q; ++q) {
    int t;
    cin >> t;
    if (t == 1) {
      int x, y, w;
      cin >> x >> y >> w;
      x ^= last, y ^= last, w ^= last;
      if (x > y) swap(x, y);
      uf.unite(x, ++y, w);
    } else {
      int x, y;
      cin >> x >> y;
      x ^= last, y ^= last;
      if (x > y) swap(x, y);
      last = uf.weight(x, ++y);
      cout << last << endl;
      if (last < 0) last = 1;
    }
  }
  return 0;
}
