Go: package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

var scanner = bufio.NewScanner(os.Stdin)

func main() {
	for scanner.Scan() {
		buf0 := strings.Split(scanner.Text(), " ")
		input0 := make([]int, 2)
		for i := range input0 {
			input0[i], _ = strconv.Atoi(buf0[i])
		}
		if input0[0] == 0 && input0[1] == 0 {
			break
		}
		a, b := input0[0], input0[1]
		scanner.Scan()
		buf1 := strings.Split(scanner.Text(), " ")
		input1 := make([]int, 2)
		for i := range input1 {
			input1[i], _ = strconv.Atoi(buf1[i])
		}
		c, d := input1[0], input1[1]
		scanner.Scan()
		buf2 := strings.Split(scanner.Text(), " ")
		input2 := make([]int, 2)
		for i := range input2 {
			input2[i], _ = strconv.Atoi(buf2[i])
		}
		e, f := input2[0], input2[1]
		scanner.Scan()
		buf3 := strings.Split(scanner.Text(), " ")
		input3 := make([]int, 2)
		for i := range input3 {
			input3[i], _ = strconv.Atoi(buf3[i])
		}
		g, h := input3[0], input3[1]
		scanner.Scan()
		r, _ := strconv.Atoi(scanner.Text())
		if (a-g)*(a-g)+(b-h)*(b-h) <= r*r && (c-g)*(c-g)+(d-h)*(d-h) <= r*r && (e-g)*(e-g)+(f-h)*(f-h) <= r*r {
			fmt.Println("b")
		} else if dist(a, b, c, d, g, h) > float64(r)-0.000001 && dist(a, b, e, f, g, h) > float64(r)-0.000001 && dist(e, f, c, d, g, h) > float64(r)-0.000001 && inclusive(a, b, c, d, e, f, g, h) {
			fmt.Println("a")
		} else if CL_intersect(a, b, c, d, g, h, r) || CL_intersect(a, b, e, f, g, h, r) || CL_intersect(e, f, c, d, g, h, r) {
			fmt.Println("c")
		} else {
			fmt.Println("d")
		}
	}
}

func CL_intersect(ax, ay, bx, by, cx, cy, r int) bool {
	acx := cx - ax
	acy := cy - ay
	bcx := cx - bx
	bcy := cy - by
	abx := bx - ax
	aby := by - ay
	if acx*acx+acy*acy >= r*r || bcx*bcx+bcy*bcy >= r*r {
		if abx*acx+aby*acy < 0 {
			if acx*acx+acy*acy <= r*r {
				return true
			}
		} else {
			if abx*acx+aby*acy > abx*abx+aby*aby {
				if bcx*bcx+bcy*bcy <= r*r {
					return true
				}
			} else if acx*acx+acy*acy-(abx*acx+aby*acy)*(abx*acx+aby*acy)/(abx*abx+aby*aby) <= r*r {
				return true
			}
		}
	}
	return false
}

func inclusive(ax, ay, bx, by, cx, cy, px, py int) bool {
	ok1 := true
	ok2 := true
	if (bx-ax)*(py-ay)-(px-ax)*(by-ay) < 0 {
		ok1 = false
	}
	if (bx-ax)*(py-ay)-(px-ax)*(by-ay) > 0 {
		ok2 = false
	}
	if (cx-bx)*(py-by)-(px-bx)*(cy-by) < 0 {
		ok1 = false
	}
	if (cx-bx)*(py-by)-(px-bx)*(cy-by) > 0 {
		ok2 = false
	}
	if (ax-cx)*(py-cy)-(px-cx)*(ay-cy) < 0 {
		ok1 = false
	}
	if (ax-cx)*(py-cy)-(px-cx)*(ay-cy) > 0 {
		ok2 = false
	}
	return ok1 || ok2
}

func dist(ax, ay, bx, by, px, py int) float64 {
	dx := float64(bx - ax)
	dy := float64(by - ay)
	A := float64(dx*dx + dy*dy)
	B := dx*float64(ax-px) + dy*float64(ay-py)
	t := -B / A
	if t < 0 {
		t = 0
	}
	if t > 1 {
		t = 1
	}
	tx := float64(ax) + dx*t
	ty := float64(ay) + dy*t
	return math.Sqrt((float64(px)-tx)*(float64(px)-tx) + (float64(py)-ty)*(float64(py)-ty))
}

C++: #include <iostream>
#include <vector>
#include <cmath>
using namespace std;

const double EPS = 1e-3;
const double PI = acos(-1.0);

// 2つのスカラーが等しいかどうか
bool equal(double a, double b) {
	return fabs(a - b) < EPS;
}

// 点クラス
struct P {
	double x, y;
	P(double x_, double y_) { x = x_; y = y_; }
	P(){}
	// 加算, 減算, スカラー倍
	P operator+(const P& a) const {
		return P(x + a.x, y + a.y);
	}
	P operator-(const P& a) const {
		return P(x - a.x, y - a.y);
	}
	P operator*(const P& a) const {
		return P(x * a.x - y * a.y, x * a.y + y * a.y);
	}
	P operator*(double c) const {
		return P(x * c, y * c);
	}
	P operator/(const P& a) const {
		double norm = a.x * a.x + a.y * a.y;
		double x_ = (x * a.x + y * a.y) / norm;
		double y_ = (y * a.x - x * a.y) / norm;
		return P(x_, y_);
	}
	P operator/(double c) const {
		return P(x / c, y / c);
	}
	P& operator+=(const P& a) {
		x += a.x; y += a.y;
	}
	P& operator-=(const P& a) {
		x -= a.x; y -= a.y;
	}
	P& operator*=(const P& a) {
		*this = P(x * a.x - y * a.y, x * a.y + y * a.y);
	}
	P& operator*=(double c) {
		*this = P(x * c, y * c);
	}
	P& operator/=(const P& a) {
		double norm = a.x * a.x + a.y * a.y;
		double x_ = (x * a.x + y * a.y) / norm;
		double y_ = (y * a.x - x * a.y) / norm;
		*this = P(x_, y_);
	}
	P& operator/=(double c) {
		*this = P(x / c, y / c);
	}
};
P operator*(double c, P a){
	return P(a.x * c, a.y * c);
}
// 比較演算子
bool operator==(const P& a, const P& b) {
	return equal(a.x, b.x) && equal(a.y, b.y);
}
bool operator!=(const P& a, const P& b) {
	return !(a == b);
}
bool operator<(const P& a, const P& b) {
	return (a.x != b.x)? a.x < b.x : a.y < b.y;
}
// 原点からの距離(絶対値)
double abs(P a) {
	return sqrt(a.x * a.x + a.y * a.y);
}
// 内積 (dot product) : a・b = |a||b|cosΘ
double dot(P a, P b) {
	return a.x * b.x + a.y * b.y;
}
// ノルム
double norm(const P& z){
	return z.x * z.x + z.y * z.y;
}

double x[4], y[4], r;

double D(double x1, double y1, double x2, double y2){
	return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

// 直線クラス
struct Line : public vector<P> {
	Line(){}
	Line(const P& a, const P& b) {
		push_back(a); push_back(b);
	}
};


// 線分 s 上に点 p があるかどうか
bool intersectSP(const Line& s, const P& p) {
	return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) < EPS;
}
P projection(const Line& l, const P& p) {
	double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
	return l[0] + (l[0] - l[1]) * t;
}
// 線分と点の距離
double distanceSP(const Line& s, const P& p) {
	const P r = projection(s, p);
	if (intersectSP(s, r)) return abs(r - p);
	return min(abs(s[0] - p), abs(s[1] - p));
}

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) );
	}
	// 点 a , b を端点とする線分に点 c が含まれているかどうか
	bool contain(P a, P b, P c) {
		return abs(a - c) + abs(b - c) - abs(b - a) < EPS;
	}
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 );
	}
	// 点 p が三角形の辺上にあるかどうか
	bool on_boundary(P p) {
		return contain(a, b, p) || contain(b, c, p) || contain(c, a, p);
	}
	// 点 p が三角形の内部にあるかどうか ( AOJ 0012 で検証済み )
	bool is_inside(P p) {
		// 辺上にあるとき
		if( this->on_boundary(p) ) return true;
		
		Triangle t1( a , b , p );
		Triangle t2( b , c , p );
		Triangle t3( c , a , p );
		// 角APB + 角BPB + 角CPA が 360度なら 点 p は三角形の内部にある
		return equal( t1.angleC + t2.angleC + t3.angleC , 2.0 * PI );
	}
};

bool in_circle(){
	for(int i = 0 ; i <= 2 ; i++ ){
		int d = (x[i] - x[3]) * (x[i] - x[3]) + (y[i] - y[3]) * (y[i] - y[3]);
		if( !(d <= r * r) ) return false;
	}
	return true;
}

bool in_triangle(){
	Triangle t(P(x[0], y[0]), P(x[1], y[1]), P(x[2], y[2]));
	return t.is_inside(P(x[3], y[3]));
}

bool intersect(){
	Line s1(P(x[0], y[0]), P(x[1], y[1]));
	Line s2(P(x[1], y[1]), P(x[2], y[2]));
	Line s3(P(x[2], y[2]), P(x[0], y[0]));
	Line s4(P(x[1], y[1]), P(x[0], y[0]));
	Line s5(P(x[2], y[2]), P(x[1], y[1]));
	Line s6(P(x[0], y[0]), P(x[2], y[2]));
	P p(x[3], y[3]);
	
	if( distanceSP(s1, p) < r + EPS ) return true;
	if( distanceSP(s2, p) < r + EPS ) return true;
	if( distanceSP(s3, p) < r + EPS ) return true;
	if( distanceSP(s4, p) < r + EPS ) return true;
	if( distanceSP(s5, p) < r + EPS ) return true;
	if( distanceSP(s6, p) < r + EPS ) return true;
	return false;
}

int main(){
	while( cin >> x[0] >> y[0], x[0] || y[0] ){
		cin >> x[1] >> y[1] >> x[2] >> y[2] >> x[3] >> y[3] >> r;
		
		if( in_circle() ){
			cout << "b" << endl;
		}else if( intersect() ){
			cout << "c" << endl;
		}else if( in_triangle() ){
			cout << "a" << endl;
		}else{
			cout << "d" << endl;
		}
	}
}