snow.pas 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. Program Snowflake;
  2. { This program draws a fractal snowflake pattern. I think I got it out
  3. of some magazine years ago. It was written, as I remember it, for the
  4. PC in BASIC, which I converted to AmigaBASIC. I have long since
  5. forgotten the details of how it worked, so I could not give the
  6. variables meaningful names. To the original author, by the way, goes
  7. the credit for those names. Invoke the program with the line "Snow
  8. <level>", where <level> is a digit between 1 and 6. In order to get a
  9. feel for what's going on, try running the levels in order. Level 6
  10. takes a long time, and frankly doesn't look as good as level 5. }
  11. {
  12. Translated to fpc pascal from pcq pascal.
  13. Updated the source to the new style. Will
  14. now also open a screen.
  15. 04 Apr 2001.
  16. Reworked to use systemvartags.
  17. 28 Nov 2002.
  18. [email protected]
  19. }
  20. uses exec,intuition,agraphics,utility;
  21. var
  22. dx : array [0..11] of real;
  23. dy : array [0..11] of real;
  24. sd : array [0..6] of Longint;
  25. rd : array [0..6] of Longint;
  26. sn : array [0..6] of Longint;
  27. ln : array [0..6] of real;
  28. a : real;
  29. nc : Longint;
  30. x, y, t : real;
  31. w : pWindow;
  32. s : pScreen;
  33. rp : pRastPort;
  34. n : Longint;
  35. d, ns, i, j : Longint;
  36. l : real;
  37. m : pMessage;
  38. const
  39. pens : array [0..0] of integer = (not 0);
  40. Procedure usage;
  41. begin
  42. writeln('Usage: Snow <level>');
  43. writeln(' where <level> is between 1 and 6');
  44. halt(20);
  45. end;
  46. procedure CleanUp(why : string; err : longint);
  47. begin
  48. if assigned(w) then CloseWindow(w);
  49. if assigned(s) then CloseScreen(s);
  50. if why <> '' then writeln(why);
  51. halt(err);
  52. end;
  53. Function readcycles: Longint;
  54. var
  55. cycles : Longint;
  56. begin
  57. if paramcount <> 1 then usage;
  58. cycles := ord(paramstr(1)[1]) - ord('0');
  59. if (cycles > 6) or (cycles < 1) then
  60. usage;
  61. readcycles := cycles;
  62. end;
  63. procedure initarrays;
  64. begin
  65. sd[0] := 0;
  66. rd[0] := 0;
  67. sd[1] := 1;
  68. rd[1] := 0;
  69. sd[2] := 1;
  70. rd[2] := 7;
  71. sd[3] := 0;
  72. rd[3] := 10;
  73. sd[4] := 0;
  74. rd[4] := 0;
  75. sd[5] := 0;
  76. rd[5] := 2;
  77. sd[6] := 1;
  78. rd[6] := 2;
  79. for n := 0 to 6 do
  80. ln[n] := 1.0 / 3.0;
  81. ln[2] := sqrt(ln[1]);
  82. a := 0.0;
  83. for n := 6 to 11 do begin
  84. dy[n] := sin(a);
  85. dx[n] := cos(a);
  86. a := a + 0.52359;
  87. end;
  88. for n := 0 to 5 do begin
  89. dx[n] := -(dx[n + 6]);
  90. dy[n] := -(dy[n + 6]);
  91. end;
  92. x := 534.0;
  93. y := 151.0;
  94. t := 324.0;
  95. end;
  96. begin
  97. nc := readcycles();
  98. initarrays;
  99. s := OpenScreenTags(nil, [SA_Pens, AsTag(@pens),
  100. SA_Depth, 2,
  101. SA_DisplayID, HIRES_KEY,
  102. SA_Title, AsTag('Simple Fractal SnowFlakes'),
  103. TAG_END]);
  104. if s = NIL then CleanUp('No screen',20);
  105. w := OpenWindowTags(nil, [
  106. WA_IDCMP, IDCMP_CLOSEWINDOW,
  107. WA_Left, 0,
  108. WA_Top, s^.BarHeight +1,
  109. WA_Width, s^.Width,
  110. WA_Height, s^.Height - (s^.BarHeight + 1),
  111. WA_DepthGadget, ltrue,
  112. WA_DragBar, ltrue,
  113. WA_CloseGadget, ltrue,
  114. WA_ReportMouse, ltrue,
  115. WA_SmartRefresh, ltrue,
  116. WA_Activate, ltrue,
  117. WA_Title, AsTag('Close the Window to Quit'),
  118. WA_CustomScreen, AsTag(s),
  119. TAG_END]);
  120. if w = nil then CleanUp('No window',20);
  121. rp := w^.RPort;
  122. SetAPen(rp,2);
  123. for n := 0 to nc do
  124. sn[n] := 0;
  125. GfxMove(rp, trunc(x), trunc(y));
  126. repeat
  127. d := 0;
  128. l := t;
  129. ns := 0;
  130. for n := 1 to nc do begin
  131. i := sn[n];
  132. l := l * ln[i];
  133. j := sn[n - 1];
  134. ns := ns + sd[j];
  135. if odd(ns) then
  136. d := (d + 12 - rd[i]) mod 12
  137. else
  138. d := (d + rd[i]) mod 12;
  139. end;
  140. x := x + 1.33 * l * dx[d];
  141. y := y - 0.5 * l * dy[d];
  142. Draw(rp, trunc(x), trunc(y));
  143. sn[nc] := sn[nc] + 1;
  144. n := nc;
  145. while (n >= 1) and (sn[n] = 7) do begin
  146. sn[n] := 0;
  147. sn[n - 1] := sn[n - 1] + 1;
  148. n := n - 1;
  149. end;
  150. until sn[0] <> 0;
  151. m := WaitPort(w^.UserPort);
  152. forbid;
  153. repeat
  154. m := GetMsg(w^.UserPort);
  155. until m = nil;
  156. permit;
  157. CleanUp('',0);
  158. end.