#include<bits/stdc++.h>
using namespace std;

const double INF = 1e+39;
const double EPS = 1e-8;


// ????¬????
struct P3{
  double x,y,z;
  P3(){}
  P3(double x,double y,double z):x(x),y(y),z(z) {}
  P3 operator + (const P3 &a) const{ return (P3){x+a.x, y+a.y, z+a.z}; }
  P3 operator - (const P3 &a) const{ return (P3){x-a.x, y-a.y, z-a.z}; }
  P3 operator * (const double &c) const{ return (P3){x*c, y*c, z*c}; }
  P3 operator / (const double &c) const{ return (P3){x/c, y/c, z/c}; }
};
P3 operator * (double c, const P3 &a){ return (P3){c * a.x, c * a.y, c * a.z}; }

struct L3{
  P3 a,b;
  L3(){
    a = P3(INF,INF,INF);
    b = P3(INF,INF,INF);
  }
  L3(P3 a,P3 b):a(a),b(b){}
};

struct Sphere{ //??????
  P3 c;
  double r;
  Sphere(){}
  Sphere(P3 c,double r):c(c),r(r){}
  double surface_area(){ return M_PI * r * r * 4.0;}
  double area(){ return M_PI * r * r * r * 4.0 / 3.0;}
};


double norm(P3 a){ return a.x*a.x + a.y*a.y + a.z*a.z; }

double abs(P3 a){ return sqrt(a.x*a.x + a.y*a.y + a.z*a.z); }

double dot(P3 a, P3 b){ return a.x*b.x+ a.y*b.y + a.z*b.z; }

P3 cross(P3 a, P3 b){
  return (P3){a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x};
}

bool eq(P3 a,P3 b){
  if( abs( a.x - b.x ) < EPS && 
      abs( a.y - b.y ) < EPS &&
      abs( a.z - b.z ) < EPS ) return true;
  return false;
}

L3 Perpendicular(P3 a, L3 b){//???a????????´???B???????????????
  if( abs(b.b-b.a) < EPS ) return L3();
  P3 vb = (b.b - b.a)/abs(b.b-b.a);
  P3 va = a - b.a;
  double ky = dot(va,vb);
  if( ky < EPS ) return L3(a,a);
  P3 ret = b.a + ky * vb;
  return L3(a,ret);
}

vector<P3> getIntersectSL(Sphere s,const L3 &l){
  vector<P3> ret;
  P3 v = (l.b - l.a)/abs(l.b - l.a);
  P3 vb = s.c - l.a;
  double a = dot( v, vb );
  double b = abs(vb);
  double c = sqrt(b*b - a*a);
  if( s.r + EPS < c ) return ret;
  if( s.r - EPS < c ) {
    ret.push_back( l.a + v * a );
    return ret;   
  }
  double x = sqrt( s.r*s.r - c*c );
  ret.push_back( l.a + v * a - v * x );
  ret.push_back( l.a + v * a + v * x );
  return ret;
}

L3 refrectSL(Sphere s,const L3 &l){
  vector<P3> p = getIntersectSL(s,l);
  if( p.empty() ) return L3();
  P3 rep = p[0];
  if( p.size() == 2 && abs( l.a - p[0] ) > abs( l.a - p[1] ) )
      rep = p[1];
  P3 v = rep - s.c;
  L3 sv =  Perpendicular( l.a, (L3){rep, rep + v} ); 
  P3 nx = sv.a + (sv.b - sv.a) * 2;
  return L3( rep, nx );
}

int N;
Sphere C[111];

void view(P3 a){
  cout << a.x << " "<< a.y << " "<< a.z << endl;
}

int main(){
  while( (~scanf("%d",&N)) && N ){
    int u,v,w;
    scanf("%d%d%d",&u,&v,&w);
    L3 s = L3( P3(0.0,0.0,0.0) , P3((double)u,(double)v,(double)w) );
    for(int i=0;i<N;i++){
      int x,y,z,r;
      scanf("%d%d%d%d",&x,&y,&z,&r);
      C[i] = Sphere( P3((double)x,(double)y,(double)z), (double)r );
    }
    
    while(1){
      vector<L3> refs;
      for(int i=0;i<N;i++){
        L3 a = refrectSL( C[i], s );
        if( a.a.x  > INF/10 ) continue;
        if( abs( a.a - s.a ) < EPS ) continue;
        P3 v1  = (a.a - s.a) / abs( a.a - s.a );
        P3 v2 = (s.b - s.a) / abs( s.b - s.a );
   
        //   cout << "v1 - "; view(v1);
        //cout << "v2 - "; view(v2);

        if( !eq( v1 , v2 ) ) continue;
        //        cout << " L a " << i << endl; view(a.a); view(a.b);

        refs.push_back( a );
      }
      
      if( refs.empty() ) break;
      L3 mini = refs[0];
      for(int i=1;i<refs.size();i++)
      if( abs( mini.a - s.a ) > abs( refs[i].a - s.a ) )
        mini = refs[i];
      s = mini;    
      // cout << " L s " << endl; view(s.a); view(s.b);
      if( abs( s.a - s.b ) < EPS ) break;
    }
    // cout <<"end" << endl;
    printf("%.10lf %.10lf %.10lf\n", s.a.x, s.a.y, s.a.z);
  }
}

Measured memory_bytes: 1236