#include <bits/stdc++.h>
#include "testlib.h"

using namespace std;

typedef unsigned long long ull;
typedef unsigned int uint;

int MAX = 1'000'000'000;
int P = 31;

int LIM = 30'000;

int queries = 0;

bool color(int x, int y, uint seed, vector<uint> & mult) {
	x += MAX;
	y += MAX;
	for (int i = 0; i < P; ++i) {
		seed ^= ((x >> i) & 1) * mult[i];
		seed ^= ((y >> i) & 1) * mult[i + P];
	}
	mt19937 generator(seed);
	uniform_int_distribution<int> distribution(0, 1);
	for (int i = 0; i < 4; ++i) {
	    distribution(generator);
	}
	return distribution(generator);
	// return rnd.next(0, 1);
}

void random_tester(uint seed, vector<uint> &  mult) {
	int BOX = 100;
	vector<vector<int>> c(2, vector<int>(2));
	for (int i = 0; i < BOX; ++i) {
		for (int j = 0; j < BOX; ++j) {
			++c[color(i, j, seed, mult)][color(i, j + 1, seed, mult)];
			// cout << color(i, j, seed, mult);
		}
	}
	cout << "\n";
	cout << c[0][0] / (1. * BOX * BOX) << " " << c[0][1] / (1. * BOX * BOX) << " " << c[1][0] / (1. * BOX * BOX) << " " << c[1][1] / (1. * BOX * BOX) << "\n";
	for (int i = -10; i < 10; ++i) {
		for (int j = -10; j < 10; ++j) {
			cout << color(i, j, seed, mult);
		}
		cout << "\n";
	}
	cout << "\n";
	for (int i = -10; i < 10; ++i) {
		for (int j = -10; j < 10; ++j) {
			cout << color(i, j, seed, mult);
		}
		cout << "\n";
	}
	cout << "\n";
}

struct DSU {
	vector<int> p;
	vector<int> sz;

	DSU() : p({}), sz({}) {}

	DSU(int n) {
		p.assign(n, 0);
		for (int i = 0; i < n; ++i) {
			p[i] = i;
		}
		sz.assign(n, 1);
	}

	int get(int x) {
		if (p[x] == x) {
			return x;
		}
		return p[x] = get(p[x]);
	}

	bool unite(int a, int b) {
		a = get(a);
		b = get(b);
		if (a == b) {
			return false;
		}
		if (sz[a] < sz[b]) {
			swap(a, b);
		}
		sz[a] += sz[b];
		p[b] = a;
		return true;
	}
};

vector<int> dx = {-1, 0, 1, -1, 1, -1, 0, 1};
vector<int> dy = {-1, -1, -1, 0, 0, 1, 1, 1};

void interactor(int n, uint seed, vector<uint> &  mult) {
	int type = -1;
	while (true) {
		string s = ouf.readToken("?|!");
		tout << s << " ";
        if (s == "?") {
            queries++;
            if (queries > LIM) {
				cout << "0" << endl;
				tout << "0" << endl;
                quitf(_wa, "Queries limit exceeded.");
            }
			int x = ouf.readInt(-MAX, MAX);
			int y = ouf.readInt(-MAX, MAX);
			tout << x << " " << y << "\n";
			string c = (color(x, y, seed, mult) ? "W" : "B");
			cout << c << endl;
			tout << c << "\n";
        } else {
            string s = ouf.readToken("W|B");
			tout << s;
			type = (s == "W" ? 1 : 0);
            break;
        }
	}
	map<pair<int, int>, int> mp;
	DSU dsu(n);
	for (int i = 0; i < n; ++i) {
		int x = ouf.readInt(-MAX, MAX);
		int y = ouf.readInt(-MAX, MAX);
		tout << " " << x << " " << y;
		if (color(x, y, seed, mult) != type) {
			quitf(_wa, "Cell (%d, %d) has different color", x, y);
		}
		pair<int, int> cur = {x, y};
		if (mp.find(cur) != mp.end()) {
			quitf(_wa, "Cell (%d, %d) is duplicated", x, y);
		}
		mp[cur] = i;
		for (int k = 0; k < 8; ++k) {
			int x1 = x + dx[k];
			int y1 = y + dy[k];
			if (mp.find({x1, y1}) != mp.end()) {
				dsu.unite(i, mp[{x1, y1}]);
			}
		}
	}
	tout << endl;
	for (int i = 0; i < n; ++i) {
		if (dsu.get(i) != dsu.get(0)) {
			quitf(_wa, "The region is disconected");
		}
	}
}

int main(int argc, char** argv) {
    registerInteraction(argc, argv);
	int t = inf.readInt();
	int n = inf.readInt();
	long long seed0 = inf.readLong();

	rnd.setSeed(seed0);
    
	cout << t << " " << n << endl;
	tout << t << " " << n << endl;

	vector<uint> seed(t);
	vector<vector<uint>> mult(t, vector<uint>(2 * P));
	for (int i = 0; i < t; ++i) {
		seed[i] = rnd.next(1ull << P);
		for (int j = 0; j < 2 * P; ++j) {
			mult[i][j] = rnd.next(1ull << P);
		}
	}
	for (int i = 0; i < t; ++i) {
		setTestCase(i + 1);
		interactor(n, seed[i], mult[i]);
	}
	tout << queries << endl;
	quitf(_ok,"OK, %d queries", queries);
}