! This is a Mandelbrot fractal zoomer I did some time ago.
! Peter De Wachter
!
[email protected]
Release 1;
Constant F_BITS = 12;
Constant F_DIV = 64; ! == 2 ^ (F_BITS / 2)
Constant TEXT = 0;
Constant STATUS = 1;
Constant C_CENTER = 1;
Constant C_LEFT = 0;
Constant C_RIGHT = 2;
Constant C_UP = 2;
Constant C_DOWN = 0;
Global max_iter = 250;
Global inf;
Global screen_width;
Global screen_height;
Global top;
Global bottom;
Global left;
Global right;
Global width;
Global height;
Global x_inc;
Global y_inc;
Array chars -> '.' '"' '-' '+' '=' '*' '#' '!' '?' 'a' '%' '&' '$' '?' '4' 64;
Array cursorpos table 2;
[ Main char;
InitScreen();
SetDim(Fixed(-2), Fixed(1), Fixed(-1), Fixed(1));
inf = Fixed(4);
DrawFractal();
PrintStatusLine("FractalZ, copyright 1999 by Peter De Wachter. Press h for help.");
for (::) {
@read_char 1 -> char;
switch (char) {
'z':
Zoom();
DrawFractal();
146 to 155:
char = char - 146;
ZoomRel(char % 3, char / 3);
DrawFractal();
'+':
max_iter++;
if (max_iter < 1) max_iter--;
PrintStatusLine("Max iterations: ", max_iter);
'-':
if (max_iter > 1) max_iter--;
PrintStatusLine("Max iterations: ", max_iter);
'd':
DrawFractal();
'o':
SetDim(Fixed(-2), Fixed(1), Fixed(-1), Fixed(1));
DrawFractal();
27, 'q':
@erase_window -1;
@quit;
's', 'r':
fsaverest(char);
'h':
Help();
}
}
];
[ InitScreen;
font off;
@buffer_mode 0;
if ((screen_width = 0->$21) == 0)
screen_width = 80;
if ((screen_height = 0->$20) == 255)
screen_height = (screen_width * 100) / 162;
@split_window screen_height;
];
[ TextScreen;
@split_window 1;
@set_window TEXT;
@erase_window TEXT;
@buffer_mode 1;
new_line;
];
[ SetDim l r t b oldl oldr oldt oldb tmp;
oldt = top; oldb = bottom; oldl = left; oldr = right;
top = t; bottom = b; left = l; right = r;
height = bottom - top; width = right - left;
x_inc = (width + screen_width) / screen_width;
y_inc = (height + screen_height - 1) / (screen_height - 1);
if ((width / x_inc < screen_width - (screen_width / 5)) ||
(height / y_inc < screen_height - (screen_width / 5))) {
PrintStatusLine("Can't zoom that much...");
@read_char 1 -> tmp;
SetDim(oldl, oldr, oldt, oldb);
}
];
[ ZoomRel x y nb nt nl nr;
switch (x) {
C_LEFT: nl = left; nr = left / 2 + right / 2;
C_RIGHT: nl = left / 2 + right / 2; nr = right;
C_CENTER: nl = left / 2 + right / 2 - width / 4;
nr = left / 2 + right / 2 + width / 4;
}
switch (y) {
C_UP: nt = top; nb = top / 2 + bottom / 2;
C_DOWN: nt = top / 2 + bottom / 2; nb = bottom;
C_CENTER: nt = top / 2 + bottom / 2 - height / 4;
nb = top / 2 + bottom / 2 + height / 4;
}
SetDim(nl, nr, nt, nb);
];
[ GetXY x y char;
for (::) {
@set_cursor y x;
style reverse;
print "+";
style roman;
@read_char 1 0 -> char;
switch (char) {
129: if (y > 2) { DrawFractalChar(x, y); y--; }
130: if (y < screen_height) { DrawFractalChar(x, y); y++; }
131: if (x > 1) { DrawFractalChar(x, y); x--; }
132: if (x < screen_width) { DrawFractalChar(x, y); x++; }
10, 13, 32, 27, 'z': jump done;
}
}
.done;
return x * 256 + y;
];
[ Zoom nl nr nt nb tmp;
PrintStatusLine("Select upper-left point...");
tmp = GetXY(screen_width / 2, screen_height / 2);
nl = left + (tmp / 256 - 1) * x_inc;
nt = top + (tmp % 256 - 2) * y_inc;
PrintStatusLine("Select lower-right point...");
tmp = GetXY(screen_width / 2, screen_height / 2);
nr = left + (tmp / 256) * (x_inc - 1);
nb = top + (tmp % 256 - 1) * (y_inc - 1);
if (nl > nr) { tmp = nl; nl = nr; nr = tmp; }
if (nt > nb) { tmp = nt; nt = nb; nb = tmp; }
SetDim(nl, nr, nt, nb);
];
[ DrawFractal x y;
@split_window 1;
@erase_window TEXT;
@split_window screen_height;
PrintStatusLine("Calculating...");
y = top;
for (::) {
x = left;
while (x < right) {
Iterate(x, y);
x = x + x_inc;
}
y = y + y_inc;
if (y < bottom) {
print "^";
} else
break;
}
PrintStatusLine(
"Ready. Horizontal zoom = ",
19200 / (width / 64),
"%, vertical zoom = ",
25600 / (height / 32));
];
[ DrawFractalChar x y;
@set_cursor y x;
Iterate(left + (x-1) * x_inc, top + (y-2) * y_inc);
];
[ Iterate x y iter cx cy xd yd x2 y2;
iter = 0;
cx = x; cy = y;
xd = x / F_DIV;
x2 = xd * xd;
yd = y / F_DIV;
y2 = yd * yd;
while ((x2 + y2 < inf) && (iter < max_iter)) {
x = x2 - y2 + cx;
y = xd * yd * 2 + cy;
iter++;
xd = x / F_DIV;
x2 = xd * xd;
yd = y / F_DIV;
y2 = yd * yd;
}
if (iter == max_iter) {
print " ";
} else {
print (char) chars->(iter&15);
}
];
[ Help tmp;
PrintStatusLine("Help");
TextScreen();
style bold;
print "FractalZ";
style roman;
print ", release ", (0-->$1) & $03ff, ", serial ";
DumpHeader($12, $17);
print ", compiled with Inform ";
DumpHeader(60, 63);
print ".^";
print "^
FractalZ is a Mandelbrot-set zoomer for the Z-Machine. Who said it could only
be used for adventure games?^^
It's controls are:
^ 1-9 Zoom into the lower-left (1), upper-right (9), ... corner.
^ z Zoom into a area you choose.
^ +/- Increase / decrease the number of iterations.
^ d Redraw the fractal
^ o Zoom out.
^ s Save the current state.
^ r Restore.
^ q Quit.
^ h Help (but you already knew that).^^
It has been programmed by Peter De Wachter (dewachter@@64softhome.net)
somewhere in the spring of 1999.";
@read_char 1 -> tmp;
InitScreen();
DrawFractal();
];
[ Fixed x;
@art_shift x F_BITS -> x;
return x;
];
[ PrintStatusLine str1 num2 str3 num4;
@set_window STATUS;
@set_cursor 1 1;
style reverse;
print " ";
if (str1 ~= nothing) { print (string) str1;
if (num2 ~= nothing) { print num2;
if (str3 ~= nothing) { print (string) str3;
if (num4 ~= nothing) { print num4, "%"; } } } }
@get_cursor cursorpos;
spaces screen_width - cursorpos->3 + 1;
@set_cursor 2 1;
style roman;
];
[ fsaverest what;
if (what == 's')
PrintStatusLine("Saving...");
else
PrintStatusLine("Restoring...");
TextScreen();
if (what == 's')
save next;
else
restore next;
.next;
InitScreen();
SetDim(left, right, top, bottom);
DrawFractal();
];
[ DumpHeader from to; ! destroys from
for (: from <= to: from++) print (char)0->from;
];