#include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int long long
using ld = long double;

#define all(v) (v).begin(), (v).end()
#define db(x) cerr << #x << " = " << x << '\n'
#define mp make_pair
#define eb emplace_back
#define pb push_back
#define sz(v) (int)((v).size())
#define pw(x) (1LL << (int)(x))
#define fr(i, a, b) for (int i = (a); i <= (b); ++i)
#define rf(i, a, b) for (int i = (a); i >= (b); --i)
#define fe(x, y) for (auto &x: y)
#define fi first
#define se second

mt19937_64 rng(566);

ll rnd(ll l, ll r) {
    return rng() % (r - l + 1) + l;
}

template<typename T>
bool umn(T &a, T b) {
    return a > b ? a = b, 1 : 0;
}

template<typename T>
bool umx(T &a, T b) {
    return a < b ? a = b, 1 : 0;
}

template<typename T>
using ve = vector<T>;

using pii = pair<int, int>;
using pll = pair<ll, ll>;

const double eps = 1e-8;
const ll mod = 1e9 + 8;
const int inf0 = 1e9 + 10;
const ll inf = 2e18 + 10;

void solve();

signed main() {
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

int QUOTA = 30'000;


ll encode(int x, int y) {
    return (x + 1'000'005LL) * 2'000'005LL + (y + 1'000'005LL);
}

char ask(int x, int y) {
    assert(QUOTA > 0);
    QUOTA--;
    cout << "? " << x << ' ' << y << endl;
    char c;
    cin >> c;
    // if (rnd(0, 1) == 0) {
        // c = 'W';
    // } else {
        // c = 'B';
    // }
    // cout << c << endl;
    return c;
}

int tests_completed = 0;

int n;

bool assert_connected(const vector<pii> &points) {
    unordered_map<ll, int> toids;
    for (int i = 0; i < sz(points); ++i) {
        toids[encode(points[i].fi, points[i].se)] = i;
    }
    ve<int> dsu(sz(points)), rang(sz(points));
    for (int i = 0; i < sz(points); ++i) {
        dsu[i] = i;
        rang[i] = 0;
    }
    std::function<int(int)> gett = [&](int v) -> int {
        if (dsu[v] == v) return v;
        return dsu[v] = gett(dsu[v]);
    };
    std::function<void(int, int)> unitte = [&](int a, int b) {
        a = gett(a);
        b = gett(b);
        if (a == b) return;
        if (rang[a] < rang[b]) {
            swap(a, b);
        }
        dsu[b] = a;
        if (rang[a] == rang[b]) {
            rang[a]++;
        }
    };
    for (int i = 0; i < n; ++i) {
        for (int dx = -1; dx <= 1; ++dx) {
            for (int dy = -1; dy <= 1; ++dy) {
                ll nxny = encode(points[i].fi + dx, points[i].se + dy);
                if (toids.contains(nxny)) {
                    unitte(i, toids[nxny]);
                }
            }
        }
    }
    for (int i = 0; i < n - 1; ++i) {
        if (gett(i) != gett(i + 1)) return false;
    }
    return true;
}

void answer(const vector<pii> &points, char color) {
    assert(sz(points) == n);
    assert(assert_connected(points));
    // return;
    cout << "! " << color;
    for (auto pt : points) {
        cout << ' ' << pt.first << ' ' << pt.second;
    }
    cout << endl;
    // cerr << "COMPLETED: " << ++tests_completed << endl;
}


void one_case() {
    vector<pii> whites, blacks;
    unordered_map<ll, char> mapp;
    char c = ask(0, 0);
    mapp[encode(0, 0)] = c;
    whites.eb(0, 0);
    int i = 0;
    while (ask(0, ++i) == c) {
        whites.eb(0, i);
        mapp[encode(0, i)] = c;
        if (sz(whites) == n) break;
    }
    if (sz(whites) == n) {
        answer(whites, mapp[encode(whites[0].fi, whites[0].se)]);
        return;
    }
    blacks.eb(0, i);
    mapp[encode(0, i)] = 'B' + 'W' - c;
    if (c == 'B') swap(whites, blacks);
    queue<pair<int, int>> cands;
    auto bi_connected = [&](int x, int y) {
        if (mapp.contains(encode(x, y))) return false;
        bool white = false, black = false;
        for (int dx = -1; dx <= 1; ++dx) {
            for (int dy = -1; dy <= 1; ++dy) {
                if (mapp.contains(encode(x + dx, y + dy))) {
                    if (mapp[encode(x + dx, y + dy)] == 'B') {
                        black = true;
                    } else {
                        white = true;
                    }
                }
            }
        }
        return white && black;
    };
    auto update_near = [&](int x, int y) {
        for (int dx = -1; dx <= 1; ++dx) {
            for (int dy = -1; dy <= 1; ++dy) {
                if (bi_connected(x + dx, y + dy)) {
                    cands.push(mp(x + dx, y + dy));
                }
            }
        }
    };
    std::function<void(char)> emergency = [&](char c) {
        // for (int x = -10; x <= 10; ++x) {
        //     for (int y = -10; y <= 10; ++y) {
        //         if (mapp.contains(encode(x, y))) {
        //             cout << mapp[encode(x, y)];
        //         } else {
        //             cout << '.';
        //         }
        //     }
        //     cout << '\n';
        // }
        // cout << c << '\n';
        // if (c == 'B') {
        //     swap(whites, blacks);
        // }
        int index = 0;
        while (sz(whites) < n) {
            if (index >= sz(whites)) {
                // for (int x = -10; x <= 10; ++x) {
                //     for (int y = -10; y <= 10; ++y) {
                //         if (mapp.contains(encode(x, y))) {
                //             cout << mapp[encode(x, y)];
                //         } else {
                //             cout << '.';
                //         }
                //     }
                //     cout << '\n';
                // }
                // exit(-2);
                swap(whites, blacks);
                blacks.clear();
                emergency('B' + 'W' - c);
                return;
            }
            for (int dx = -1; dx <= 1; ++dx) {
                for (int dy = -1; dy <= 1; ++dy) {
                    int nx = whites[index].fi + dx, ny = whites[index].se + dy;
                    // cout << "Check " << nx << ' ' << ny << endl;
                    if (mapp.contains(encode(nx, ny))) continue;
                    char cc = ask(nx, ny);
                    if (cc == c) {
                        whites.eb(mp(nx, ny));
                    } else {
                        blacks.eb(mp(nx, ny));
                    }
                    mapp[encode(nx, ny)] = cc;
                    if (sz(whites) == n) break;
                }
                if (sz(whites) == n) break;
            }
            index++;
        }
        answer(whites, mapp[encode(whites[0].fi, whites[0].se)]);
    };
    update_near(0, i);
    while (sz(whites) < n && sz(blacks) < n) {
        if (cands.empty()) {
            if (sz(whites) > sz(blacks)) {
                blacks.clear();
                emergency('W');
            } else {
                swap(whites, blacks);
                blacks.clear();
                emergency('B');
            }
            return;
        }
        while (!cands.empty() && mapp.contains(encode(cands.front().fi, cands.front().se))) {
            cands.pop();
        }
        if (cands.empty()) {
            if (sz(whites) > sz(blacks)) {
                blacks.clear();
                emergency('W');
            } else {
                swap(whites, blacks);
                blacks.clear();
                emergency('B');
            }
            return;
        }
        auto [x, y] = cands.front();
        char c = ask(x, y);
        cands.pop();
        if (c == 'W') {
            whites.eb(x, y);
        } else {
            blacks.eb(x, y);
        }
        mapp[encode(x, y)] = c;
        update_near(x, y);
    }
    if (sz(whites) == n) {
        answer(whites, mapp[encode(whites[0].fi, whites[0].se)]);
    } else {
        answer(blacks, mapp[encode(blacks[0].fi, blacks[0].se)]);
    }
}

void stress() {
    int t = 50;
    n = 300;
    while (t--) {
        one_case();
    }
    cerr << QUOTA << endl;
    QUOTA = 30'000;
}

void solve() {
    // for (int i = 0; i < 1000; ++i) {
    //     stress();
    // }
    int t;
    cin >> t >> n;
    while (t--) {
        one_case();
    }
}