#include <bits/stdc++.h>
using namespace std;
int cnt = 0;
int X[400003];
map<int, int> mp[400003];
map<int, int> parent;
int query(int l, int r) {
  if (!parent.count(l - 1) || !parent.count(r))
    return -1;
  else if (parent[l - 1] != parent[r])
    return -1;
  else
    return mp[parent[r]][r] ^ mp[parent[l - 1]][l - 1];
}
void update(int l, int r, int c) {
  int num = query(l, r);
  if (num != -1) return;
  l--;
  if (!parent.count(l)) parent[l] = ++cnt, mp[cnt][l] = 0;
  if (!parent.count(r)) parent[r] = ++cnt, mp[cnt][r] = 0;
  int parl = parent[l];
  int parr = parent[r];
  if (mp[parl].size() <= mp[parr].size()) swap(parl, parr), swap(l, r);
  for (auto it = mp[parr].begin(); it != mp[parr].end(); ++it)
    it->second ^= X[parr];
  X[parr] = 0;
  int l0 = (*mp[parl].begin()).first;
  int r0 = (*mp[parr].begin()).first;
  int pl = mp[parl][l];
  int qr = mp[parr][r];
  if (l0 < r0) {
    int rr = (pl ^ X[parl]) ^ c;
    for (auto it : mp[parr]) {
      int i = it.first;
      int qi = it.second;
      int ri = rr ^ qi ^ qr;
      mp[parl][i] = ri ^ X[parl];
      parent[i] = parl;
    }
    mp[parr].clear();
  } else {
    int z = (pl ^ X[parl]) ^ qr ^ c;
    for (auto it : mp[parr]) {
      int i = it.first;
      int qi = it.second;
      mp[parl][i] = qi ^ X[parl] ^ z;
      parent[i] = parl;
    }
    X[parl] ^= z;
    mp[parr].clear();
  }
}
int main() {
  int q;
  scanf("%d", &q);
  int ans = 0;
  while (q--) {
    int t;
    scanf("%d", &t);
    int l, r;
    scanf("%d %d", &l, &r);
    l ^= ans;
    r ^= ans;
    if (l > r) swap(l, r);
    if (t == 1) {
      int x;
      scanf("%d", &x);
      x ^= ans;
      update(l, r, x);
    } else {
      ans = query(l, r);
      printf("%d\n", ans);
      ans = abs(ans);
    }
  }
}
