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 <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <iterator>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) container.begin(), container.end()
#define RALL(container) container.rbegin(), container.rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

const int INF = 1<<28;
const double EPS = 1e-8;
const int MOD = 1000000007;

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	typedef double R;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }

	typedef complex<R> P;
	istream& operator>>(istream &is, P &p) {
		R x, y;
		is >> x >> y;
		p = P(x, y);
		return is;
	}
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}

	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		P dir()const {return SELF[1] - SELF[0];}
		friend istream& operator>>(istream &is, L &l) {
			P p1, p2;
			is >> p1 >> p2;
			l = L(p1, p2);
			return is;
		}
		bool online(const P &p)const {return !sig(outp(p-SELF[0], dir()));}
		R distance(const P &p)const {return abs(outp(dir(), p - SELF[0])) / abs(dir());}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		bool online(const P &p){return !sig(abs(SELF[0]-p) + abs(SELF[1] - p) - abs(SELF[0] - SELF[1]));}
		friend inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
		R distance(const P &p)const {
			if(inp(p-SELF[0],  dir()) < EPS) return abs(p - SELF[0]);
			if(inp(p-SELF[1], -dir()) < EPS) return abs(p - SELF[1]);
			return L::distance(p);
		}
	};

	struct C : public P{
		R r;
		friend istream& operator>>(istream &is, C &c) {
			operator>>(is, (P &)c);
			is >> c.r;
			return is;
		}
		bool inside(const P& p)const { return abs(p-SELF) < r + EPS;}
		friend inline bool cc_intersect(const C &a, const C &b){return abs(a-b)<a.r+b.r+EPS && abs(a-b)>abs(a.r - b.r)-EPS;}
		friend inline bool cl_intersect(const C &c, const L &l){return l.distance(c) < c.r + EPS;}
		friend inline bool cs_intersect(const C &c, const S &s){return (!c.inside(s[0]) || !c.inside(s[1])) && s.distance(c) < c.r + EPS;}
	};
	
	struct G : public vector<P>{
		enum {OUT, IN, ON};
		S edge(int i)const {return S(at(i), at((i+1)%size()));}
		bool contains(const P &p)const {
			R sum = .0;
			REP(i, size()){
				if(L(at(i), at((i+1)%size())).online(p)) return ON;	// online
				sum += arg((at(i) - p) / (at((i+1)%size()) - p));
			}
			return sig(sum) ? IN : OUT;
		}
		
		R area(){
			R sum = 0;
			REP(i, size()) sum += outp(at(i), at((i+1)%size()));
			return abs(sum / 2.);
		}
	};
#undef SELF
#undef at
};
using namespace geom;

int n;

char check(const C& c, const G &g){
	REP(i, 3) if(cs_intersect(c, g.edge(i))) return 'c';
	int f = 1;
	REP(i, 3) if(!c.inside(g[i])) f = 0;
	if(f) return 'b';
	if(g.contains((P)c)) return 'a';
	return 'd';
}

int main(){
	ios::sync_with_stdio(false);
	while(1){
		G g;
		C c;
		REP(i, 3){
			P p;
			cin >> p;
			if(p.X == 0) return 0;
			g.push_back(p);
		}
		cin >> c;
		cout << check(c, g) << endl;
	}
	return 0;
}