#include <bits/stdc++.h>
using namespace std;
#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repl(i,0,n)
#define mp(a,b) make_pair((a),(b))
#define pb(a) push_back((a))
#define all(x) (x).begin(),(x).end()
#define uniq(x) sort(all(x)),(x).erase(unique(all(x)),end(x))
#define fi first
#define se second
#define dbg(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
void _dbg(string){cout<<endl;}
template<class H,class... T> void _dbg(string s,H h,T... t){int l=s.find(',');cout<<s.substr(0,l)<<" = "<<h<<", ";_dbg(s.substr(l+1),t...);}
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

#define INF 1120000000

class UnionFind {
public:
  vector<int> par, rank; // parent(negative := its root and abs-value is its size), depth
  UnionFind(int sz) : par(sz, -1), rank(sz, 0){}
  int find(int x){
    if(par[x]<0) return x;
    else return par[x] = find(par[x]);
  }
  void unite(int x, int y){
    x=find(x); y=find(y);
    if(x==y) return;  // already belong to same tree
    if(rank[x] < rank[y]){  // y becomes parent node
      par[y] += par[x];
      par[x] = y;
    } else {  // x becomes parent node
      par[x] += par[y];
      par[y] = x;
      if(rank[x]==rank[y]) rank[x]++;
    }
  }
  bool same(int x, int y){ return find(x) == find(y); }
  int size(int x){ return -par[find(x)]; }
};

bool solve(int n){
  vector<int> x(n),y(n);
  vector<char> dir(n);
  map<pair<int,int>,int> number;
  int cnt=0;
  auto add = [&](int xx, int yy){
    if(number.count(mp(xx,yy))==0) number[mp(xx,yy)] = cnt++;
  };
  rep(i,n){
    char s[5];
    scanf("%d %d %s", &x[i], &y[i], s);
    dir[i] = s[0];
    add(x[i],y[i]);
    if(dir[i]=='x') add(x[i]+1, y[i]);
    else add(x[i],y[i]+1);
  }

  UnionFind uf(2*cnt);

  auto same = [&](int x1, int y1, int x2, int y2){
    if(number.count(mp(x1,y1))==0 || number.count(mp(x2,y2))==0) return true;
    int n1 = number[mp(x1,y1)], n2 = number[mp(x2,y2)];
    uf.unite(n1,n2); uf.unite(n1+cnt, n2+cnt);
    if(uf.same(n1, n2+cnt) || uf.same(n1+cnt, n2)) return false;
    return true;
  };
  auto diff = [&](int x1, int y1, int x2, int y2){
    if(number.count(mp(x1,y1))==0 || number.count(mp(x2,y2))==0) return true;
    int n1 = number[mp(x1,y1)], n2 = number[mp(x2,y2)];
    uf.unite(n1, n2+cnt); uf.unite(n1+cnt, n2);
    if(uf.same(n1, n2) || uf.same(n1+cnt, n2+cnt)) return false;
    return true;
  };

  rep(i,n){
    if(dir[i]=='x'){
      if(!same(x[i],y[i], x[i]-1,y[i]) ||
         !same(x[i],y[i], x[i],y[i]+1) ||
         !same(x[i],y[i], x[i],y[i]-1) ||
         !same(x[i]+1,y[i], x[i]+2,y[i]) ||
         !same(x[i]+1,y[i], x[i]+1,y[i]+1) ||
         !same(x[i]+1,y[i], x[i]+1,y[i]-1) ||
         !diff(x[i],y[i], x[i]+1,y[i]) ) return false;
    }
    else {
      if(!same(x[i],y[i], x[i]-1,y[i]) ||
         !same(x[i],y[i], x[i]+1,y[i]) ||
         !same(x[i],y[i], x[i],y[i]-1) ||
         !same(x[i],y[i]+1, x[i]+1,y[i]+1) ||
         !same(x[i],y[i]+1, x[i]-1,y[i]+1) ||
         !same(x[i],y[i]+1, x[i],y[i]+2) ||
         !diff(x[i],y[i], x[i],y[i]+1) ) return false;
    }
  }
  return true;
}


int main(){
  int n;
  while(cin>>n, n){
    if(solve(n)) cout << "Yes" <<endl;
    else cout << "No" << endl;
  }

  return 0;
}

Measured memory_bytes: 6384