#include<bits/stdc++.h>
#define f first
#define s second
#define mp make_pair
#define pi M_PI
#define inf 1<<30
#define eps (1e-11)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;

class Point{
public:
  double x,y,z;
  Point(double x=0,double y=0,double z=0):x(x),y(y),z(z){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y,z+p.z);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y,z-p.z);}
  Point operator*(double k){ return Point(x*k,y*k,z*k);}
  Point operator/(double k){ return Point(x/k,y/k,z/k);}
  bool operator<(Point p)const{ 
    return (x!=p.x ? x<p.x : (y!=p.y ? y<p.y : z<p.z));}
  bool operator==(Point p)const{ 
    return (fabs(x-p.x)<eps && fabs(y-p.y)<eps &&  fabs(z-p.z)<eps);}
  
  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y+z*z);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1,Point p2):p1(p1),p2(p2){}
};
typedef Segment Line;

class sphere{
public:
  Point c;
  double r;
  sphere(Point c=Point(),double r=0.0):c(c),r(r){}
};

double norm(Vector a){ return (a.x*a.x+a.y*a.y+a.z*a.z);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y+a.z*b.z);}
Vector cross(Vector a,Vector b){ 
  Vector res;
  res.x=(a.y*b.z)-(a.z*b.y);
  res.y=(a.z*b.x)-(a.x*b.z);
  res.z=(a.x*b.y)-(a.y*b.x);
  return res;
}

static const int COUNTER_CLOCKWISE=1;
static const int CLOCKWISE=-1;
static const int ONLINE_BACK=2;
static const int ONLINE_FRONT=-2;
static const int ON_SEGMENT=0;

int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(abs(cross(a,b))>eps)return COUNTER_CLOCKWISE;
  if(abs(cross(a,b))<-eps)return CLOCKWISE;
  if(dot(a,b)<-eps)return ONLINE_BACK;
  if(a.norm()<b.norm())return ONLINE_FRONT;
  return ON_SEGMENT;
}

Point project(Segment s,Point p){
  Vector base=(s.p2-s.p1);
  double r=(dot(p-s.p1,base)/base.norm());
  return (s.p1+base*r);
}

Point reflect(Segment s,Point p){
  return p+(project(s,p)-p)*2;
}

double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1))/abs(l.p2-l.p1);
}

bool iscross(Line l,sphere c){
  if((getDistanceLP(l,c.c)-c.r)<eps)return true;
  return false;
}

pair<Point,Point> getCrossPoints(sphere c,Line l){
  Vector pr=project(l,c.c);
  Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
  double base=sqrt(c.r*c.r-norm(pr-c.c));
  return mp(pr+e*base,pr-e*base);
}

Point firstCrossPointCL(sphere s,Line a){
  pair<Point,Point> pp=getCrossPoints(s,a);
  if(abs(pp.f-a.p1)<abs(pp.s-a.p1))return pp.f;
  return pp.s;
}

int main()
{
  int n,u,v,w,x,y,z,r;

  while(1){
    cin>>n;
    if(n==0)break;
    cin>>u>>v>>w;
    vector<sphere> vs;
    for(int i=0;i<n;i++){
      cin>>x>>y>>z>>r;
      vs.push_back(sphere(Point(x,y,z),r));
    }

    Line s(Point(0,0,0),Point(u,v,w));

    while(1){
      Point p(inf,inf);
      int j=-1;

      for(int i=0;i<vs.size();i++){
	if(iscross(s,vs[i])){
	  Point p2=firstCrossPointCL(vs[i],s);
	  if(p2==s.p1)continue;
	  if(ccw(s.p1,s.p2,p2)!=2 && (abs(p2-s.p1)-abs(p-s.p1))<-eps){
	    p=p2;
	    j=i;
	  }
	}
      }
      if(p.x==inf && p.y==inf){
	printf("%.10f %.10f %.10f\n",s.p1.x,s.p1.y,s.p1.z);
	break;
      }
      Line L(vs[j].c,p);
      s.p2=reflect(L,s.p1);
      s.p1=p;
    }
  }
  return 0;
}

Measured memory_bytes: 1244