! This is a Mandelbrot fractal zoomer I did some time ago. ! Peter De Wachter ! dewachter@softhome.net 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 -> '.' '"' '-' '+' '=' '*' '#' '!' '?' 'æ' '%' '&' '$' 'œ' '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; ];