#include <iostream>
#include <cstdio>
#include <vector>
#include <complex>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
 
// * XY座標
#define X real()
#define Y imag()
 
// * 点の表現
typedef complex<double> P;

// * 許容する誤差ε
const double EPS = 1e-8;
// * Infinity
const double INF = 1e12;
// * 円周率
const double PI = acos(-1.0);
// * Infinity 2
const P INF_P(INF,INF);
 
// * complex<double> の順序を定義する
namespace std {
	bool operator < (const P& a, const P& b) {
		return (real(a) != real(b))? real(a) < real(b) : imag(a) < imag(b);
	}
}

// * 2点間の距離
double dist(P p1, P p2) {
	return abs(p1 - p2);
}
 
// * 2つのスカラーが等しいかどうか
bool equal(double a, double b) {
	return ( fabs( a - b ) < EPS );
}
 
// * 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) {
	return real( conj(a) * b );
}
 
// * 外積 (cross product) : a×b = |a||b|sinΘ
double cross(P a, P b) {
	return imag( conj(a) * b ) ;
}
 
// CCW : 反時計回り (Counter Clock Wise)
// CW : 時計回り (Clock Wise)
enum {CCW=1, CW=-1, ON=0};
// * 3点がどちら回りであるか返す, 3点が1直線に乗っているときは ON を返す
int ccw(const P &a, P b, P c) {
    b-=a, c-=a;
    if( cross(b,c) >  EPS ) return CCW; // CCW : 反時計回り
    if( cross(b,c) < -EPS ) return CW;  // CW : 時計回り
    if(dot(b, c) < -EPS )   return +2;  // c--a--b on line
    if(dot(b, b) + EPS < dot(c, c) ) return -2; // a--b--c on line ???
    return ON;
}
 
// ラジアンから度数へ変換して返す
double to_deg(double rad) {
	return rad * 180.0 / PI;
}
 
// 度数からラジアンに変換して返す
double to_rad(double deg) {
	return deg * PI / 180.0;
}

// 直線の表現 ((*this)[0]) と ((*this)[1]) を通る直線
struct Line : public vector<P> {
	Line(const P &a, const P &b) {
		push_back(a); push_back(b);
	}
	Line(vector<P> v){
		push_back(v[0]); push_back(v[1]);
	}
	Line(){}
	// 2直線の平行判定
	bool parallel(const Line& l) {
		return equal( cross( (*this)[0] - (*this)[1] , l[0] - l[1] ), 0.0 );
	}
	// 直線の交差判定
	bool is_intersection(const Line& l) {
		return !equal( cross( (*this)[0] - (*this)[1], l[0] - l[1] ) , 0.0 );
	}
	// 直線の交差判定と交点計算
	bool intersection(Line l, P& p) {
		bool result = this->is_intersection( l );
		if( result ) {
			P a = (*this)[1] - (*this)[0];
			P b = l[1] - l[0];
			p = (*this)[0] + a * cross(b, l[0] - (*this)[0]) / cross(b, a);
		}else {
			p = INF_P;
		}
		return result;
	}
};
 
// 三角形の表現
struct Triangle{
private:
	// 余弦定理から 3 つの角の角度を求める (内部の関数で使用)
    double law_of_cos(double a, double b, double c) {
        return acos( (b*b + c*c - a*a) / (2.0 * b * c) );
    }
public:
	// 3 つの頂点
	P a, b, c;
    // 3 つの辺の長さ
    double edgeA, edgeB, edgeC;
    // 3 つの角の角度 (ラジアン)
    double angleA,angleB,angleC;
    
    // コンストラクタで初期化
    Triangle(P p1, P p2, P p3) {
        a = p1;
        b = p2;
        c = p3;
        edgeB = abs(c-a);
        edgeA = abs(b-c);
        edgeC = abs(a-b);
        angleA = law_of_cos( edgeA, edgeB, edgeC );
        angleB = law_of_cos( edgeB, edgeC, edgeA );
        angleC = law_of_cos( edgeC, edgeA, edgeB );
    }
    // 三角形の面積を返す (ヘロンの公式)
	double get_area() {
		double s = 0.5 * (edgeA + edgeB + edgeC);
		return sqrt( s * (s - edgeA) * (s - edgeB) * (s - edgeC) );
	}
	// 三角形の重心を返す
	P gravity() {
		return P( (a.X + b.X + c.X) / 3.0 , (a.Y + b.Y + c.Y) / 3.0 );
	}
};
 
// 多角形の表現 (凸多角形と仮定する)
struct Polygon{
	// 頂点の集まり
	vector<P> g;
	// コンストラクタで初期化
	Polygon(vector<P> g_){ g = g_; }
	Polygon(){}
	// 凸多角形の面積を返す
	double get_area() {
		double s = 0.0;
		for(int i=2 ; i < g.size() ; i++ ) {
			s += cross( g[i-1] - g[0] , g[i] - g[0] );
		}
		return s/2.0;
	}
	// 凸多角形の重心を返す
	P gravity() {
		P sg(0,0);
		double s = 0.0;
		for(int i=2 ; i < g.size() ; i++ ) {
			Triangle t( g[0] , g[i-1] , g[i] );
			s += t.get_area();
			sg += t.get_area() * t.gravity();
		};
		return sg / s;
	}
	// 凸多角形 を 直線l で切断し、直線の左側の多角形を返す
	Polygon convex_cut(Line l) {
  		vector<P> Q;
  		for(int i = 0; i < g.size() ; i++ ) {
    		P A = g[i];
    		P B = g[(i+1) % g.size()];
    		if( ccw( l[0] , l[1] , A ) != CW ) {
    			Q.push_back( A );
    		}
    		if( ccw( l[0] , l[1] , A ) * ccw( l[0] , l[1] , B ) < 0 ) {
    			Line AB( A , B );
    			P p;
    			AB.intersection( l , p );
     			Q.push_back( p );
     		}
  		}
 		return Polygon( Q );
	}
};
 
// 入力
double W, H, E;
// cnt := ダウジングできる回数
int cnt = 200;
// 解を出力したかどうか
bool ans_flag = false;

// 解を出力
void answer(double x, double y){
	if( !ans_flag ){
		ans_flag = true;
		printf("! %.12f %.12f\n", x, y); fflush(stdout);
	}
}

// (x,y) からダウジングして角度(ラジアン)を返す.
double ask(double x, double y){
	double a;
	printf("? %.12f %.12f\n", x, y); fflush(stdout);
	scanf("%lf", &a);
	cnt--;
	return to_rad(a);
}

P func(P p, double a){
	return p + P( cos(a) , sin(a) );
}
 
int main(){
	
	// 入力
	scanf("%lf %lf %lf", &W, &H, &E );
	
	Polygon g;
	vector<P> vp(4);
	vp[0] = P(W,H);
	vp[1] = P(-W,H);
	vp[2] = P(-W,-H);
	vp[3] = P(W,-H);
	g.g = vp;
	P gp(0,0);
	
	if( E < EPS ){
		P p, p1(0,0), p2(W,H), p3(-W,H);
		double a1 = ask(p1.X,p1.Y);
		double a2 = ask(p2.X,p2.Y);
		double a3 = ask(p3.X,p3.Y);
		Line l1( p1 , func(p1,a1) ), l2( p2 , func(p2,a2) ), l3(p3, func(p3,a3) );
		if( l1.parallel(l2) ){
			l1.intersection( l3 , p );
		}else{
			l1.intersection( l2 , p );
		}
		answer( p.X , p.Y );
	}else if( E <= 90.0 ){
		while( cnt ){
			double a = ask( gp.X , gp.Y );
			double a1 = a - to_rad(E);
			double a2 = a + to_rad(E);
			Line l1( gp ,func(gp,a1) );
			Line l2( func(gp,a2) , gp );
			g = (g.convex_cut(l1)).convex_cut(l2);
			gp = g.gravity();
			
			if( g.get_area() < EPS ) break;
		};
		answer( gp.X , gp.Y );
	}else{
		while( cnt ){
			double a = ask( gp.X , gp.Y ), a_;
			bool flag = false;
			while( cnt ){
				a_ = ask( gp.X , gp.Y );
				if( 60.0 < to_deg(fabs(a-a_)) && to_deg(fabs(a-a_)) < 120.0 ){
					flag = true; break;
				}
				if( 240.0 < to_deg(fabs(a-a_)) && to_deg(fabs(a-a_)) < 300.0 ){
					flag = true; break;
				}
			}
			if( flag ){
				if( 240.0 < to_deg(fabs(a-a_)) && to_deg(fabs(a-a_)) < 300.0 ){
					if( a < 0.0 ) a += 2.0 * PI;
					else a_ += 2.0 * PI;
				}
			
				double a1 = max(a,a_) - to_rad(120);
				double a2 = min(a,a_) + to_rad(120);
			
				Line l1( gp ,func(gp,a1) );
				Line l2( func(gp,a2) , gp );
				g = (g.convex_cut(l1)).convex_cut(l2);
				gp = g.gravity();
			}
			if( g.get_area() < EPS ) break;
		};
		answer( gp.X , gp.Y );
	}
}

Measured memory_bytes: 0