import std.stdio;
import std.c.stdio;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.regex;
import std.typecons;

const EPS = 1e-9;
struct Point {
    double x, y;
    Point opBinary(string op)(in Point p) const {
        static if (op == "+") {
            return Point(x + p.x, y + p.y);
        } else if (op == "-") {
            return Point(x - p.x, y - p.y);
        }
    }
    Point opBinary(string op)(double a) const {
        static if (op == "*") {
            return Point(a * x, a * y);
        } else if (op == "/") {
            return Point(x / a, y / a);
        }
    }
}

double distance2(in Point a, in Point b) {
    double dx = a.x - b.x, dy = a.y - b.y;
    return dx * dx + dy * dy;
}
double norm2(in Point a) {
    return (a.x * a.x) + (a.y * a.y);
}
double norm(in Point a) {
    return sqrt(norm2(a));
}
double dot(in Point a, in Point b) {
    return a.x * b.x + a.y * b.y;
}
double cross(in Point a, in Point b) {
    return a.x * b.y - a.y * b.x;
}
static int CCW(Point a, Point b, Point c){
    b = b - a; c = c - a;
    if (cross(b, c) > EPS) return +1;      // 反時計周り
    if (cross(b, c) < -EPS) return -1;     // 時計周り
    if (dot(b, c) < 0) return +2;          // c--a--b 直線
    if (b.norm < c.norm) return -2;    // a--b--c 直線
    return 0;                              // a--c--b 直線
}

Point projection(in Segment s, in Point p) {
    Point a = s.a, b = s.b;
    Point u = b - a,
          v = p - a;
    double n = u.norm2;
    return a + u * dot(u, v) / n;
}

struct Segment {
    Point a, b;
}

bool contains(in Segment s, in Point p) {
    Point a = s.a, b = s.b;
    if (a.x > b.x) swap(a, b);
    if (! (a.x <= p.x && p.x <= b.x) ) return false;
    if (a.y > b.y) swap(a, b);
    return a.y <= p.y && p.y <= b.y;
}
double distance2(in Segment s, in Point p) {
    if (s.contains(s.projection(p))) {
        Point u = s.b - s.a,
              v = p - s.a;
        double x = cross(u, v),
               y = distance2(s.a, s.b);
        return (x * x / y);
    } else {
        return min(distance2(s.a, p), distance2(s.b, p));
    }
}
 
void main() {
    Point[] P = new Point[3];
    Point C;
    double R;
    bool input() {
        double x, y;
        scanf("%lf %lf\n", &x, &y);
        if (x == 0 && y == 0) return false;
        P[0] = Point(x, y);
        foreach (i; 1 .. 3) {
            scanf("%lf %lf\n", &x, &y);
            P[i] = Point(x, y);
        }
        scanf("%lf %lf\n", &C.x, &C.y);
        scanf("%lf\n", &R);
        return true;
    }
    
    void solve() {
        bool CheckB() {
            // 三角形が円に含まれる
            foreach (i; 0 .. 3) {
                Point p = P[i];
                if (C.distance2(p) > R * R) {
                    return false;
                }
            }
            return true;
        }
        bool CheckC() {
            // 交点が存在
            foreach (i; 0 .. 3) {
                Point p = P[i], q = P[(i + 1) % 3];
                if (Segment(p, q).distance2(C) <= R * R) {
                    return true;
                }
            }
            return false;
        }
        bool CheckA() {
            // 円が三角形に含まれる
            int ccw = CCW(P[0], P[1], C);
            foreach (i; 1 .. 3) {
                Point p = P[i], q = P[(i + 1) % 3];
                if (ccw != CCW(p, q, C)) return false;
            }
            foreach (i; 0 .. 3) {
                Point p = P[i], q = P[(i + 1) % 3];
                if (Segment(p, q).distance2(C) < R * R) {
                    return false;
                }
            }
            return true;
        }
        if (CheckB) {
            writeln("b");
        } else if (CheckA) {
            writeln("a");
        } else if (CheckC) {
            writeln("c");
        } else {
            writeln("d");
        }
    }

    while (input) solve;
}

Measured memory_bytes: 1076