#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_N = 50;
const int MAX_X = 50;
const int MAX_Y = 50;
const int MAX_D = 10;
const int MAX_T = 100;
const int MAX_DT = MAX_D * MAX_T;

const int dxs[4] = {1, 0, -1,  0};
const int dys[4] = {0, 1,  0, -1};

const int D_E = 0, D_N = 1, D_W = 2, D_S = 3;

/* typedef */

struct Pt {
  int x, y;
  Pt() {}
  Pt(int _x, int _y) { x = _x, y = _y; }
  bool operator<(const Pt& pt) const {
    return x < pt.x || (x == pt.x && y < pt.y);
  }
};

struct Stat {
  int d, x, y, drc;
  Stat() {}
  Stat(int _d, int _x, int _y, int _drc) {
    d = _d, x = _x, y = _y, drc = _drc;
  }
};

/* global variables */

bool grids[MAX_Y + 1][MAX_X + 1][4];
char drcs[MAX_DT + 1];
bool visited[MAX_DT + 1][MAX_Y + 1][MAX_X + 1][4];
vector<Pt> vps;
queue<Stat> q;

/* main */

int main() {
  int n, x0, y0, t;
  cin >> n >> x0 >> y0 >> t;

  memset(drcs, -1, sizeof(drcs));
  
  for (int i = 0; i < n; i++) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;

    if (x1 != x2) {
      if (x1 > x2) swap(x1, x2);
      for (int x = x1; x <= x2; x++) {
	if (x != x2) grids[y1][x][D_E] = true;
	if (x != x1) grids[y1][x][D_W] = true;
      }
    }
    else {
      if (y1 > y2) swap(y1, y2);
      for (int y = y1; y <= y2; y++) {
	if (y != y2) grids[y][x1][D_N] = true;
	if (y != y1) grids[y][x1][D_S] = true;
      }
    }
  }

  if (false) {
    for (int y = 1; y <= 2; y++)
      for (int x = 1; x <= 2; x++) {
	printf("grids[%d,%d]=", x, y);
	for (int drc = 0; drc < 4; drc++)
	  printf("%d ", grids[y][x][drc]);
	putchar('\n');
      }
  }
  
  int sumd = 0;
  for (int i = 0; i < t; i++) {
    int di;
    char ci;
    cin >> di >> ci;

    sumd += di;
    switch (ci) {
    case 'E': drcs[sumd] = D_E; break;
    case 'N': drcs[sumd] = D_N; break;
    case 'W': drcs[sumd] = D_W; break;
    case 'S': drcs[sumd] = D_S; break;
    default: cout << "Illegal char: " << ci << endl;
    }
  }

  if (false) {
    printf("drcs=");
    for (int d = 0; d <= 9; d++) printf("%d ", drcs[d]);
    putchar('\n');
  }
  
  q.push(Stat(0, x0, y0, -1));

  while (! q.empty()) {
    Stat u = q.front();
    q.pop();
    // printf("stat(%d,%d,%d,%d)\n", u.d, u.x, u.y, u.drc);
    
    int rudrc = u.drc ^ 2;
    int ddrc = drcs[u.d];

    if (u.d == sumd) {
      if (u.drc == ddrc || (ddrc != rudrc && grids[u.y][u.x][ddrc]))
	vps.push_back(Pt(u.x, u.y));
      continue;
    }

    int nvd = u.d + 1;
    
    for (int vdrc = 0; vdrc < 4; vdrc++) {
      if (vdrc == rudrc || ! grids[u.y][u.x][vdrc]) continue;
      if (ddrc >= 0 && u.drc != ddrc && vdrc != ddrc) continue;

      int vx = u.x + dxs[vdrc], vy = u.y + dys[vdrc];
      if (! visited[nvd][vy][vx][vdrc]) {
	visited[nvd][vy][vx][vdrc] = true;
	q.push(Stat(nvd, vx, vy, vdrc));
      }
    }
  }

  sort(vps.begin(), vps.end());
  //cout << vps.size() << endl;
  
  int prvx = vps[0].x, prvy = vps[0].y;
  for (int i = 1; i < vps.size(); i++) {
    Pt& vpi = vps[i];
    if (prvx != vpi.x || prvy != vpi.y) {
      printf("%d %d\n", prvx, prvy);
      prvx = vpi.x, prvy = vpi.y;
    }
  }
  printf("%d %d\n", prvx, prvy);
  
  return 0;
}

Measured memory_bytes: 9096