#include <graphics.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>

void tree(int x, int y, int height, float angle);

float branch_rotation = 30.0f;
float branch_height_factor = 0.73;

void draw_loop()
{
    int x = getmaxx() / 2;
    int y = getmaxy();
    int height = y - 32;
    float angle = -90;

    setcolor(15);

    while (1)
    {
        clrscr();

        char message[128];
        sprintf(message, "height: %d; rotation: %f (z/x); branch offset %f (a/s)",
            height, branch_rotation, branch_height_factor);
        outtextxy(10, 10, message);

        setcolor(11);
        tree(x, y, height, angle);

        switch (getch())
        {
            case 'z':
                branch_rotation -= 1.0f;
                break;

            case 'x':
                branch_rotation += 1.0f;
                break;

            case 'a':
                branch_height_factor -= 0.01f;
                break;

            case 's':
                branch_height_factor += 0.01f;
                break;

            case ' ':
            case 'q':
            case 27: // Escape.
                return;

            default:
                break;
        }
    }
}

int main()
{
    int gddriver = DETECT, gmode, errorcode;
    initgraph(&gddriver, &gmode, "");
    draw_loop();
    closegraph();
    return 0;
}



void tree(int x, int y, int height, float angle)
{
    // Convert angle to radians.
    float angle_rad = angle * (M_PI / 180.0);

    // Calculate a direction vector.
    float xf = cos(angle_rad);
    float yf = sin(angle_rad);

    // Draw subtrees.
    int branch_height = (int) (height * branch_height_factor);
    int branch_start_x = x + (int) (xf * (height - branch_height));
    int branch_start_y = y + (int) (yf * (height - branch_height));

    // Stop recursion for extreme cases.
    if (branch_height < 1 || branch_height >= height)
    {
        return;
    }

    // Draw the center of the (sub)tree.
    line(x, y, x + (int) (xf * height ), y + (int) (yf * height));

    tree(branch_start_x, branch_start_y, branch_height, angle - branch_rotation);
    tree(branch_start_x, branch_start_y, branch_height, angle + branch_rotation);
}

