#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <cstdlib>
#include <bitset>
#include <tuple>
#include <assert.h>
#include <deque>
#include <bitset>
#include <iomanip>
#include <limits>
#include <chrono>
#include <random>
#include <array>
#include <unordered_map>
#include <functional>
#include <complex>
#include <numeric>
#include <cctype>

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
//constexpr long long MAX = 5100000;
constexpr long long INF = 1LL << 60;
constexpr int inf = 1000000007;
constexpr long long mod = 1000000007LL;
//constexpr long long mod = 998244353LL;
const long double PI = acos((long double)(-1));

using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;

class UnionFind {
public:
	vector<int> Parent;
	UnionFind(int N) {
		Parent = vector<int>(N, -1);
	}
	int root(int A) {
		if (Parent[A] < 0) {
			return A;
		}
		return Parent[A] = root(Parent[A]);
	}

	long long size(int A) {
		return -(long long)Parent[root(A)];
	}

	bool connect(int A, int B) {
		A = root(A);
		B = root(B);
		if (A == B) {
			return false;
		}
		if (size(A) < size(B)) {
			swap(A, B);
		}

		Parent[A] += Parent[B];
		Parent[B] = A;

		return true;
	}

};

template<typename T>
struct Compress {
	vector<T> v;
	Compress() {}
	Compress(vector<T> _v) :v(_v) {
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()), v.end());
	}

	void build(vector<T> _v) {
		v = _v;
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()), v.end());
	}
	int get(T x) {
		if (!binary_search(v.begin(), v.end(), x)) assert(false);
		return lower_bound(v.begin(), v.end(), x) - v.begin();
	}

	T& operator[](int i) { return v[i]; }


	int size() {
		return (int)v.size();
	}
};

int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };

int cnt;
void solve() {
	cnt++;
	using P = pair<int, int>;
	int n; cin >> n; if (n == 0) exit(0);
	vector<vector<int>> x(2, vector<int>(n)), y(2, vector<int>(n));
	vector<char> c(n);
	Compress<P> comp;
	vector<P> v;
	for (int i = 0; i < n; i++) {
		cin >> x[0][i] >> y[0][i] >> c[i];
		v.emplace_back(x[0][i], y[0][i]);
		if (c[i] == 'x') {
			x[1][i] = x[0][i] + 1;
			y[1][i] = y[0][i];
			v.emplace_back(x[1][i], y[1][i]);
		}
		else {
			x[1][i] = x[0][i];
			y[1][i] = y[0][i] + 1;
			v.emplace_back(x[1][i], y[1][i]);
		}
	}
	comp.build(v);
	int sz = comp.size();
	UnionFind uni(sz * 2);
	set<P> st;
	for (int i = 0; i < n; i++) {
		P s = { x[0][i],y[0][i] };
		P t = { x[1][i],y[1][i] };
		int si = comp.get(s);
		int ti = comp.get(t);
		uni.connect(si, ti + sz);
		uni.connect(si + sz, ti);
		for (int i = 0; i < 4; i++) {
			int nx = s.first + dx[i];
			int ny = s.second + dy[i];
			if (st.count({ nx,ny })) {
				int idx = comp.get({ nx,ny });
				uni.connect(si, idx);
				uni.connect(si + sz, idx + sz);
			}
		}
		for (int i = 0; i < 4; i++) {
			int nx = t.first + dx[i];
			int ny = t.second + dy[i];
			if (st.count({ nx,ny })) {
				int idx = comp.get({ nx,ny });
				uni.connect(ti, idx);
				uni.connect(ti + sz, idx + sz);
			}
		}
		st.emplace(s);
		st.emplace(t);
	}
	for (int i = 0; i < n; i++) {
		P s = { x[0][i],y[0][i] };
		P t = { x[1][i],y[1][i] };
		int si = comp.get(s);
		int ti = comp.get(t);
		if (uni.root(si) == uni.root(si + sz)) {
			cout << "No" << "\n";
			return;
		}
		if (uni.root(ti) == uni.root(ti + sz)) {
			cout << "No" << "\n";
			return;
		}
	}
	cout << "Yes" << "\n";
}

int main()
{

	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int kkt = 89;
	while (kkt) solve();
	
}



Measured memory_bytes: 5940