/* gcc -o julia julia.c `allegro-config --libs` -O3 -funroll-loops */

#include <stdlib.h>
#include <stdio.h>
#include <allegro.h>

#define ZOOM 100
#define ITERS 60

typedef struct { double re, im; } COMPLEX;

int julia(COMPLEX, COMPLEX);

int main(int argc, char **argv)
{
    int i, j;
    BITMAP *buffa;
    COMPLEX c, incr;
    int steps;

    if (argc < 6) {
        fprintf(stderr, "%s REAL1 IMAG1 REAL2 IMAG2 STEPS\n", argv[0]);
        return 2;
    }

    steps = atoi(argv[5]);

    c.re = atof(argv[1]);
    c.im = atof(argv[2]);

    incr.re = (atof(argv[3]) - c.re) / steps;
    incr.im = (atof(argv[4]) - c.im) / steps;

    allegro_init();
    install_keyboard();

    set_color_depth(desktop_color_depth());
    if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, ZOOM * 4, ZOOM * 4, 0, 0) != 0)
        return 1;

    buffa = create_bitmap(SCREEN_H, SCREEN_W);

    do {
        char wt[25];

        for (i = 0; i < ZOOM * 4; ++i) {
            COMPLEX z;
            
            z.re = ((double)i - ZOOM * 2) / ZOOM;

            for (j = 0; j < ZOOM * 4; ++j) {
                int its, col;

                z.im = ((double)j - ZOOM * 2) / ZOOM;
                its = julia(z, c);
                col = 255 - its * 255 / ITERS;

                putpixel(buffa, i, j, makecol(col, col, col));
            }
        }

        snprintf(wt, 25 * sizeof(char), "%f + %fj", c.re, c.im);
        set_window_title(wt);
        blit(buffa, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

        c.re += incr.re;
        c.im += incr.im;

    } while (steps--);

    while (!keypressed());

    return 0;

} END_OF_MAIN()

int julia(COMPLEX z, COMPLEX c)
{
    int i;

    for (i = 0; i < ITERS; ++i) {
        COMPLEX t;

        t.re = z.re * z.re - z.im * z.im + c.re;
        t.im = 2 * z.re * z.im + c.im;

        z = t;

        if (z.re * z.re + z.im * z.im > 4)
            return i;
    }

    return i;
}