Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - STxAxTIC

Pages: [1] 2 3 ... 5
1
QB64 Discussion / TIMER vs SLEEP
« on: March 28, 2022, 07:57:16 am »
What happens when the unstoppable force of TIMER meets the immovable object of SLEEP?

Code: QB64: [Select]
  1. Screen _NewImage(600, 600, 32)
  2.  
  3. On Timer(t1, .01) moo
  4. Timer(t1) On
  5.  
  6.     PSet (Rnd * _Width, Rnd * _Height), _RGB(255, 255, 255)
  7.     'Sleep
  8.     _Display
  9.  
  10.  
  11. Sub moo
  12.     'do nothing

When there's a Timer at play, SLEEP never fully halts the program - or, it sorta does. It slows the thing down in kindof an interesting way. Not that anybody should ever depend on SLEEP for anything, so it's weird that this question would come up in the first place.... anyway... Thought I'd share.

2
Programs / Finished Driven Pendulum + Mouse Toy
« on: March 22, 2022, 04:32:01 pm »
REDACTED

3
Programs / Double Pendulum Studies
« on: March 12, 2022, 03:08:58 pm »
REDACTED

4
Programs / Oddly satisfying Lissajous Glyphs
« on: March 02, 2022, 12:14:33 am »
REDACTED

5
Programs / Domain Coloring
« on: February 14, 2022, 01:54:11 pm »
Code: QB64: [Select]
  1. 'A = render anti-aliased image
  2. 'B = render standard image
  3.  
  4. 'MouseButton1 = Re-center
  5. 'MouseButton3 = Zoom x2 (in)
  6. 'MouseButton2 = Zoom /2 (out)
  7.  
  8. 'Leftarrow  = Next example plot
  9. 'Rightarrow = Previous example plot
  10. 'Uparrow    = Increase iterations (where applicable)
  11. 'DownArrow  = Decrease iterations (where applicable)
  12.  
  13. 'Num 1 = Shading option (HSV vs RGB vs Average)
  14. 'Num 2 = Shading scheme (1, 2, 3)
  15. 'Num 3 = Shade near origin
  16. 'Num 4 = Shade axes
  17. 'Num 5 = Shade integers
  18. 'Num 6 = Shade contours
  19. 'Num 7 = Greyscale
  20. 'Num 8 = Stencil
  21. 'Num 9 = Invert
  22. 'Num 0 = Bolden
  23.  
  24. _TITLE "Domain Coloring"
  25.  
  26. 'SCREEN _NEWIMAGE(250, 250, 32)
  27. SCREEN _NEWIMAGE(800, 800, 32)
  28. 'SCREEN _NEWIMAGE(1024, 768, 32)
  29. 'SCREEN _NEWIMAGE(1920, 1080, 32)
  30.  
  31. pi = 4 * ATN(1)
  32.  
  33. DIM AS DOUBLE zoom, xshift, yshift, re, im
  34. DIM AS STRING ExhibitName
  35. DIM SHARED PlotOption(0 TO 10) AS DOUBLE
  36.  
  37. PlotOption(0) = 10
  38. PlotOption(1) = .5
  39. PlotOption(2) = 1
  40. PlotOption(3) = 1
  41. PlotOption(4) = 1
  42. PlotOption(5) = 1
  43. PlotOption(6) = 1
  44. PlotOption(7) = -1
  45. PlotOption(8) = -1
  46. PlotOption(9) = -1
  47. PlotOption(10) = -1
  48.  
  49. ' Selector
  50. q = 1
  51.  
  52. Initialize q, ExhibitName, zoom, xshift, yshift
  53. CALL DrawPlot(ExhibitName, zoom, xshift, yshift, -1)
  54.  
  55. ' User interaction
  56. DIM ReDraw AS INTEGER
  57.         re = xshift + (_MOUSEX - _WIDTH / 2) / zoom
  58.         im = yshift - (_MOUSEY - _HEIGHT / 2) / zoom
  59.         Calculate re, im, ExhibitName
  60.         'LOCATE 5, 1: PRINT "re: "; INT(re + .5); "      "
  61.         'LOCATE 6, 1: PRINT "im: "; INT(im + .5); "      "
  62.         IF (_MOUSEBUTTON(1)) THEN
  63.             xshift = xshift + (_MOUSEX - _WIDTH / 2) / zoom
  64.             yshift = yshift - (_MOUSEY - _HEIGHT / 2) / zoom
  65.             ReDraw = -1
  66.             DO WHILE _MOUSEINPUT: LOOP
  67.         END IF
  68.         IF (_MOUSEBUTTON(2)) THEN
  69.             zoom = zoom * 1 / 2
  70.             ReDraw = -1
  71.             DO WHILE _MOUSEINPUT: LOOP
  72.         END IF
  73.         IF (_MOUSEBUTTON(3)) THEN
  74.             zoom = zoom * 2
  75.             ReDraw = -1
  76.             DO WHILE _MOUSEINPUT: LOOP
  77.         END IF
  78.     LOOP
  79.     kh = _KEYHIT
  80.     _KEYCLEAR
  81.     IF ((kh = ASC("a")) OR (kh = ASC("A"))) THEN
  82.         ReDraw = 1
  83.     END IF
  84.     IF ((kh = ASC("b")) OR (kh = ASC("B"))) THEN
  85.         ReDraw = -1
  86.     END IF
  87.     IF (kh = ASC("1")) THEN
  88.         PlotOption(1) = PlotOption(1) + .5
  89.         IF ((PlotOption(1) > 1)) THEN PlotOption(1) = 0
  90.         ReDraw = -1
  91.     END IF
  92.     IF (kh = ASC("2")) THEN
  93.         PlotOption(2) = PlotOption(2) + 1
  94.         IF (PlotOption(2) > 4) THEN PlotOption(2) = 1
  95.         ReDraw = -1
  96.     END IF
  97.     IF (kh = ASC("3")) THEN PlotOption(3) = -PlotOption(3): ReDraw = -1
  98.     IF (kh = ASC("4")) THEN PlotOption(4) = -PlotOption(4): ReDraw = -1
  99.     IF (kh = ASC("5")) THEN PlotOption(5) = -PlotOption(5): ReDraw = -1
  100.     IF (kh = ASC("6")) THEN PlotOption(6) = -PlotOption(6): ReDraw = -1
  101.     IF (kh = ASC("7")) THEN PlotOption(7) = -PlotOption(7): ReDraw = -1
  102.     IF (kh = ASC("8")) THEN PlotOption(8) = -PlotOption(8): ReDraw = -1
  103.     IF (kh = ASC("9")) THEN PlotOption(9) = -PlotOption(9): ReDraw = -1
  104.     IF (kh = ASC("0")) THEN PlotOption(10) = -PlotOption(10): ReDraw = -1
  105.     IF ((kh = ASC(" ")) OR (kh = 19712)) THEN
  106.         q = q + 1
  107.         Initialize q, ExhibitName, zoom, xshift, yshift
  108.         ReDraw = -1
  109.     END IF
  110.     IF (kh = 19200) THEN
  111.         q = q - 1
  112.         IF (q = 0) THEN q = 1
  113.         Initialize q, ExhibitName, zoom, xshift, yshift
  114.         ReDraw = -1
  115.     END IF
  116.     IF (kh = 18432) THEN
  117.         PlotOption(0) = PlotOption(0) + 1
  118.         ReDraw = -1
  119.     END IF
  120.     IF (kh = 20480) THEN
  121.         PlotOption(0) = PlotOption(0) - 1
  122.         IF (PlotOption(0) < 0) THEN PlotOption(0) = 0
  123.         ReDraw = -1
  124.     END IF
  125.     IF (ReDraw <> 0) THEN
  126.         CALL DrawPlot(ExhibitName, zoom, xshift, yshift, ReDraw)
  127.         ReDraw = 0
  128.     END IF
  129.  
  130.  
  131.  
  132. SUB Initialize (x AS LONG, ExhibitName AS STRING, zoom AS DOUBLE, xshift AS DOUBLE, yshift AS DOUBLE)
  133.     xshift = 0
  134.     yshift = 0
  135.     zoom = 50 * 2
  136.     SELECT CASE x
  137.         CASE 1
  138.             ExhibitName = "Vanilla"
  139.         CASE 2
  140.             ExhibitName = "Monomial"
  141.         CASE 3
  142.             ExhibitName = "Pole"
  143.         CASE 4
  144.             ExhibitName = "Shifts"
  145.         CASE 5
  146.             ExhibitName = "Geometric Series"
  147.             PlotOption(0) = 5
  148.         CASE 6
  149.             ExhibitName = "Taylor"
  150.             PlotOption(0) = 10
  151.         CASE 7
  152.             ExhibitName = "Exponential"
  153.         CASE 8
  154.             ExhibitName = "Logarithm"
  155.         CASE 9
  156.             ExhibitName = "Sqrt"
  157.         CASE 10
  158.             ExhibitName = "Branch"
  159.         CASE 11
  160.             ExhibitName = "Cosine"
  161.         CASE 12
  162.             ExhibitName = "Sine"
  163.         CASE 13
  164.             ExhibitName = "Gamma"
  165.         CASE 14
  166.             ExhibitName = "Condenser"
  167.         CASE 15
  168.             ExhibitName = "Inductor"
  169.         CASE 16
  170.             ExhibitName = "Mandelbrot"
  171.             xshift = -.5 - .25
  172.             PlotOption(0) = 1
  173.         CASE 17
  174.             ExhibitName = "Julia"
  175.             PlotOption(0) = 8
  176.         CASE 18
  177.             ExhibitName = "CIF1"
  178.             PlotOption(0) = 10
  179.         CASE 19
  180.             ExhibitName = "CIF2"
  181.             PlotOption(0) = 50
  182.         CASE 20
  183.             ExhibitName = "CIF3"
  184.         CASE 21
  185.             ExhibitName = "Canonical Logarithm"
  186.         CASE ELSE
  187.     END SELECT
  188.  
  189. SUB Calculate (x AS DOUBLE, y AS DOUBLE, a AS STRING)
  190.     DIM AS INTEGER j, m, n
  191.     DIM AS DOUBLE re, im, u, v, u0, v0, uu, vv, fu, fv, xx, yy, p, q, t
  192.  
  193.     SELECT CASE a
  194.         CASE "Vanilla"
  195.             re = x
  196.             im = y
  197.  
  198.         CASE "Monomial"
  199.             're = x ^ 2 - y ^ 2
  200.             'im = 2 * x * y
  201.             'cexp re, im, x, y, 2, 0
  202.             cexp re, im, x, y, 3, 0
  203.  
  204.         CASE "Pole"
  205.             'cexp re, im, x, y, -1, 0
  206.             cexp re, im, x, y, -2, 0
  207.  
  208.         CASE "Shifts"
  209.             'cdiv u, v, x + 1, y, x - 1, y
  210.             cdiv u, v, x, y, x - 1, y
  211.             re = u
  212.             im = v
  213.  
  214.         CASE "Geometric Series"
  215.             p = 0
  216.             q = 0
  217.             u = 1
  218.             v = 0
  219.             cadd u0, v0, p, q, u, v
  220.             FOR m = 1 TO PlotOption(0)
  221.                 cexp uu, vv, x, y, m, 0
  222.                 cadd p, q, u0, v0, uu, vv
  223.                 u0 = p
  224.                 v0 = q
  225.             NEXT
  226.             re = u0
  227.             im = v0
  228.  
  229.         CASE "Taylor"
  230.             p = 0
  231.             q = 0
  232.             u = 1
  233.             v = 0
  234.             cadd u0, v0, p, q, u, v
  235.             FOR m = 1 TO PlotOption(0)
  236.                 cexp uu, vv, x, y, m, 0
  237.                 cdiv u, v, uu, vv, facto&(m), 0
  238.                 cadd p, q, u0, v0, u, v
  239.                 u0 = p
  240.                 v0 = q
  241.             NEXT
  242.             re = u0
  243.             im = v0
  244.  
  245.         CASE "Exponential"
  246.             cexp re, im, EXP(1), 0, x, y
  247.  
  248.         CASE "Logarithm"
  249.             clog re, im, x, y
  250.  
  251.         CASE "Sqrt"
  252.             cexp re, im, x, y, 1 / 2, 0
  253.  
  254.         CASE "Branch"
  255.             cdiv p, q, x + 2, y + 1, x - 2, y - 1
  256.             clog re, im, p, q
  257.  
  258.         CASE "Cosine"
  259.             cosz re, im, x, y
  260.  
  261.         CASE "Sine"
  262.             sinz re, im, x, y
  263.  
  264.         CASE "Gamma"
  265.             ' Is this right?
  266.             uu = x - y
  267.             vv = x + y
  268.             cgamma uu, vv, x, y
  269.             re = uu
  270.             im = vv
  271.  
  272.         CASE "Condenser"
  273.             re = 1
  274.             im = 0
  275.             FOR j = 0 TO 7
  276.                 cmul u, v, 1, 0, -0.1 * (j - 3.5), 0
  277.                 cmul re, im, re, im, x - u, y - v - 0.1
  278.                 cdiv re, im, re, im, x - u, y - v + 0.1
  279.             NEXT
  280.  
  281.         CASE "Inductor"
  282.             re = 1
  283.             im = 0
  284.             FOR j = 0 TO 5
  285.                 cmul u, v, 1, 0, 0, -0.18 * (j - 2.5)
  286.                 cmul re, im, re, im, x - u - 0.2, y - v
  287.                 cdiv re, im, re, im, x - u + 0.2, y - v + 0.1
  288.             NEXT
  289.  
  290.         CASE "Mandelbrot"
  291.             u = x
  292.             v = y
  293.             FOR m = 0 TO PlotOption(0) '2 '5 '00
  294.                 u0 = u
  295.                 v0 = v
  296.                 u = u0 ^ 2 - v0 ^ 2 + x
  297.                 v = 2 * u0 * v0 + y
  298.             NEXT
  299.             re = u
  300.             im = v
  301.  
  302.         CASE "Julia"
  303.             u = x
  304.             v = y
  305.             FOR m = 0 TO PlotOption(0)
  306.                 u0 = u
  307.                 v0 = v
  308.                 u = u0 ^ 2 - v0 ^ 2 + 0.35
  309.                 v = 2 * u0 * v0 + 0 '0.5
  310.             NEXT
  311.             re = u
  312.             im = v
  313.  
  314.         CASE "CIF1"
  315.             ' Riemann sum resolution
  316.             n = PlotOption(0) '25
  317.             xx = 0
  318.             yy = 0
  319.  
  320.             FOR j = 0 TO n - 1
  321.  
  322.                 ' Integration contour
  323.                 ' 1:
  324.                 'u = 3 * (2 * COS(j * 2 * pi / n))
  325.                 'v = 3 * (2 * SIN(j * 2 * pi / n))
  326.                 ' 2:
  327.                 u = 4 * (2 * COS(j * 2 * pi / n))
  328.                 v = 4 * (2 * SIN(j * 2 * pi / n) * COS(j * 2 * pi / n))
  329.  
  330.                 ' f(z)
  331.                 fu = u - v 'u ^ 2 - v ^ 2
  332.                 fv = u + v '2 * u * v
  333.  
  334.                 ' f(z) / (z - z_0)
  335.                 cdiv uu, vv, fu, fv, u - x, v - y
  336.  
  337.                 ' z'(t) = derivative of integration contour
  338.                 ' 1:
  339.                 'cmul re, im, uu, vv, 3 * (-2 * SIN(j * 2 * pi / n)), 3 * (2 * COS(j * 2 * pi / n))
  340.                 ' 2:
  341.                 cmul re, im, uu, vv, 4 * (-2 * SIN(j * 2 * pi / n)), 4 * (2 * COS(j * 4 * pi / n))
  342.  
  343.                 ' Integral height calculation
  344.                 IF ((j = 0) OR (j = n - 1)) THEN
  345.                     xx = xx + 0.5 * re
  346.                     yy = yy + 0.5 * im
  347.                 ELSE
  348.                     xx = xx + re
  349.                     yy = yy + im
  350.                 END IF
  351.             NEXT
  352.  
  353.             ' Integral base calculation
  354.             xx = xx * 2 * pi / n
  355.             yy = yy * 2 * pi / n
  356.  
  357.             ' Rescale by 1/(2*pi*i)
  358.             cmul re, im, xx, yy, 0, -1 / (2 * pi)
  359.  
  360.         CASE "CIF2"
  361.             ' Riemann sum resolution
  362.             n = PlotOption(0) '10
  363.             xx = 0
  364.             yy = 0
  365.  
  366.             DIM xr AS DOUBLE
  367.             DIM xi AS DOUBLE
  368.             xr = 2.0
  369.             xi = 0.0
  370.  
  371.             FOR j = 0 TO n - 1
  372.  
  373.                 ' Integration contour
  374.                 u = 3 * 3 * COS(j * 2 * pi / n)
  375.                 v = 3 * 2 * SIN(j * 2 * pi / n)
  376.  
  377.                 ' f(z)
  378.                 sinz fu, fv, u, v
  379.  
  380.                 ' f(z) / (z - z_0)^(xr + i xi)
  381.                 p = u - x
  382.                 q = v - y
  383.                 cexp p, q, p, q, xr, xi
  384.                 cdiv uu, vv, fu, fv, p, q
  385.  
  386.                 ' z'(t) = derivative of integration contour
  387.                 cmul re, im, uu, vv, 3 * -3 * SIN(j * 2 * pi / n), 2 * COS(j * 2 * pi / n)
  388.  
  389.                 ' Integral height calculation
  390.                 IF ((j = 0) OR (j = n - 1)) THEN
  391.                     xx = xx + 0.5 * re
  392.                     yy = yy + 0.5 * im
  393.                 ELSE
  394.                     xx = xx + re
  395.                     yy = yy + im
  396.                 END IF
  397.             NEXT
  398.  
  399.             ' Integral base calculation
  400.             xx = xx * 2 * pi / n
  401.             yy = yy * 2 * pi / n
  402.  
  403.             ' rescale by Gamma(xr + i ri)/(2*pi*i)
  404.             cgamma u, v, xr + 1, xi
  405.             cmul re, im, xx, yy, u, v
  406.             cmul re, im, re, im, 0, -1 / (2 * pi)
  407.  
  408.         CASE "CIF3"
  409.             xx = 0
  410.             yy = 0
  411.             FOR t = 0 TO 3 STEP 0.1
  412.                 uu = t * COS(5 * t)
  413.                 vv = t * SIN(5 * t)
  414.                 cexp p, q, EXP(1), 0, uu, vv
  415.                 cdiv u0, v0, p, q, uu - x, vv - y
  416.                 cmul p, q, u0, v0, COS(5 * t) - 5 * t * SIN(5 * t), SIN(5 * t) + 5 * t * COS(5 * t)
  417.                 IF ((t = 0) OR (t = 3)) THEN
  418.                     xx = xx + 0.5 * p
  419.                     yy = yy + 0.5 * q
  420.                 ELSE
  421.                     xx = xx + 1 * p
  422.                     yy = yy + 1 * q
  423.                 END IF
  424.             NEXT
  425.             xx = xx * 0.01
  426.             yy = yy * 0.01
  427.             cmul re, im, xx, yy, 0, -1 / (2 * pi)
  428.  
  429.         CASE "Canonical Logarithm"
  430.             DIM AS DOUBLE a0, k0, sx0, sy0, tx0, ty0
  431.             a0 = .5
  432.             k0 = 0.09
  433.             sx0 = 2
  434.             sy0 = 1
  435.             tx0 = a0 * EXP(k0 * 16) * COS(16) + sx0
  436.             ty0 = a0 * EXP(k0 * 16) * SIN(16) + sy0
  437.             re = 0
  438.             im = 0
  439.             FOR t = 0 TO 16 STEP .1
  440.                 p = a0 * EXP(k0 * t) * COS(t) + sx0 - tx0
  441.                 q = a0 * EXP(k0 * t) * SIN(t) + sy0 - ty0
  442.                 cdiv uu, vv, 1, 0, p - x, q - y
  443.                 cmul xx, yy, uu, vv, a0 * EXP(k0 * t) * (k0 * COS(t) - SIN(t)), a0 * EXP(k0 * t) * (k0 * SIN(t) + COS(t))
  444.                 re = re + xx
  445.                 im = im + yy
  446.             NEXT
  447.             FOR t = 16 - .1 TO 0 STEP -.1
  448.                 p = -a0 * EXP(k0 * t) * COS(t) - sx0 + tx0
  449.                 q = -a0 * EXP(k0 * t) * SIN(t) - sy0 + ty0
  450.                 cdiv uu, vv, 1, 0, p - x, q - y
  451.                 cmul xx, yy, uu, vv, a0 * EXP(k0 * t) * (k0 * COS(t) - SIN(t)), a0 * EXP(k0 * t) * (k0 * SIN(t) + COS(t))
  452.                 re = re + xx
  453.                 im = im + yy
  454.             NEXT
  455.             re = re * 0.1
  456.             im = im * 0.1
  457.             cmul uu, vv, re, im, 0, -1 / (2 * pi)
  458.             re = uu
  459.             im = vv
  460.  
  461.         CASE ELSE
  462.     END SELECT
  463.  
  464.     x = re
  465.     y = im
  466.  
  467. SUB ShadePixel (red AS DOUBLE, grn AS DOUBLE, blu AS DOUBLE, alf AS DOUBLE, re AS DOUBLE, im AS DOUBLE, zoom AS DOUBLE)
  468.     DIM AS _UNSIGNED LONG c0, c1, c2
  469.     DIM AS DOUBLE r, a, h, s, k
  470.  
  471.     r = SQR(re * re + im * im)
  472.  
  473.     ' Color scheme 0
  474.     a = (pi + _ATAN2(im, -re)) / (2 * pi)
  475.     c1~& = hrgb~&(a, r)
  476.  
  477.     ' Color scheme 1
  478.     a = _ATAN2(im, -re) * .99999
  479.     h = 180 + a * 180 / pi
  480.     SELECT CASE PlotOption(2)
  481.         CASE 1
  482.             k = 50 * r
  483.         CASE 2
  484.             k = 50 * LOG(1 + r * zoom)
  485.         CASE 3
  486.             k = 50 * LOG(1 + r) * (1 + r)
  487.         CASE 4
  488.             k = 50 * r / zoom
  489.         CASE ELSE
  490.             'IF (r < 1) THEN
  491.             'ELSE
  492.             'END IF
  493.     END SELECT
  494.     s = 50 + ((k * 1) MOD 50)
  495.     c2~& = HSVtoRGB~&(h, s, 100)
  496.  
  497.     ' Weighted average of color schemes
  498.     c0~& = ShadeBlend(PlotOption(1), c1~&, c2~&)
  499.     c0~& = SetAlpha(c0~&, 255)
  500.  
  501.     'IF ((re > 0) AND (im > 0)) THEN
  502.  
  503.     ' Origin
  504.     IF (PlotOption(3) = 1) THEN c0~& = ShadeOrigin(c0~&, re, im, 0.075, 100)
  505.  
  506.     ' Axes
  507.     IF (PlotOption(4) = 1) THEN c0~& = ShadeAxes(c0~&, re, im, 0.075, 100)
  508.  
  509.     ' Integers
  510.     IF (PlotOption(5) = 1) THEN c0~& = ShadeIntegers(c0~&, re, im, 0.075, 100)
  511.  
  512.     'END IF
  513.  
  514.     ' Contours
  515.     IF (PlotOption(6) = 1) THEN c0~& = ShadeContours(c0~&, k, 50, 2, 100)
  516.  
  517.     ' Greyscale
  518.     IF (PlotOption(7) = 1) THEN c0~& = ShadeGreyscale(c0~&)
  519.  
  520.     ' Stencil
  521.     IF (PlotOption(8) = 1) THEN c0~& = ShadeStencil(c0~&, 100)
  522.  
  523.     ' Invert
  524.     IF (PlotOption(9) = 1) THEN c0~& = ShadeInvert(c0~&)
  525.  
  526.     ' Bolden
  527.     IF (PlotOption(0) = 1) THEN c0~& = ShadeBolden(c0~&, .8)
  528.  
  529.     red = _RED32(c0~&)
  530.     grn = _GREEN32(c0~&)
  531.     blu = _BLUE32(c0~&)
  532.     alf = _ALPHA32(c0~&)
  533.  
  534. SUB DrawPlot (TheExhibit AS STRING, zoom AS DOUBLE, xshift AS DOUBLE, yshift AS DOUBLE, AAtoggle AS INTEGER)
  535.     DIM AS DOUBLE j, k, x0, y0, re, im, red, grn, blu, alf, nr, ng, nb, na, d, f, jj, kk
  536.     DIM AS DOUBLE r(99), g(99), b(99), a(99), w(99)
  537.     DIM AS INTEGER ii
  538.  
  539.     CLS
  540.     _TITLE TheExhibit
  541.     FOR j = 0 TO _WIDTH
  542.         FOR k = 0 TO _HEIGHT
  543.  
  544.             IF (AAtoggle = -1) THEN
  545.                 x0 = (j) - _WIDTH / 2
  546.                 y0 = -(k) + _HEIGHT / 2
  547.                 re = x0 / zoom + xshift
  548.                 im = y0 / zoom + yshift
  549.                 Calculate re, im, TheExhibit
  550.                 ShadePixel red, grn, blu, alf, re, im, zoom
  551.  
  552.             ELSE
  553.                 f = 2
  554.                 d = .25
  555.                 ii = 0
  556.                 FOR jj = j - f * d TO j + f * d STEP d
  557.                     FOR kk = k - f * d TO k + f * d STEP d
  558.                         ii = ii + 1
  559.                         x0 = (jj - d) - _WIDTH / 2
  560.                         y0 = -(kk - d) + _HEIGHT / 2
  561.                         re = x0 / zoom + xshift
  562.                         im = y0 / zoom + yshift
  563.                         Calculate re, im, TheExhibit
  564.                         ShadePixel red, grn, blu, alf, re, im, zoom
  565.                         r(ii) = red
  566.                         g(ii) = grn
  567.                         b(ii) = blu
  568.                         a(ii) = alf
  569.                         w(ii) = EXP(-1 * ((j - jj) ^ 2 + (k - kk) ^ 2))
  570.                     NEXT
  571.                 NEXT
  572.                 red = 0
  573.                 grn = 0
  574.                 blu = 0
  575.                 alf = 0
  576.                 nr = 0
  577.                 ng = 0
  578.                 nb = 0
  579.                 na = 0
  580.                 FOR jj = 1 TO ii
  581.                     red = red + r(jj) * w(ii)
  582.                     grn = grn + g(jj) * w(ii)
  583.                     blu = blu + b(jj) * w(ii)
  584.                     alf = alf + a(jj) * w(ii)
  585.                     nr = nr + w(ii)
  586.                     ng = ng + w(ii)
  587.                     nb = nb + w(ii)
  588.                     na = na + w(ii)
  589.                 NEXT
  590.                 red = red / nr
  591.                 grn = grn / ng
  592.                 blu = blu / nb
  593.                 alf = alf / na
  594.             END IF
  595.  
  596.             CALL CPset(x0, y0, _RGBA(red, grn, blu, alf))
  597.  
  598.         NEXT
  599.     NEXT
  600.  
  601.     'COLOR _RGB32(255, 255, 255, 255)
  602.     'LOCATE 1, 1: PRINT TheExhibit
  603.     'LOCATE 2, 1: PRINT "zoom: "; zoom
  604.     'LOCATE 3, 1: PRINT "xshift: "; xshift
  605.     'LOCATE 4, 1: PRINT "yshift: "; yshift
  606.  
  607. FUNCTION ShadeBlend~& (f AS DOUBLE, x AS _UNSIGNED LONG, y AS _UNSIGNED LONG)
  608.     DIM AS DOUBLE red, grn, blu, alf
  609.     red = (1 - f) * (_RED32(x)) + f * (_RED32(y))
  610.     grn = (1 - f) * (_GREEN32(x)) + f * (_GREEN32(y))
  611.     blu = (1 - f) * (_BLUE32(x)) + f * (_BLUE32(y))
  612.     alf = (1 - f) * (_ALPHA32(x)) + f * (_ALPHA32(y))
  613.     ShadeBlend~& = _RGB32(red, grn, blu, alf)
  614.  
  615. FUNCTION SetAlpha~& (x AS _UNSIGNED LONG, y AS DOUBLE)
  616.     SetAlpha~& = _RGB32(_RED32(x), _GREEN32(x), _BLUE32(x), y)
  617.  
  618. FUNCTION ShadeContours~& (c AS _UNSIGNED LONG, k AS DOUBLE, x AS DOUBLE, y AS DOUBLE, a AS DOUBLE)
  619.     IF (((k MOD x) < y) OR ((k MOD x) > (x - y))) THEN c = SetAlpha(c, a)
  620.     ShadeContours~& = c
  621.  
  622. FUNCTION ShadeIntegers~& (c AS _UNSIGNED LONG, x AS DOUBLE, y AS DOUBLE, z AS DOUBLE, a AS DOUBLE)
  623.     IF (((x - INT(x)) < z) AND (INT(x) <> 0)) THEN c = SetAlpha(c, a)
  624.     IF (((y - INT(y)) < z) AND (INT(y) <> 0)) THEN c = SetAlpha(c, a)
  625.     IF (((INT(x) + 1 - x) < z) AND ((INT(x) + 1) <> 0)) THEN c = SetAlpha(c, a)
  626.     IF (((INT(y) + 1 - y) < z) AND ((INT(y) + 1) <> 0)) THEN c = SetAlpha(c, a)
  627.     ShadeIntegers~& = c
  628.  
  629. FUNCTION ShadeAxes~& (c AS _UNSIGNED LONG, x AS DOUBLE, y AS DOUBLE, z AS DOUBLE, a AS DOUBLE)
  630.     IF SQR(x * x + y * y) > 1 THEN
  631.         IF (((x - INT(x)) < z) AND (INT(x) = 0)) THEN c = SetAlpha(c, a)
  632.         IF (((y - INT(y)) < z) AND (INT(y) = 0)) THEN c = SetAlpha(c, a)
  633.         IF (((INT(x) + 1 - x) < z) AND ((INT(x) + 1) = 0)) THEN c = SetAlpha(c, a)
  634.         IF (((INT(y) + 1 - y) < z) AND ((INT(y) + 1) = 0)) THEN c = SetAlpha(c, a)
  635.     END IF
  636.     ShadeAxes~& = c
  637.  
  638. FUNCTION ShadeOrigin~& (c AS _UNSIGNED LONG, x AS DOUBLE, y AS DOUBLE, z AS DOUBLE, a AS DOUBLE)
  639.     IF SQR(x * x + y * y) <= 1 THEN
  640.         IF (((x - INT(x)) < z) AND (INT(x) = 0)) THEN c = SetAlpha(c, a)
  641.         IF (((y - INT(y)) < z) AND (INT(y) = 0)) THEN c = SetAlpha(c, a)
  642.         IF (((INT(x) + 1 - x) < z) AND ((INT(x) + 1) = 0)) THEN c = SetAlpha(c, a)
  643.         IF (((INT(y) + 1 - y) < z) AND ((INT(y) + 1) = 0)) THEN c = SetAlpha(c, a)
  644.     END IF
  645.     ShadeOrigin~& = c
  646.  
  647. FUNCTION ShadeGreyscale~& (x AS _UNSIGNED LONG)
  648.     DIM AS DOUBLE a
  649.     a = 255 - (1 / 3) * (_RED32(x) + _GREEN32(x) + _BLUE32(x))
  650.     ShadeGreyscale~& = _RGB32(a, a, a, _ALPHA32(x))
  651.  
  652. FUNCTION ShadeStencil~& (x AS _UNSIGNED LONG, t AS DOUBLE)
  653.     DIM AS DOUBLE red, grn, blu
  654.     IF (_ALPHA32(x) <> t) THEN
  655.         red = 0
  656.         grn = 0
  657.         blu = 0
  658.     ELSE
  659.         red = _RED32(x)
  660.         grn = _GREEN32(x)
  661.         blu = _BLUE32(x)
  662.     END IF
  663.     ShadeStencil~& = _RGB32(red, grn, blu, 255)
  664.  
  665. FUNCTION ShadeInvert~& (x AS _UNSIGNED LONG)
  666.     ShadeInvert~& = _RGB32(255 - _RED32(x), 255 - _GREEN32(x), 255 - _BLUE32(x), _ALPHA32(x))
  667.  
  668. FUNCTION ShadeBolden~& (x AS _UNSIGNED LONG, t AS DOUBLE)
  669.     DIM AS DOUBLE red, grn, blu
  670.     red = _RED32(x)
  671.     grn = _GREEN32(x)
  672.     blu = _BLUE32(x)
  673.     IF ((red + grn + blu) < (3 * 255)) THEN
  674.         red = red * t
  675.         grn = grn * t
  676.         blu = blu * t
  677.     END IF
  678.     ShadeBolden~& = _RGB32(red, grn, blu, _ALPHA32(x))
  679.  
  680. FUNCTION HSVtoRGB~& (h AS DOUBLE, s AS DOUBLE, v AS DOUBLE)
  681.     DIM AS DOUBLE c, x, m, r, g, b
  682.     IF ((h > 360) OR (h < 0) OR (s > 100) OR (s < 0) OR (v > 100) OR (v < 0)) THEN
  683.         PRINT "Out of range:"; h; s; v
  684.     END IF
  685.     s = s / 100
  686.     v = v / 100
  687.     c = s * v
  688.     x = c * (1 - ABS(fmod(h / 60, 2) - 1))
  689.     m = v - c
  690.     IF ((h >= 0) AND (h < 60)) THEN
  691.         r = c
  692.         g = x
  693.         b = 0
  694.     END IF
  695.     IF ((h >= 60) AND (h < 120)) THEN
  696.         r = x
  697.         g = c
  698.         b = 0
  699.     END IF
  700.     IF ((h >= 120) AND (h < 180)) THEN
  701.         r = 0
  702.         g = c
  703.         b = x
  704.     END IF
  705.     IF ((h >= 180) AND (h < 240)) THEN
  706.         r = 0
  707.         g = x
  708.         b = c
  709.     END IF
  710.     IF ((h >= 240) AND (h < 300)) THEN
  711.         r = x
  712.         g = 0
  713.         b = c
  714.     END IF
  715.     IF ((h >= 300) AND (h < 360)) THEN
  716.         r = c
  717.         g = 0
  718.         b = x
  719.     END IF
  720.     r = (r + m) * 255
  721.     g = (g + m) * 255
  722.     b = (b + m) * 255
  723.     HSVtoRGB~& = _RGB32(r, g, b)
  724.  
  725. FUNCTION fmod## (numer AS DOUBLE, denom AS DOUBLE)
  726.     fmod## = numer - INT(numer / denom) * denom
  727.  
  728. ' a vince original, slightly modified
  729. FUNCTION hrgb~& (h AS DOUBLE, m AS DOUBLE)
  730.     DIM n AS LONG
  731.     DIM AS DOUBLE r, g, b, mm, p, rr, gg, bb
  732.     r = 0.5 - 0.5 * SIN(2 * pi * h - pi / 2)
  733.     g = (0.5 + 0.5 * SIN(2 * pi * h * 1.5 - pi / 2)) * -(h < 0.66)
  734.     b = (0.5 + 0.5 * SIN(2 * pi * h * 1.5 + pi / 2)) * -(h > 0.33)
  735.     mm = 0 * (m * 500 MOD 500)
  736.     n = 16
  737.     p = ABS((h * n) - INT(h * n))
  738.     rr = 255 * r - 0.15 * mm - 35 * p
  739.     gg = 255 * g - 0.15 * mm - 35 * p
  740.     bb = 255 * b - 0.15 * mm - 35 * p
  741.     IF (rr < 0) THEN rr = 0
  742.     IF (gg < 0) THEN gg = 0
  743.     IF (bb < 0) THEN bb = 0
  744.     hrgb~& = _RGB(rr, gg, bb)
  745.  
  746. SUB CPset (x0 AS DOUBLE, y0 AS DOUBLE, shade AS _UNSIGNED LONG)
  747.     PSET (_WIDTH / 2 + x0, -y0 + _HEIGHT / 2), shade
  748.  
  749. 'SUB circlef (x AS LONG, y AS LONG, r AS LONG, c AS LONG)
  750. '    DIM AS LONG xx, yy, e
  751. '    xx = r
  752. '    yy = 0
  753. '    e = -r
  754. '    DO WHILE (yy < xx)
  755. '        IF (e <= 0) THEN
  756. '            yy = yy + 1
  757. '            LINE (x - xx, y + yy)-(x + xx, y + yy), c, BF
  758. '            LINE (x - xx, y - yy)-(x + xx, y - yy), c, BF
  759. '            e = e + 2 * yy
  760. '        ELSE
  761. '            LINE (x - yy, y - xx)-(x + yy, y - xx), c, BF
  762. '            LINE (x - yy, y + xx)-(x + yy, y + xx), c, BF
  763. '            xx = xx - 1
  764. '            e = e - 2 * xx
  765. '        END IF
  766. '    LOOP
  767. '    LINE (x - r, y)-(x + r, y), c, BF
  768. 'END SUB
  769.  
  770. SUB cadd (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE, aa AS DOUBLE, bb AS DOUBLE)
  771.     DIM AS DOUBLE x, y, a, b
  772.     x = xx
  773.     y = yy
  774.     a = aa
  775.     b = bb
  776.     u = x + a
  777.     v = y + b
  778.  
  779. SUB cmul (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE, aa AS DOUBLE, bb AS DOUBLE)
  780.     DIM AS DOUBLE x, y, a, b
  781.     x = xx
  782.     y = yy
  783.     a = aa
  784.     b = bb
  785.     u = x * a - y * b
  786.     v = x * b + y * a
  787.  
  788. SUB cdiv (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE, aa AS DOUBLE, bb AS DOUBLE)
  789.     DIM AS DOUBLE x, y, a, b, d
  790.     x = xx
  791.     y = yy
  792.     a = aa
  793.     b = bb
  794.     d = a * a + b * b
  795.     u = (x * a + y * b) / d
  796.     v = (y * a - x * b) / d
  797.  
  798. SUB cexp (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE, aa AS DOUBLE, bb AS DOUBLE)
  799.     DIM AS DOUBLE x, y, a, b, lnz, argz, mag, ang
  800.     x = xx
  801.     y = yy
  802.     a = aa
  803.     b = bb
  804.     lnz = x * x + y * y
  805.     IF (lnz = 0) THEN
  806.         u = 0
  807.         v = 0
  808.     ELSE
  809.         lnz = 0.5 * LOG(lnz)
  810.         argz = _ATAN2(y, x)
  811.         mag = EXP(a * lnz - b * argz)
  812.         ang = a * argz + b * lnz
  813.         u = mag * COS(ang)
  814.         v = mag * SIN(ang)
  815.     END IF
  816.  
  817. SUB clog (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE)
  818.     DIM AS DOUBLE x, y, lnz, argz
  819.     x = xx
  820.     y = yy
  821.     lnz = x * x + y * y
  822.     IF (lnz = 0) THEN
  823.         u = 0
  824.         v = 0
  825.     ELSE
  826.         lnz = 0.5 * LOG(lnz)
  827.         argz = _ATAN2(y, x)
  828.         u = lnz
  829.         v = argz
  830.     END IF
  831.  
  832. FUNCTION cosh## (x AS DOUBLE)
  833.     cosh## = 0.5## * (EXP(x) + EXP(-x))
  834.  
  835. FUNCTION sinh## (x AS DOUBLE)
  836.     sinh## = 0.5## * (EXP(x) - EXP(-x))
  837.  
  838. SUB sinz (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE)
  839.     DIM AS DOUBLE x, y
  840.     x = xx
  841.     y = yy
  842.     u = SIN(x) * cosh(y)
  843.     v = COS(x) * sinh(y)
  844.  
  845. SUB cosz (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE)
  846.     DIM AS DOUBLE x, y
  847.     x = xx
  848.     y = yy
  849.     u = COS(x) * cosh(y)
  850.     v = -SIN(x) * sinh(y)
  851.  
  852. FUNCTION rgamma## (x)
  853.     rgamma = SQR(2 * pi * x) * ((x / EXP(1)) ^ x)
  854.  
  855. SUB cgamma (u AS DOUBLE, v AS DOUBLE, xx AS DOUBLE, yy AS DOUBLE)
  856.     DIM AS DOUBLE x, y, uu, vv, p, q
  857.     x = xx
  858.     y = yy
  859.     IF x = 0 AND y = 0 THEN
  860.         u = 1
  861.         v = 0
  862.     ELSE
  863.         cexp uu, vv, x, y, x - 0.5, y
  864.         cexp p, q, EXP(1), 0, -x, -y
  865.         cmul u, v, uu, vv, p, q
  866.         u = u * SQR(2 * pi)
  867.         v = v * SQR(2 * pi)
  868.     END IF
  869.  
  870. FUNCTION facto& (x AS LONG)
  871.     IF (x = 1) THEN facto& = 1
  872.     IF (x > 1) THEN facto& = x * facto&(x - 1)
  873.  

 
thing19081008.png

 
2222.png

 
fdsafdsfdsfdsf.png


6
Programs / Scalar Field
« on: February 14, 2022, 08:13:41 am »
Code: QB64: [Select]
  1.  
  2. _TITLE "Scalar Field"
  3.  
  4. SCREEN _NEWIMAGE(800, 600, 32)
  5.  
  6. TYPE Vector
  7.     x AS DOUBLE
  8.     y AS DOUBLE
  9.  
  10. DIM SHARED Position(10) AS Vector
  11. DIM SHARED Velocity(10) AS Vector
  12. DIM AS DOUBLE f, f1, f3, f7, f9, g
  13.  
  14. FOR j = 1 TO UBOUND(Position)
  15.     Position(j).x = _WIDTH * (RND - .5)
  16.     Position(j).y = _HEIGHT * (RND - .5)
  17.     Velocity(j).x = 5 * (RND - .5)
  18.     Velocity(j).y = 5 * (RND - .5)
  19.  
  20.     CLS
  21.  
  22.     FOR j = 1 TO UBOUND(Position)
  23.         Position(j).x = Position(j).x + Velocity(j).x
  24.         Position(j).y = Position(j).y + Velocity(j).y
  25.         IF (Position(j).x < -_WIDTH / 2) THEN Velocity(j).x = -Velocity(j).x
  26.         IF (Position(j).x > _WIDTH / 2) THEN Velocity(j).x = -Velocity(j).x
  27.         IF (Position(j).y < -_HEIGHT / 2) THEN Velocity(j).y = -Velocity(j).y
  28.         IF (Position(j).y > _HEIGHT / 2) THEN Velocity(j).y = -Velocity(j).y
  29.     NEXT
  30.  
  31.     FOR j = -_WIDTH / 2 TO _WIDTH / 2 STEP 10
  32.         FOR k = -_HEIGHT / 2 TO _HEIGHT / 2 STEP 10
  33.             f = 15 * CalcPotential#(j, k)
  34.             CALL CCircle(j, k, 4, _RGB(255 * f, 255 * f / 2, 255 * f / 4))
  35.             'NEXT
  36.             'NEXT
  37.  
  38.             'FOR j = -_WIDTH / 2 TO _WIDTH / 2 STEP 10
  39.             'FOR k = -_HEIGHT / 2 TO _HEIGHT / 2 STEP 10
  40.             f1 = 10 * CalcPotential#(j - 5, k - 5)
  41.             f3 = 10 * CalcPotential#(j + 5, k - 5)
  42.             f7 = 10 * CalcPotential#(j - 5, k + 5)
  43.             f9 = 10 * CalcPotential#(j + 5, k + 5)
  44.             FOR g = .15 TO .65 STEP .1
  45.                 f = .5
  46.                 IF (f1 > g) AND (f3 > g) AND (f7 > g) AND (f9 > g) THEN f = 1
  47.                 IF (f1 < g) AND (f3 < g) AND (f7 < g) AND (f9 < g) THEN f = 0
  48.                 IF (f = .5) THEN
  49.                     IF (f1 < g) AND (f3 < g) AND (f7 > g) AND (f9 > g) THEN CALL CLine(j - 5, k, j + 5, k, _RGB(255, 255, 255 / 2))
  50.                     IF (f1 > g) AND (f3 > g) AND (f7 < g) AND (f9 < g) THEN CALL CLine(j - 5, k, j + 5, k, _RGB(255, 255, 255 / 2))
  51.                     IF (f1 > g) AND (f3 < g) AND (f7 > g) AND (f9 < g) THEN CALL CLine(j, k - 5, j, k + 5, _RGB(255, 255, 255 / 2))
  52.                     IF (f1 < g) AND (f3 > g) AND (f7 < g) AND (f9 > g) THEN CALL CLine(j, k - 5, j, k + 5, _RGB(255, 255, 255 / 2))
  53.                     IF (f1 > g) AND (f3 < g) AND (f7 < g) AND (f9 < g) THEN CALL CLine(j - 5, k, j, k - 5, _RGB(255, 255, 255 / 2))
  54.                     IF (f1 < g) AND (f3 > g) AND (f7 < g) AND (f9 < g) THEN CALL CLine(j, k - 5, j + 5, k, _RGB(255, 255, 255 / 2))
  55.                     IF (f1 < g) AND (f3 < g) AND (f7 > g) AND (f9 < g) THEN CALL CLine(j - 5, k, j, k + 5, _RGB(255, 255, 255 / 2))
  56.                     IF (f1 < g) AND (f3 < g) AND (f7 < g) AND (f9 > g) THEN CALL CLine(j, k + 5, j + 5, k, _RGB(255, 255, 255 / 2))
  57.                 END IF
  58.             NEXT
  59.         NEXT
  60.     NEXT
  61.  
  62.     _DISPLAY
  63.     _LIMIT 60
  64.  
  65.  
  66. FUNCTION CalcPotential# (x0 AS DOUBLE, y0 AS DOUBLE)
  67.     DIM TheReturn AS DOUBLE
  68.     DIM AS INTEGER j
  69.     DIM AS DOUBLE dx, dy, r
  70.     TheReturn = 0
  71.     FOR j = 1 TO UBOUND(Position)
  72.         dx = x0 - Position(j).x
  73.         dy = y0 - Position(j).y
  74.         r = SQR(dx * dx + dy * dy)
  75.         TheReturn = TheReturn + 1 / r
  76.     NEXT
  77.     CalcPotential# = TheReturn
  78.  
  79. SUB CCircle (x0 AS DOUBLE, y0 AS DOUBLE, rad AS DOUBLE, shade AS _UNSIGNED LONG)
  80.     CIRCLE (_WIDTH / 2 + x0, -y0 + _HEIGHT / 2), rad, shade
  81.  
  82. SUB CLine (x0 AS DOUBLE, y0 AS DOUBLE, x1 AS DOUBLE, y1 AS DOUBLE, shade AS _UNSIGNED LONG)
  83.     LINE (_WIDTH / 2 + x0, -y0 + _HEIGHT / 2)-(_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), shade
  84.  

7
Programs / Draw any curve using only circles
« on: February 14, 2022, 08:07:36 am »
REDACTED

8
Programs / Combinator Calculator: The purest math you'll ever see
« on: January 09, 2022, 11:55:17 pm »
Alright, this post will mostly appeal to the theory-heads out there, but maybe there's some unforseen value in making a general-audience post about this, so here we go.

Today the Science Department of QB64 brings your attention to the oldest, most powerful model of computing ever conceived. Before Turing machines, before lambda calculus - in December 1920, the world was alerted to the S and K combinators. These are abstract functions that you can implement very easily on a computer or another device to make that device become a computer. Here are the functions:

Code: [Select]
s[x][y][z] = x[z][y[z]]
k[x][y] = x

... and that's it. The entirety of computing is in those two functions. All data, all algorithms. Everything you've ever written or will write, whether it be code or it be mathematics, can be compiled to/from those S and K combinators as such. One paper I came across said something like "S and K combinators are the machine language of mathematics". I totally jive with this statement. I got so into this actually, that I had to implement this language in QB64. I'll 'splain you it all.

But first, quiz time. You fall into one of three categories right now:

1)
If you're lost or mostly uninterested, forget about whatever you just read and check out the calculator I made. It does plus, times, and exponents, but only on the integers. Code at the bottom!

2)
If you want to know what's going on so far, and want to hear it *from me*, then I wrote all about this (in Notepad with no spell check and in a hurry, and I still need to add images):
http://barnes.x10host.com/pages/Function-Officium/Function-Officium-One.php
http://barnes.x10host.com/pages/Function-Officium/Function-Officium-Two.php

3)
If you want it straight from the horse's mouth, I suggest you start with this:
https://people.cs.uchicago.edu/~odonnell/Teacher/Lectures/Formal_Organization_of_Knowledge/Examples/combinator_calculus/
https://writings.stephenwolfram.com/2020/12/combinators-a-centennial-view/

To play with this, have it crank out some math for you. You can thumb through the examples in the code I commented out - they will make more sense if read alongside my online notes.

Code: QB64: [Select]
  1.  
  2.  
  3.     _KEYCLEAR
  4.     INPUT "Enter first integer: ", a
  5.     INPUT "Enter second integer: ", b
  6.     c = -1
  7.     DO WHILE ((c < 1) OR (c > 3))
  8.         INPUT "Enter operation. 1 for add, 2 for multiply, 3 for exponent: ", c
  9.     LOOP
  10.     PRINT
  11.  
  12.     SELECT CASE c
  13.         CASE 1
  14.             d = "+"
  15.             e = "s[k[s]][s[k[s[k[s]]]][s[k[k]]]]"
  16.         CASE 2
  17.             d = "*"
  18.             e = "s[k[s]][k]"
  19.         CASE 3
  20.             d = "^"
  21.             e = "s[k[s[s[k][k]]]][k]"
  22.     END SELECT
  23.  
  24.     PRINT "You entered:"
  25.     PRINT a; d; b
  26.     PRINT
  27.     PRINT "Translation of problem: "
  28.     PRINT NumberPrefix$(a); e; NumberPrefix$(b)
  29.     PRINT
  30.     PRINT "Press any key to compute..."
  31.     SLEEP
  32.  
  33.     SELECT CASE c
  34.         CASE 1
  35.             PRINT InterpretInteger&(EvalLoop$(SumPrefix$(a, b) + "[s][k]"))
  36.             PRINT "Result:"; a; d; b; "="; a + b
  37.         CASE 2
  38.             PRINT InterpretInteger&(EvalLoop$(ProductPrefix$(a, b) + "[s][k]"))
  39.             PRINT "Result:"; a; d; b; "="; a * b
  40.         CASE 3
  41.             PRINT InterpretInteger&(EvalLoop$(ExponentPrefix$(a, b) + "[s][k]"))
  42.             PRINT "Result:"; a; d; b; "="; a ^ b
  43.     END SELECT
  44.     PRINT
  45.  
  46.  
  47. '' Identity
  48. 'PRINT EvalLoop$("s[k][k]" + "[a]")
  49.  
  50. '' Wolfram's example
  51. 'PRINT EvalLoop$("s[s[k[s]][s[k[k]][s[k[s]][k]]]][s[k[s[s[k][k]]]][k]]")
  52. 'PRINT EvalLoop$("s[s[k[s]][s[k[k]][s[k[s]][k]]]][s[k[s[s[k][k]]]][k]][a][b][c]")
  53.  
  54. '' Zero
  55. 'PRINT EvalLoop$("s[k]" + "[s][k]")
  56. 'PRINT EvalLoop$(NumberPrefix$(0) + "[s][k]")
  57.  
  58. '' One
  59. 'PRINT EvalLoop$("s[s[k[s]][k]][s[k]]" + "[s][k]")
  60. 'PRINT EvalLoop$("s[s[k[s]][k]]" + "[s[k]][s][k]")
  61. 'PRINT EvalLoop$(NumberPrefix$(1) + "[s][k]")
  62.  
  63. '' Two
  64. 'PRINT EvalLoop$("s[s[k[s]][k]][s[s[k[s]][k]][s[k]]]" + "[s][k]")
  65. 'PRINT EvalLoop$("s[s[k[s]][k]]" + "[" + "s[s[k[s]][k]]" + "[s[k]]][s][k]")
  66. 'PRINT EvalLoop$(NumberPrefix$(2) + "[s][k]")
  67.  
  68. '' Three
  69. 'PRINT EvalLoop$("s[s[k[s]][k]][s[s[k[s]][k]][s[s[k[s]][k]][s[k]]]]" + "[s][k]")
  70. 'PRINT EvalLoop$("s[s[k[s]][k]]" + "[" + "s[s[k[s]][k]]" + "[" + "s[s[k[s]][k]]" + "[s[k]]]][s][k]")
  71. 'PRINT EvalLoop$(NumberPrefix$(3) + "[s][k]")
  72.  
  73. '' Sum
  74. 'PRINT EvalLoop$("s[k[s]][s[k[s[k[s]]]][s[k[k]]]][s[s[k[s]][k]][s[k]]][s[s[k[s]][k]][s[s[k[s]][k]][s[k]]]][s][k]")
  75. 'PRINT EvalLoop$(SumPrefix$(1, 2) + "[s][k]")
  76. 'PRINT EvalLoop$(SumPrefix$(3, 4) + "[s][k]")
  77. 'PRINT EvalLoop$(SumPrefix$(30, 40) + "[s][k]")
  78.  
  79. '' Product
  80. 'PRINT EvalLoop$("s[k[s]][k][s[s[k[s]][k]][s[s[k[s]][k]][s[k]]]][s[s[k[s]][k]][s[s[k[s]][k]][s[k]]]][s][k]")
  81. 'PRINT EvalLoop$(ProductPrefix$(2, 2) + "[s][k]")
  82. 'PRINT EvalLoop$(ProductPrefix$(3, 2) + "[s][k]")
  83. 'PRINT EvalLoop$(ProductPrefix$(2, 3) + "[s][k]")
  84.  
  85. '' Exponent
  86. 'PRINT EvalLoop$(ExponentPrefix$(3, 2) + "[s][k]")
  87.  
  88. '' Self-apply: siix
  89. 'PRINT EvalLoop$("s[s[k][k]][s[k][k]][x]")
  90.  
  91. '' Infinite loop: sii(sii)
  92. 'PRINT EvalLoop$("s[s[k][k]][s[k][k]][s[s[k][k]][s[k][k]]]")
  93.  
  94. '' Swap: s(k(si))(s(kk)i)ab
  95. 'PRINT EvalLoop$("s[k[s[s[k][k]]]][s[k[k]][s[k][k]]][a][b]")
  96.  
  97. '' Self-reference 1:
  98. 'PRINT EvalLoop$("s[k[x]][s[s[k][k]][s[k][k]]][y]")
  99.  
  100. '' Self-reference 2: (infinite loop)
  101. 'PRINT EvalLoop$("s[k[x]][s[s[k][k]][s[k][k]]][s[k[x]][s[s[k][k]][s[k][k]]]]")
  102.  
  103.  
  104. ' Human helper fucntion(s)
  105.  
  106. FUNCTION InterpretInteger& (t AS STRING)
  107.     DIM TheReturn AS LONG
  108.     DIM j AS INTEGER
  109.     DIM w AS STRING
  110.     TheReturn = 0
  111.     w = t
  112.     j = INSTR(w, "s")
  113.     DO WHILE (j <> 0)
  114.         TheReturn = TheReturn + 1
  115.         w = RIGHT$(w, LEN(w) - j - 1)
  116.         j = INSTR(w, "s")
  117.     LOOP
  118.     InterpretInteger& = TheReturn
  119.  
  120. ' Math functions
  121.  
  122. FUNCTION ExponentPrefix$ (a AS INTEGER, b AS INTEGER)
  123.     ExponentPrefix$ = "s[k[s[s[k][k]]]][k]" + "[" + NumberPrefix$(a) + "]" + "[" + NumberPrefix$(b) + "]"
  124.  
  125. FUNCTION ProductPrefix$ (a AS INTEGER, b AS INTEGER)
  126.     ProductPrefix$ = "s[k[s]][k]" + "[" + NumberPrefix$(a) + "]" + "[" + NumberPrefix$(b) + "]"
  127.  
  128. FUNCTION SumPrefix$ (a AS INTEGER, b AS INTEGER)
  129.     SumPrefix$ = "s[k[s]][s[k[s[k[s]]]][s[k[k]]]]" + "[" + NumberPrefix$(a) + "]" + "[" + NumberPrefix$(b) + "]"
  130.  
  131. FUNCTION NumberPrefix$ (n AS LONG)
  132.     NumberPrefix$ = Nest$("s[s[k[s]][k]]", "s[k]", n)
  133.  
  134. ' Higher-order functions
  135.  
  136. FUNCTION Nest$ (f AS STRING, x AS STRING, n AS LONG)
  137.     DIM TheReturn AS STRING
  138.     DIM AS LONG j
  139.     TheReturn = x
  140.     IF (n > 0) THEN
  141.         FOR j = 1 TO n
  142.             TheReturn = f + "[" + TheReturn + "]"
  143.         NEXT
  144.     END IF
  145.     Nest$ = TheReturn
  146.  
  147. ' Eval functions
  148.  
  149. FUNCTION EvalLoop$ (TheStringIn AS STRING)
  150.     DIM TheReturn AS STRING
  151.     DIM Tmp AS STRING
  152.     DIM k AS INTEGER
  153.     Tmp = TheStringIn
  154.     TheReturn = TheStringIn
  155.     PRINT TheReturn
  156.     k = 0
  157.     DO
  158.         Tmp = EvalStep$(TheReturn)
  159.         IF (Tmp <> TheReturn) THEN
  160.             k = k + 1
  161.             TheReturn = Tmp
  162.             PRINT "Step "; _TRIM$(STR$(k)); ": "; TheReturn
  163.         ELSE
  164.             EXIT DO
  165.         END IF
  166.         '_DELAY .025
  167.     LOOP
  168.     EvalLoop$ = TheReturn
  169.  
  170. FUNCTION EvalStep$ (TheStringIn AS STRING)
  171.     DIM TheReturn AS STRING
  172.     DIM AS STRING ArgListS(3)
  173.     DIM AS STRING ArgListK(2)
  174.     DIM AS LONG s0, k0
  175.     DIM AS STRING t1, t2
  176.     TheReturn = TheStringIn
  177.     s0 = FindValidS(TheStringIn, ArgListS())
  178.     k0 = FindValidK(TheStringIn, ArgListK())
  179.     IF (s0 < k0) THEN
  180.         t1 = "s" + ArgListS(1) + ArgListS(2) + ArgListS(3)
  181.         t2 = Shave$(ArgListS(1)) + "[" + Shave$(ArgListS(3)) + "][" + Shave$(ArgListS(2)) + "[" + Shave$(ArgListS(3)) + "]]"
  182.         TheReturn = Replace$(TheStringIn, t1, t2)
  183.     END IF
  184.     IF (k0 < s0) THEN
  185.         t1 = "k" + ArgListK(1) + ArgListK(2)
  186.         t2 = Shave$(ArgListK(1))
  187.         TheReturn = Replace$(TheStringIn, t1, t2)
  188.     END IF
  189.     EvalStep$ = TheReturn
  190.  
  191. ' Parsing functions
  192.  
  193. FUNCTION Shave$ (TheStringIn AS STRING)
  194.     DIM TheReturn AS STRING
  195.     TheReturn = TheStringIn
  196.     TheReturn = LEFT$(TheReturn, LEN(TheReturn) - 1)
  197.     TheReturn = RIGHT$(TheReturn, LEN(TheReturn) - 1)
  198.     Shave$ = TheReturn
  199.  
  200. FUNCTION Replace$ (TheStringIn AS STRING, TargetSegment AS STRING, NewSegment AS STRING)
  201.     DIM TheReturn AS STRING
  202.     DIM k AS INTEGER
  203.     k = INSTR(TheStringIn, TargetSegment)
  204.     IF (k <> 0) THEN
  205.         TheReturn = LEFT$(TheStringIn, k - 1) + NewSegment + RIGHT$(TheStringIn, LEN(TheStringIn) - k - LEN(TargetSegment) + 1)
  206.     ELSE
  207.         TheReturn = TheStringIn
  208.     END IF
  209.     Replace$ = TheReturn
  210.  
  211. SUB FindArgs (TheStringIn AS STRING, StartPos AS LONG, NumArgs AS LONG, arr() AS STRING)
  212.     DIM TheString AS STRING
  213.     DIM AS LONG i, j0, j1, j2, bal
  214.     TheString = TheStringIn
  215.     j0 = 0
  216.     j1 = 0
  217.     j2 = 0
  218.     bal = 0
  219.     i = StartPos
  220.     DO WHILE (i <= LEN(TheString))
  221.         i = i + 1
  222.         IF (MID$(TheString, i, 1) = "[") THEN
  223.             bal = bal + 1
  224.             IF (bal = 1) THEN j1 = i
  225.         END IF
  226.         IF (MID$(TheString, i, 1) = "]") THEN
  227.             bal = bal - 1
  228.             IF (bal = 0) THEN j2 = i
  229.         END IF
  230.         IF ((j1 <> 0) AND (j2 <> 0) AND (bal = 0)) THEN
  231.             j0 = j0 + 1
  232.             arr(j0) = MID$(TheString, j1, j2 - j1 + 1)
  233.             j1 = 0
  234.             j2 = 0
  235.             bal = 0
  236.             IF (j0 = NumArgs) THEN EXIT DO
  237.         END IF
  238.     LOOP
  239.  
  240. FUNCTION FindValidS& (TheStringIn AS STRING, arr() AS STRING)
  241.     DIM TheReturn AS LONG
  242.     DIM Tmp AS STRING
  243.     DIM AS LONG j, n
  244.     TheReturn = 2147483647
  245.     Tmp = TheStringIn
  246.     FOR j = 1 TO UBOUND(arr)
  247.         arr(j) = ""
  248.     NEXT
  249.     n = 0
  250.     DO
  251.         j = INSTR(Tmp, "s")
  252.         IF (j > 0) THEN
  253.             CALL FindArgs(Tmp, j, 3, arr())
  254.             IF ((arr(1) <> "") AND (arr(2) <> "") AND (arr(3) <> "")) THEN
  255.                 TheReturn = j + n
  256.                 EXIT DO
  257.             ELSE
  258.                 Tmp = RIGHT$(Tmp, LEN(Tmp) - j)
  259.                 n = LEN(TheStringIn) - LEN(Tmp)
  260.             END IF
  261.         ELSE
  262.             EXIT DO
  263.         END IF
  264.     LOOP
  265.     FindValidS& = TheReturn
  266.  
  267. FUNCTION FindValidK& (TheStringIn AS STRING, arr() AS STRING)
  268.     DIM TheReturn AS LONG
  269.     DIM Tmp AS STRING
  270.     DIM AS LONG j, n
  271.     TheReturn = 2147483647
  272.     Tmp = TheStringIn
  273.     FOR j = 1 TO UBOUND(arr)
  274.         arr(j) = ""
  275.     NEXT
  276.     n = 0
  277.     DO
  278.         j = INSTR(Tmp, "k")
  279.         IF (j > 0) THEN
  280.             CALL FindArgs(Tmp, j, 2, arr())
  281.             IF ((arr(1) <> "") AND (arr(2) <> "")) THEN
  282.                 TheReturn = j + n
  283.                 EXIT DO
  284.             ELSE
  285.                 Tmp = RIGHT$(Tmp, LEN(Tmp) - j)
  286.                 n = LEN(TheStringIn) - LEN(Tmp)
  287.             END IF
  288.         ELSE
  289.             EXIT DO
  290.         END IF
  291.     LOOP
  292.     FindValidK& = TheReturn

EDIT:

Here is a screenshot of calculating 4^4. It took almost 3000 steps!
 
sssss.png

9
Programs / qXed 2021
« on: December 26, 2021, 02:00:08 am »
Yello all,

Some are aware of this project, some aren't. So playing to both audiences, qXed is a hackable text editor made in qb64. It doesn't behave exactly like notepad or gedit, but its probably a bit more friendly than vim. I won't discuss the controls or address the learning curve here, sorry about that. Today is only for new stuff... Using the word "hackable", I mean qXed does more than let you write text. It can also take commands through Pipecom and receive the results back. For instance, I could be typing along, and then for whatever reason need to see the contents of the directory I'm in, so I can type:

Code: [Select]
>dir
and press Ctrl+Enter. (This would be "ls" in Linux of course.) Then, boom, right in the middle of my document, I get the contents of DIR:

Code: [Select]
>dir
( Volume in drive D is New Volume
 Volume Serial Number is 9E67-C1F1

 Directory of D:\qb64

12/26/2021  01:46 AM    <DIR>          .
12/26/2021  01:46 AM    <DIR>          ..
12/26/2021  01:16 AM                37 animals.txt
12/25/2021  09:53 PM         2,170,368 BinaryAnalyzer-Game.exe
12/25/2021  09:56 PM         2,172,416 BinaryAnalyzer.exe
12/23/2021  06:18 PM         1,611,264 bubblesort.exe



Since Pipecom is so handy, you can also send commands to external programs and get the answer back, supposing you have what I'll call "qXed-compatible" programs. These are defined as "pure text in, pure text out". Watch this example session (try to puzzle out what happens):

Code: [Select]
]save animals.txt
dog
cat
poodle
zebra
waifu
turtle

(animals.txt)
]

>quicksort animals.txt zoo.txt
()

>list zoo.txt
(cat
dog
poodle
turtle
waifu
zebra)
>

For this example to work, a program called quicksort(.exe) needs to already exist that reads a list from file, sorts it, and spits out a new sorted list. We read the sorted list back with another program called list(.exe).



Alright, so you see what I'm trying to make here. It's a text editor colliding with a terminal. This thing might behave in ways you might not expect, maybe rough ways, but I'm calling everything you see a "feature". I reserve the word "bug" for... well, you'll have to really convince me there's a problem. The grander point here is this aims to be one of those kinds of programs you can always have open. With the right supporting programs, it can do all kinds of work for you that the internet already does 1,000,000 times better, but what the hell right?

This is how it's landing in 2021. We'll see how the future treats this code but I bid you all to mess with it and try to dream up whatever console-friendly qXed-compatible programs can run with it. Full code here, all one file:

Code: QB64: [Select]
  1.  
  2. 'On Error GoTo BadExit
  3.  
  4.  
  5. _Title "qXed"
  6.  
  7. '$ExeIcon:'qXedlogo.ico'
  8.  
  9. Const KeyboardBksp = 8
  10. Const KeyboardTab = 9
  11. Const KeyboardEnter = 13
  12. Const KeyboardEsc = 27
  13. Const KeyboardF1 = 15104
  14. Const KeyboardF2 = 15360
  15. Const KeyboardF3 = 15616
  16. Const KeyboardF4 = 15872
  17. Const KeyboardF5 = 16128
  18. Const KeyboardF6 = 16384
  19. Const KeyboardF7 = 16640
  20. Const KeyboardF8 = 16896
  21. Const KeyboardF9 = 17152
  22. Const KeyboardF10 = 17408
  23. Const KeyboardF11 = 34048
  24. Const KeyboardF12 = 34304
  25. Const KeyboardHome = 18176
  26. Const KeyboardUpArrow = 18432
  27. Const KeyboardPgUp = 18688
  28. Const KeyboardLeftArrow = 19200
  29. Const KeyboardRightArrow = 19712
  30. Const KeyboardEnd = 20224
  31. Const KeyboardDnArrow = 20480
  32. Const KeyboardPgDn = 20736
  33. Const KeyboardIns = 20992
  34. Const KeyboardDel = 21248
  35. Const KeyboardRightShift = 100304
  36. Const KeyboardLeftShift = 100304
  37. Const KeyboardRightCtrl = 100305
  38. Const KeyboardLeftCtrl = 100306
  39. Const KeyboardRightAlt = 100307
  40. Const KeyboardLeftAlt = 100308
  41.  
  42. Dim Shared Spacebar As String
  43. LF = Chr$(10)
  44. CR = Chr$(13)
  45. Spacebar = Chr$(32)
  46.  
  47. Dim Shared BackgroundColor
  48. Dim Shared Cursor1Back
  49. Dim Shared Cursor2Back
  50. Dim Shared CursorBlinkFace
  51. Dim Shared CursorMixedBack
  52. Dim Shared CursorStdFace
  53. Dim Shared ScrollbarBack
  54. Dim Shared ScrollbarBase
  55. Dim Shared ScrollbarFace
  56. Dim Shared StatusBarColor
  57. Dim Shared TextBackColor
  58. Dim Shared TextFaceColor
  59. Dim Shared TextHighBack
  60. Dim Shared TextHighFace
  61. Dim Shared TitleColor
  62. Dim Shared WireColor
  63.  
  64. Dim Shared ColorTheme
  65. ColorTheme = 1
  66.  
  67. Dim Shared TheERROR As String
  68. Dim Shared Debug$
  69.  
  70.  
  71. _Delay .25
  72. Dim Shared scrHand As Long
  73. Dim Shared oldHand As Long
  74. scrHand = _NewImage(1 * 80, 1 * 24, 0) ' 8, 16, 0
  75. Screen scrHand
  76. Call SetPalette
  77.  
  78. ' Define fundamental structures.
  79. Type Vector
  80.     X As Integer
  81.     Y As Integer
  82.  
  83. Type Cell
  84.     Identity As Long
  85.     Pointer As Long
  86.     Lagger As Long
  87.     Content As String * 1
  88.  
  89. Dim Shared ChainLimit As Long
  90. Dim Shared BOC As Long ' Beginning of chain.
  91. Dim Shared EOC As Long ' End of chain.
  92. ChainLimit = 1 * 10 ^ 6
  93. BOC = 0
  94. EOC = ChainLimit
  95.  
  96. ' Define text window properties.
  97. Dim Shared WindowHeight As Integer
  98. Dim Shared WindowWidth As Integer
  99. Dim Shared VisibleLines As Integer
  100. Dim Shared TopIndent As Integer
  101. Dim Shared LeftIndent As Integer
  102. Dim Shared TextHeight As Integer
  103. Dim Shared TextWidth As Integer
  104. Dim Shared TextWrapping As Integer
  105. Dim Shared TextFormatting As Integer
  106. Dim Shared InsertKey As Integer
  107.  
  108. ' Set window properties.
  109. Call InitTextWindow
  110.  
  111. ' Set display state.
  112. HScroll = 1
  113. TextWrapping = 1
  114. TextFormatting = -1
  115. InsertKey = -1
  116.  
  117. ' Initiate text inside window.
  118. Dim Shared StartIndex
  119. Dim Shared LineAsMapped(TextHeight + 1) As String
  120. Dim Shared Cursor1 As Vector
  121. Dim Shared Cursor2 As Vector
  122.  
  123. ' Auxiliary 2D text grid.
  124. Dim Shared GOLSwitch
  125. Dim Shared AuxGrid(TextWidth, TextHeight, 2) As String
  126. GOLSwitch = -1
  127.  
  128. ' Create memory space for string.
  129. Dim Shared TheChain(ChainLimit) As Cell
  130.  
  131. ' File I/O.
  132. Dim Shared WorkingFileName As String
  133.  
  134. Dim Shared Highlight As String
  135. Highlight = "qXed"
  136.  
  137. ' Load text file into memory if applicable, use example string if not.
  138. Call InitTextChain(Command$)
  139.  
  140. ' Prime main loop.
  141. Call MapText
  142. Call CalibrateCursor(ID1)
  143. Call CalibrateCursor(ID2)
  144. Call PrintEverything
  145.  
  146. ' Main loop.
  147.  
  148.     If (StateChange% = 1) Then
  149.         Call PrintEverything
  150.     End If
  151.  
  152.     If (GOLSwitch = 1) Then
  153.         Call ConvertToGrid
  154.         Call GOL
  155.         Call ConvertFromGrid
  156.         Call MapText
  157.         Call PrintEverything
  158.     End If
  159.  
  160.     Do While (_Resize)
  161.         If ((_ResizeWidth / 8 > 18) And (_ResizeHeight / 16 > 6)) Then
  162.             oldHand = scrHand
  163.             scrHand = _NewImage((_ResizeWidth / 8), (_ResizeHeight / 16), 0)
  164.             Screen scrHand
  165.             _FreeImage oldHand
  166.             Call SetPalette
  167.             Call InitTextWindow
  168.             ReDim LineAsMapped(TextHeight)
  169.             ReDim AuxGrid(TextWidth, TextHeight, 2)
  170.             Call MapText
  171.             Call CalibrateCursor(ID1)
  172.             Call CalibrateCursor(ID2)
  173.             Call PrintEverything
  174.         End If
  175.     Loop
  176.  
  177.         If (_FileExists(_DroppedFile$(1))) Then
  178.             Call InitTextChain(_DroppedFile$(1))
  179.             Call MapText
  180.             Call CalibrateCursor(ID1)
  181.             Call CalibrateCursor(ID2)
  182.             Call PrintEverything
  183.         End If
  184.         _FinishDrop
  185.     End If
  186.  
  187.     _Display
  188.     _Limit 240
  189.  
  190.  
  191. BadExit:
  192. _Echo (TheERROR)
  193.  
  194. Sub StringPrint (RequestCode As String, x As Integer, y As Integer, txt As String)
  195.     TheERROR = RequestCode + Str$(x) + Str$(y) + " " + txt
  196.     '_PrintString (x * 8, y * 16), txt
  197.     Locate y, x: Print txt;
  198.  
  199. Sub InitTextWindow
  200.     WindowWidth = _Width / 1 - 0 * 1 '8, 1
  201.     WindowHeight = _Height / 1 - 0 * 1 '16, 1
  202.     TopIndent = 1 '0
  203.     LeftIndent = 1 '0
  204.     TextHeight = WindowHeight - (1 + TopIndent)
  205.     TextWidth = WindowWidth - (1 + LeftIndent)
  206.  
  207. Sub SetPalette
  208.     BackgroundColor = 0
  209.     Cursor1Back = 3
  210.     Cursor2Back = 7
  211.     CursorBlinkFace = 16 + 6
  212.     CursorMixedBack = 7
  213.     CursorStdFace = 0
  214.     ScrollbarBack = 7
  215.     ScrollbarBase = 8
  216.     ScrollbarFace = 1
  217.     StatusBarColor = 3
  218.     TextBackColor = 1
  219.     TextFaceColor = 11
  220.     TextHighBack = 2
  221.     TextHighFace = 1
  222.     TitleColor = 3
  223.     WireColor = 8
  224.     If (ColorTheme = 1) Then
  225.         _PaletteColor 0, _RGB32(0, 0, 39)
  226.         _PaletteColor 1, _RGB32(0, 49, 78)
  227.         _PaletteColor 3, _RGB32(69, 118, 147)
  228.         _PaletteColor 4, _RGB32(216, 98, 78)
  229.         _PaletteColor 6, _RGB32(255, 167, 0) '''
  230.         _PaletteColor 7, _RGB32(98, 98, 98)
  231.         _PaletteColor 8, _RGB32(48, 48, 48) '''
  232.         _PaletteColor 9, _RGB32(0, 88, 108)
  233.         _PaletteColor 10, _RGB32(85, 206, 85)
  234.         _PaletteColor 11, _RGB32(0, 170, 170) '''
  235.         _PaletteColor 14, _RGB32(255, 167, 0)
  236.         _PaletteColor 15, _RGB32(216, 216, 216)
  237.     Else
  238.         oldHand = scrHand
  239.         scrHand = _NewImage(_Width, _Height, 0)
  240.         Screen scrHand
  241.         _FreeImage oldHand
  242.     End If
  243.  
  244. Sub InitTextChain (c As String)
  245.     Dim i As Integer
  246.     Dim j As Integer
  247.     Dim k As Long
  248.     Dim q As String
  249.     Dim r As String
  250.     If (c <> "") Then
  251.         q = ""
  252.         Open c For Input As #1
  253.         Do While Not EOF(1)
  254.             Line Input #1, r
  255.             q = q + r + CR
  256.         Loop
  257.         Close #1
  258.         i = InStr(c, ".")
  259.         If (i <> 0) Then
  260.             j = i - 1
  261.         Else
  262.             j = Len(c)
  263.         End If
  264.         WorkingFileName = Left$(c, j) + "-" + LTrim$(RTrim$(Str$(Int(Timer)))) + ".txt"
  265.     Else
  266.         WorkingFileName = "qXed_file" + "-" + Date$ + "-" + LTrim$(RTrim$(Str$(Int(Timer)))) + ".txt"
  267.         q = ""
  268.         'q = q + "Working file is:" + CR + Chr$(9) + WorkingFileName + CR + CR + "Press F6 to save." + CR
  269.         q = q + "Welcome to qXed" + CR
  270.         q = q + "... a hackable text editor" + CR
  271.         q = q + "... now boosted with Pipecom!" + CR
  272.         q = q + CR
  273.         q = q + "Use Pipecom by starting a line with a bracket '>'." + CR
  274.         q = q + "Press Ctrl+Enter to evaluate that line." + CR
  275.         q = q + CR
  276.         q = q + "For example, place the cursor after 'dir', and press Ctrl+Enter:" + CR
  277.         q = q + "(Or, replace 'dir' with 'ls' for Linux.)" + CR
  278.         q = q + CR
  279.         q = q + ">dir"
  280.         q = q + CR
  281.         q = q + CR
  282.         q = q + "This program has a steeper learning curve than Notepad, so beware." + CR
  283.         q = q + CR
  284.         q = q + "Press F3 to change search term." + CR
  285.         q = q + "Press F10 to toggle high contrast mode." + CR
  286.         q = q + "Press F11 to see break returns and whitespace." + CR
  287.         q = q + "Press F12 to cycle text wrapping modes." + CR
  288.     End If
  289.  
  290.     ' Create character list.
  291.     For k = 1 To ChainLimit
  292.         TheChain(k).Identity = 0
  293.     Next
  294.     ID2 = Assimilate&(q, BOC, EOC)
  295.     'StartIndex = 1
  296.     ID1 = StartIndex
  297.  
  298.     GOLSwitch = -1
  299.  
  300. Function Assimilate& (a As String, st As Long, en As Long)
  301.     ' Maps a raw string of text between a set of identities.
  302.     Dim b As String
  303.     Dim c As String
  304.     Dim j As Long
  305.     Dim previousID As Long
  306.     Dim nextID As Long
  307.     Dim n0 As Long
  308.  
  309.     If ((st = BOC) And (en = EOC)) Then
  310.         previousID = st
  311.         nextID = NextOpenIdentity&(1)
  312.     Else
  313.         previousID = TheChain(st).Lagger
  314.         nextID = NextOpenIdentity&(st)
  315.     End If
  316.     n0 = nextID
  317.  
  318.     b = a
  319.     Do
  320.         c = Left$(b, 1)
  321.         b = Right$(b, Len(b) - 1)
  322.         Select Case c
  323.             Case Chr$(9)
  324.                 c = " "
  325.                 b = "   " + b
  326.             Case CR
  327.                 If (Left$(b, 1) = LF) Then
  328.                     b = Right$(b, Len(b) - 1)
  329.                 End If
  330.             Case LF
  331.                 c = CR
  332.         End Select
  333.         j = nextID
  334.         TheChain(j).Identity = j
  335.         TheChain(j).Content = c
  336.         TheChain(j).Lagger = previousID
  337.         If (previousID <> BOC) Then TheChain(previousID).Pointer = j
  338.         If (Len(b) > 0) Then
  339.             previousID = j
  340.             nextID = NextOpenIdentity&(j)
  341.         Else
  342.             If ((st = BOC) And (en = EOC)) Then
  343.                 TheChain(j).Pointer = en
  344.                 TheChain(en).Lagger = j
  345.             Else
  346.                 TheChain(j).Pointer = st
  347.                 TheChain(st).Lagger = j
  348.             End If
  349.             Exit Do
  350.         End If
  351.     Loop
  352.  
  353.     If ((st = BOC) And (en = EOC)) Then
  354.         StartIndex = n0
  355.     End If
  356.  
  357.     If (st <> EOC) Then
  358.         If (st = StartIndex) Then
  359.             StartIndex = BackBreak&(StartIndex)
  360.         End If
  361.     End If
  362.  
  363.     Assimilate& = n0
  364.  
  365. Function InsertString& (a As String, st As Long)
  366.     InsertString& = Assimilate&(a, st, TheChain(st).Pointer)
  367.  
  368. Function NthP& (a As Long, b As Long)
  369.     ' Returns the address that is b jumps ahead of address a.
  370.     Dim i As Long
  371.     Dim j As Long
  372.     Dim k As Long
  373.     i = a
  374.     j = 0
  375.     If (i <> EOC) Then
  376.         k = 0
  377.         Do While (k < b)
  378.             k = k + 1
  379.             j = i
  380.             i = TheChain(j).Pointer
  381.             If (i = EOC) Then Exit Do
  382.         Loop
  383.     End If
  384.     '''
  385.     If (j = 0) Then
  386.         j = StartIndex
  387.         Sound 1000, 1
  388.     End If
  389.     '''
  390.     NthP& = j
  391.  
  392. Function NthL& (a As Long, b As Long)
  393.     ' Returns the address that is b jumps behind address a.
  394.     Dim i As Long
  395.     Dim j As Long
  396.     Dim k As Long
  397.     i = a
  398.     k = 0
  399.     Do While (k < b)
  400.         k = k + 1
  401.         j = i
  402.         i = TheChain(j).Lagger
  403.         If (i = BOC) Then Exit Do
  404.     Loop
  405.     NthL& = j
  406.  
  407. Function NextOpenIdentity& (a As Long)
  408.     Dim j As Long
  409.     For j = a To ChainLimit
  410.         If (TheChain(j).Identity = 0) Then Exit For
  411.     Next
  412.     If (j > ChainLimit) Then
  413.         Print "Chain limit exceeded."
  414.         Sleep
  415.         System
  416.     End If
  417.     NextOpenIdentity& = j
  418.  
  419. Function BackBreak& (a As Long)
  420.     ' Function for scrolling up.
  421.     Dim c As String
  422.     Dim d As String
  423.     Dim j As Long
  424.     Dim k As Long
  425.     Dim lastBreak As Long
  426.     j = a
  427.     lastBreak = 0
  428.     c = ""
  429.     Do
  430.         If (j = BOC) Then Exit Do
  431.         k = TheChain(j).Lagger
  432.         If (k = BOC) Then
  433.             lastBreak = j
  434.             Exit Do
  435.         End If
  436.         j = k
  437.         d = TheChain(j).Content
  438.         c = d + c
  439.         If (TextWrapping = 1) Then
  440.             If ((d = " ") Or (d = CR)) Then
  441.                 lastBreak = j
  442.             End If
  443.         End If
  444.         If (TextWrapping <> 2) And (Len(c) = TextWidth) Then Exit Do
  445.         If (d = CR) Then
  446.             Exit Do
  447.         End If
  448.     Loop
  449.     If (lastBreak <> 0) Then j = lastBreak
  450.     BackBreak& = j
  451.  
  452. Function BackBreak2& (a As Long)
  453.     Dim c As String
  454.     Dim d As String
  455.     Dim j As Long
  456.     Dim k As Long
  457.     Dim lastBreak As Long
  458.     j = a
  459.     lastBreak = 0
  460.     c = ""
  461.     Do
  462.         If (j = BOC) Then Exit Do
  463.         k = TheChain(j).Lagger
  464.         If (k = BOC) Then
  465.             lastBreak = j
  466.             Exit Do
  467.         End If
  468.         j = k
  469.         d = TheChain(j).Content
  470.         c = d + c
  471.         If (TextWrapping = 1) Then
  472.             If (d = CR) Then
  473.                 If (Mid$(c, 2, 1) = ">") Or (Mid$(c, 2, 1) = "]") Then
  474.                     'If ((d = " ") Or (d = CR)) Then
  475.                     lastBreak = TheChain(j).Pointer
  476.                     'lastBreak = j
  477.                 End If
  478.             End If
  479.         End If
  480.         If (TextWrapping <> 2) And (Len(c) = TextWidth) Then Exit Do
  481.         If (d = CR) Then
  482.             If (Mid$(c, 2, 1) = ">") Or (Mid$(c, 2, 1) = "]") Then
  483.                 'If (d = CR) Then
  484.                 Exit Do
  485.             End If
  486.         End If
  487.     Loop
  488.     If (lastBreak <> 0) Then j = lastBreak
  489.     BackBreak2& = j
  490.  
  491.  
  492. Sub InsertBefore (a As Long, b As String)
  493.     ' Inserts a single cell before address a in the chain.
  494.     Dim lg As Long
  495.     Dim j As Long
  496.     j = NextOpenIdentity&(a)
  497.     lg = TheChain(a).Lagger
  498.     TheChain(j).Identity = j
  499.     TheChain(j).Pointer = a
  500.     TheChain(j).Lagger = lg
  501.     TheChain(j).Content = b
  502.     TheChain(a).Lagger = j
  503.     If (lg = BOC) Then
  504.         StartIndex = j
  505.     Else
  506.         TheChain(lg).Pointer = j
  507.     End If
  508.  
  509. Sub InsertCharacter (k As Integer)
  510.     If (InsertKey = -1) Then
  511.         Call InsertBefore(ID1, LTrim$(RTrim$(Chr$(k))))
  512.     Else
  513.         TheChain(ID1).Content = LTrim$(RTrim$(Chr$(k)))
  514.         ID1 = NthP&(ID1, 2)
  515.     End If
  516.     If (TextWrapping = 2) Then
  517.         If (Cursor1.X - LeftIndent = TextWidth) Then
  518.             HScroll = HScroll + 1
  519.         End If
  520.     End If
  521.  
  522. Function InsertAfter& (a As Long, b As String)
  523.     ' Inserts a single cell after address a in the chain.
  524.     Dim j As Long
  525.     Dim p As Long
  526.     j = NextOpenIdentity&(a)
  527.     p = TheChain(a).Pointer
  528.     TheChain(j).Identity = j
  529.     TheChain(j).Pointer = p
  530.     TheChain(j).Lagger = a
  531.     TheChain(j).Content = b
  532.     TheChain(a).Pointer = j
  533.     If (p <> EOC) Then
  534.         TheChain(p).Lagger = j
  535.     End If
  536.     InsertAfter& = j
  537.  
  538. Function LinearCount& (a As Long, b As Long)
  539.     LinearCount& = LinearCountProto&(a, b, ChainLimit + 1)
  540.  
  541. Function LinearCountProto& (a As Long, b As Long, c As Long)
  542.     ' Returns number of links between two addresses, with exit condition.
  543.     Dim i As Long
  544.     Dim j As Long
  545.     Dim k As Long
  546.     i = a
  547.     k = 0
  548.     Do While (i <> b)
  549.         k = k + 1
  550.         j = i
  551.         i = TheChain(j).Pointer
  552.         If (i = EOC) Then Exit Do
  553.         If (k = c) Then Exit Do
  554.     Loop
  555.     LinearCountProto& = k
  556.  
  557. Function Projection$ (a As Long, b As Long)
  558.     ' Returns the linear content for all address between a and b, inclusive.
  559.     Dim TheReturn As String
  560.     Dim j As Long
  561.     Dim k As Long
  562.     Dim c As String
  563.     TheReturn = ""
  564.     If (a = b) Then
  565.         TheReturn = TheChain(a).Content
  566.     Else
  567.         j = a
  568.         Do
  569.             c = TheChain(j).Content
  570.             TheReturn = TheReturn + c
  571.             k = TheChain(j).Pointer
  572.             If (j = b) Then Exit Do
  573.             If (k = EOC) Then Exit Do
  574.             j = k
  575.         Loop
  576.     End If
  577.     Projection$ = TheReturn
  578.  
  579. Sub MapText
  580.     Dim c1 As Long
  581.     Dim c2 As Long
  582.     Dim i As Integer
  583.     Dim r As Integer
  584.     Dim m As Integer
  585.     Dim j As Long
  586.     Dim k As Long
  587.     Dim k1 As Long
  588.     Dim k2 As Long
  589.     Dim n As Long
  590.     Dim q As String
  591.     Dim d As String
  592.     Dim c As String
  593.     Dim brsymbol As String
  594.     If (TextFormatting = 1) Then
  595.         brsymbol = "~"
  596.     Else
  597.         brsymbol = " "
  598.     End If
  599.     j = StartIndex
  600.     i = 1
  601.     q = ""
  602.     d = ""
  603.     Do ' Begin with any left-over text from previous iteration.
  604.         q = d
  605.         d = ""
  606.         r = TextWidth - Len(q)
  607.  
  608.         '''
  609.         If (TextWrapping = 0) Then
  610.             k1 = NthP&(j, r)
  611.             If (TheChain(k1).Pointer = EOC) Then k1 = EOC
  612.         End If
  613.         If (TextWrapping = 1) Then
  614.             k1 = NthP&(j, r)
  615.             If (TheChain(k1).Pointer = EOC) Then k1 = EOC
  616.         End If
  617.         If (TextWrapping = 2) Then
  618.             k1 = EOC
  619.         End If
  620.         '''
  621.  
  622.         k2 = j
  623.         Do
  624.             If (TheChain(k2).Content = CR) Then Exit Do
  625.             If (TheChain(k2).Pointer = EOC) Then Exit Do
  626.             k2 = TheChain(k2).Pointer
  627.         Loop
  628.  
  629.         If (TextWrapping <> 2) Then
  630.             c1 = LinearCount&(j, k1)
  631.         Else
  632.             c1 = LinearCountProto&(j, k1, TextWidth * TextHeight)
  633.         End If
  634.  
  635.         c2 = LinearCount&(j, k2)
  636.  
  637.         If (c2 = 0) Then ' Line has one character (except in Fluid mode).
  638.             k = k2
  639.             If (TheChain(j).Content = CR) Then
  640.                 q = q + brsymbol
  641.             Else
  642.                 q = q + TheChain(j).Content
  643.             End If
  644.             j = NthP&(k, 2)
  645.  
  646.         Else
  647.  
  648.             If (c1 = c2) Then ' End of line. (Possible end of chain?)
  649.                 '''
  650.                 If (TextWrapping = 0) Then
  651.                     k = k1
  652.                     If (TheChain(k).Content = CR) Then
  653.                         q = q + Projection$(j, TheChain(k).Lagger) + brsymbol
  654.                     Else
  655.                         q = q + Projection$(j, k)
  656.                     End If
  657.                     j = NthP&(k, 2)
  658.                 End If
  659.                 If (TextWrapping = 1) Then
  660.                     k = TheChain(k1).Lagger
  661.                     If (TheChain(k).Content = CR) Then
  662.                         q = q + Projection$(j, TheChain(k).Lagger) + brsymbol
  663.                     Else
  664.                         q = q + Projection$(j, k)
  665.                     End If
  666.                     j = NthP&(k, 2)
  667.                 End If
  668.                 If (TextWrapping = 2) Then
  669.                     k = k1 ' == EOC
  670.                     q = q + Projection$(j, k)
  671.                     j = NthP&(k, 2)
  672.                 End If
  673.                 '''
  674.             End If
  675.             If (c1 < c2) Then ' Width limit case (not always maximum).
  676.                 k = k1
  677.                 q = q + Projection$(j, k)
  678.                 j = NthP&(k, 2)
  679.             End If
  680.             If (c1 > c2) Then ' Break return somewhere in line (not first).
  681.                 k = k2
  682.                 n = TheChain(k).Pointer
  683.                 ''' Clean this up if compelled.
  684.                 If (n <> EOC) Then
  685.                     q = q + Projection$(j, TheChain(k).Lagger) + brsymbol
  686.                     j = n
  687.                 Else ' End of chain.
  688.                     If (TheChain(k).Content = CR) Then
  689.                         q = q + Projection$(j, TheChain(k).Lagger) + brsymbol
  690.                     Else
  691.                         q = q + Projection$(j, k)
  692.                     End If
  693.                 End If
  694.                 '''
  695.             End If
  696.         End If
  697.  
  698.         If (TextWrapping = 1) Then ' Wrap text at first breaking character from right, send remainder to next line.
  699.             If (Len(q) >= TextWidth) Then
  700.                 For m = Len(q) To 1 Step -1
  701.                     c = Mid$(q, m, 1)
  702.                     If ((c = " ") Or (c = "-") Or (c = ".") Or (c = "_") Or (c = brsymbol)) Then
  703.                         q = Left$(q, m)
  704.                         Exit For
  705.                     End If
  706.                     d = c + d
  707.                 Next
  708.                 If (m = 0) Then ' Text is too long for line and contains no wrapping characters.
  709.                     q = Left$(q, TextWidth)
  710.                     d = ""
  711.                 End If
  712.             End If
  713.         End If
  714.  
  715.         LineAsMapped(i) = q
  716.         i = i + 1
  717.  
  718.         If (n = EOC) Then
  719.             If (d <> "") Then
  720.                 LineAsMapped(i) = d
  721.                 i = i + 1
  722.             End If
  723.             Exit Do
  724.         End If
  725.         If (i = TextHeight) Then
  726.             'IF (d <> "") THEN BEEP
  727.             Exit Do
  728.         End If
  729.         If (j = k) Then
  730.             'IF (d <> "") THEN BEEP
  731.             Exit Do
  732.         End If
  733.     Loop
  734.     VisibleLines = i - 1
  735.  
  736. Sub PasteClipboard (a As Long, b As String)
  737.     Dim z As Long
  738.     z = InsertString&(b, a)
  739.  
  740. Sub CalibrateCursor (a As Long)
  741.     ' Place Cursor under ID on rendered line.
  742.     Dim s As Long
  743.     Dim c As Long
  744.     Dim i As Integer
  745.     Dim j As Integer
  746.     Dim k As Integer
  747.     Dim n As Integer
  748.     s = StartIndex
  749.     If ((TextWrapping = 2) And (HScroll > 1)) Then s = NthP&(s, HScroll)
  750.     c = LinearCount&(s, a)
  751.     k = 0
  752.     i = -1
  753.     For j = 1 To VisibleLines
  754.         n = Len(LineAsMapped(j))
  755.         If (k + n < c) Then
  756.             k = k + n
  757.         Else
  758.             i = c - k + 1
  759.             Exit For
  760.         End If
  761.     Next
  762.     If (j < VisibleLines) Then
  763.         If (i >= 1 + Len(LineAsMapped(j))) Then ''' Clean this line up a little.
  764.             i = 1
  765.             j = j + 1
  766.         End If
  767.     End If
  768.     If (a = ID1) Then
  769.         Cursor1.X = LeftIndent + i
  770.         Cursor1.Y = TopIndent + j
  771.     End If
  772.     If (a = ID2) Then
  773.         Cursor2.X = LeftIndent + i
  774.         Cursor2.Y = TopIndent + j
  775.     End If
  776.  
  777. Function FindID% (a As Integer, b As Long)
  778.     ' Find identity under a mapped location.
  779.     Dim relx As Integer
  780.     Dim rely As Integer
  781.     Dim k As Integer
  782.     Dim t As Integer
  783.     relx = a - LeftIndent
  784.     rely = b - TopIndent
  785.     For k = 1 To rely - 1
  786.         t = t + Len(LineAsMapped(k))
  787.     Next
  788.     t = t + relx
  789.     FindID% = t
  790.  
  791. Sub ReassignID1
  792.     ID1 = NthP&(StartIndex, FindID%(Cursor1.X, Cursor1.Y) + (HScroll - 1))
  793.  
  794. Sub ReassignID2
  795.     ID2 = NthP&(StartIndex, FindID%(Cursor2.X, Cursor2.Y) + (HScroll - 1))
  796.  
  797. Sub PrintEverything
  798.     Color BackgroundColor, BackgroundColor
  799.     Cls
  800.     Call PrintWires
  801.     Call HorizontalScrollbar
  802.     Call PrintStatusBars(VerticalScrollbar#)
  803.     Call PrintCursorInfo
  804.     Call PrintMainText
  805.     Call PrintCursor2
  806.     Call PrintCursor1
  807.  
  808. Sub PrintWires
  809.     Dim i As Integer
  810.     Color WireColor, BackgroundColor
  811.     Call StringPrint("PrintWires", WindowWidth, WindowHeight - 1, Chr$(217))
  812.     Call StringPrint("PrintWires", LeftIndent, WindowHeight - 1, Chr$(192))
  813.     For i = 1 + TopIndent To WindowHeight - 2
  814.         Call StringPrint("PrintWires", LeftIndent, i, Chr$(179))
  815.     Next
  816.     Call StringPrint("PrintWires", LeftIndent, TopIndent, Chr$(218))
  817.     Call StringPrint("PrintWires", WindowWidth, TopIndent, Chr$(191))
  818.     For i = 1 + LeftIndent To WindowWidth - 1
  819.         Call StringPrint("PrintWires", i, TopIndent, Chr$(196))
  820.     Next
  821.  
  822. Sub HorizontalScrollbar
  823.     Dim i As Integer
  824.     Dim p As Long
  825.     Dim q As Long
  826.     Dim r As Double
  827.     Dim s As Double
  828.     Color ScrollbarBase, BackgroundColor
  829.     For i = (1 + LeftIndent) To (WindowWidth - 1)
  830.         Call StringPrint("HorizontalScrollbar1", i, WindowHeight - 1, Chr$(177))
  831.     Next
  832.     p = LinearCount&(NthP&(StartIndex, FindID%(LeftIndent + 1, Cursor1.Y)), ID1)
  833.     q = Len(LineAsMapped(Cursor1.Y - TopIndent))
  834.     If (q <> 1) Then
  835.         r = p / (q - 1)
  836.         If (r > 1) Then r = 1
  837.     Else
  838.         r = 0
  839.     End If
  840.     s = r * (WindowWidth - LeftIndent - 2)
  841.     i = (1 + LeftIndent) + Int(s)
  842.     Color ScrollbarFace, ScrollbarBack
  843.     Call StringPrint("HorizontalScrollbar2", i, WindowHeight - 1, "^")
  844.  
  845. Function VerticalScrollbar#
  846.     Dim i As Integer
  847.     Dim p As Long
  848.     Dim q As Long
  849.     Dim r As Double
  850.     Dim s As Double
  851.     Color ScrollbarBase, BackgroundColor
  852.     For i = (1 + TopIndent) To (WindowHeight - 2)
  853.         Call StringPrint("VerticalScrollbar#", WindowWidth, i, Chr$(177))
  854.     Next
  855.     p = LinearCount&(ID1, NthP&(ID1, ChainLimit + 1))
  856.     q = LinearCount&(NthL&(ID1, ChainLimit + 1), NthP&(ID1, ChainLimit + 1))
  857.     If (q = 0) Then
  858.         r = 1
  859.     Else
  860.         r = Abs(1 - p / q)
  861.     End If
  862.     s = r * (WindowHeight - TopIndent - 3)
  863.     i = (1 + TopIndent) + Int(s)
  864.     Color ScrollbarFace, ScrollbarBack
  865.     Call StringPrint("VerticalScrollbar#", WindowWidth, i, "<")
  866.     VerticalScrollbar# = r
  867.  
  868. Sub PrintStatusBars (r As Double)
  869.     Dim c As String
  870.     c = ""
  871.     If (TextFormatting = 1) Then c = "[Fmt] " + c
  872.     Select Case TextWrapping
  873.         Case 0: c = c + "[Square]" + " "
  874.         Case 1: c = c + "[Fluid]" + " "
  875.         Case 2: c = c + "[None]" + " "
  876.     End Select
  877.     c = c + "[" + LTrim$(RTrim$(Str$(Int(100 * r)))) + "%]"
  878.     If (Len(c) >= TextWidth) Then c = Left$(c, TextWidth)
  879.     Color StatusBarColor, BackgroundColor
  880.     Call StringPrint("PrintStatusBars", WindowWidth - Len(c), TopIndent, c)
  881.     c = ""
  882.     If (InsertKey = 1) Then c = "[Ins]" + c
  883.     If (Len(c) >= TextWidth) Then c = Left$(c, TextWidth)
  884.     Color StatusBarColor, BackgroundColor
  885.     Call StringPrint("PrintStatusBars", WindowWidth - Len(c), WindowHeight, c)
  886.  
  887. Sub PrintCursorInfo
  888.     Dim c As String
  889.     Dim d As String
  890.     Dim c0 As String
  891.     Dim d0 As String
  892.     c = TheChain(ID1).Content
  893.     d = TheChain(ID2).Content
  894.     c0 = c
  895.     d0 = d
  896.     If (c = LF) Then c = "@" ' Should never happen.
  897.     If (d = LF) Then d = "@" ' Should never happen.
  898.     If (c = CR) Then c = "~"
  899.     If (d = CR) Then d = "~"
  900.     If (c = Spacebar) Then c = "_"
  901.     If (d = Spacebar) Then d = "_"
  902.     c = "(" + LTrim$(RTrim$(Str$(Cursor1.X - LeftIndent))) + " " + LTrim$(RTrim$(Str$(Cursor1.Y - TopIndent))) + " " + c + Str$(ID1) + ")"
  903.     Color CursorStdFace, Cursor1Back
  904.     Call StringPrint("PrintCursorInfo", 1 + LeftIndent, WindowHeight, c)
  905.     'IF (LinearCount&(StartIndex, ID2) > LinearCount&(StartIndex, ID1)) THEN
  906.     d = "(" + LTrim$(RTrim$(Str$(Cursor2.X - LeftIndent))) + " " + LTrim$(RTrim$(Str$(Cursor2.Y - TopIndent))) + " " + d + Str$(ID2) + ")"
  907.     Color CursorStdFace, Cursor2Back
  908.     Call StringPrint("PrintCursorInfo", 2 + LeftIndent + Len(c), WindowHeight, d)
  909.     'END IF
  910.     Color TitleColor, BackgroundColor
  911.     Call StringPrint("PrintCursorInfo", 1 + LeftIndent, TopIndent, "[qXed]" + Debug$)
  912.  
  913. Sub PrintMainText
  914.     Dim i As Integer
  915.     Dim j As Integer
  916.     Dim k As Integer
  917.     Dim k0 As Integer
  918.     Dim k00 As Integer
  919.     Dim c As String
  920.     Dim d As String
  921.     For i = 1 To VisibleLines
  922.         c = LineAsMapped(i)
  923.         If (TextFormatting = 1) Then
  924.             For j = 1 To TextWidth - Len(c)
  925.                 c = c + "_"
  926.             Next
  927.         End If
  928.         d = Mid$(c, HScroll, TextWidth)
  929.  
  930.         If (Highlight <> "") Then
  931.             k = InStr(d, Highlight)
  932.         End If
  933.         If (k > 0) Then
  934.             k0 = 0
  935.             Do While (k > 0)
  936.                 k00 = k0 + k - 1
  937.                 Color TextFaceColor, TextBackColor
  938.                 Call StringPrint("PrintMainText", k0 + LeftIndent + 1, TopIndent + i, Left$(d, k - 1))
  939.                 Color TextHighFace, TextHighBack
  940.                 Call StringPrint("PrintMainText", k0 + k - 1 + LeftIndent + 1, TopIndent + i, Mid$(d, k, Len(Highlight)))
  941.                 d = Right$(d, Len(d) - k - Len(Highlight) + 1)
  942.                 k0 = k0 + k - 1 + Len(Highlight)
  943.                 k = InStr(d, Highlight)
  944.             Loop
  945.             Color TextFaceColor, TextBackColor
  946.             Call StringPrint("PrintMainText", k00 + Len(Highlight) + LeftIndent + 1, TopIndent + i, d)
  947.         Else
  948.             Color TextFaceColor, TextBackColor
  949.             Call StringPrint("PrintMainText", LeftIndent + 1, TopIndent + i, d)
  950.         End If
  951.     Next
  952.  
  953. Sub PrintCursor1
  954.     Dim c As String
  955.     If ((Cursor1.X > 0 And Cursor1.X < WindowWidth) And ((Cursor1.Y > 0) And (Cursor1.Y < WindowHeight))) Then
  956.         c = TheChain(ID1).Content
  957.         If (c = " ") Then c = "_"
  958.         If (c = CR) Then c = "~"
  959.         If ((Cursor1.X = Cursor2.X) And (Cursor1.Y = Cursor2.Y)) Then
  960.             Color CursorBlinkFace, CursorMixedBack
  961.             Call StringPrint("PrintCursor1", Cursor1.X, Cursor1.Y, c)
  962.         Else
  963.             Color CursorBlinkFace, Cursor1Back
  964.             Call StringPrint("PrintCursor1", Cursor1.X, Cursor1.Y, c)
  965.         End If
  966.     End If
  967.  
  968. Sub PrintCursor2
  969.     Dim c As String
  970.     Dim p1 As Long
  971.     Dim p2 As Long
  972.     Dim pe As Long
  973.     If ((Cursor2.X > 0 And Cursor2.X < WindowWidth) And ((Cursor2.Y > 0) And (Cursor2.Y < WindowHeight))) Then
  974.         p1 = LinearCount&(StartIndex, ID1)
  975.         p2 = LinearCount&(StartIndex, ID2)
  976.         pe = LinearCount&(StartIndex, EOC)
  977.         If p2 < pe Then 'IF ((p2 > p1) AND (p2 < pe)) THEN
  978.             c = TheChain(ID2).Content
  979.             If (c = " ") Then c = "_"
  980.             If (c = CR) Then c = "~"
  981.             Color CursorStdFace, Cursor2Back
  982.             Call StringPrint("PrintCursor2", Cursor2.X, Cursor2.Y, c)
  983.         End If
  984.     End If
  985.  
  986. Function StateChange%
  987.     Dim TheReturn As Integer
  988.     Dim MH As Integer
  989.     Dim MW As Integer
  990.     Dim MT As Integer
  991.     Dim MH1 As Integer
  992.     Dim MH2 As Integer
  993.     Dim MH3 As Integer
  994.     Dim KH As Long
  995.     MH = 0
  996.     MW = 0
  997.     MT = 0
  998.  
  999.     KH = _KeyHit
  1000.  
  1001.         MH1 = _MouseButton(1)
  1002.         MH2 = _MouseButton(2)
  1003.         MH3 = _MouseButton(3)
  1004.         MW = _MouseWheel
  1005.         If (MW <> 0) Then MT = MW
  1006.     Loop
  1007.     MW = MT
  1008.  
  1009.     If (MH1 = -1) Then MH = MouseButton1%
  1010.     If (MH2 = -1) Then MH = MouseButton2%
  1011.     If (MH3 = -1) Then MH = MouseButton3%
  1012.     If (MW = -1) Then MH = MouseWheelUp%
  1013.     If (MW = 1) Then MH = MouseWheelDown%
  1014.  
  1015.     If (KH = KeyboardBksp) Then Call KeyBksp
  1016.     If (KH = KeyboardTab) Then Call KeyTab
  1017.     If (KH = KeyboardEsc) Then Call KeyEsc
  1018.     If (KH = KeyboardEnter) Or ((KH >= 32) And (KH <= 126)) Then Call KeyEnterAlphaNumer(KH)
  1019.     If (KH = KeyboardF1) Then Call KeyF1
  1020.     If (KH = KeyboardF2) Then Call KeyF2
  1021.     If (KH = KeyboardF3) Then Call KeyF3
  1022.     If (KH = KeyboardF4) Then Call KeyF4
  1023.     If (KH = KeyboardF5) Then Call KeyF5
  1024.     If (KH = KeyboardF6) Then Call KeyF6
  1025.     'If (KH = KeyboardF7) Then Call KeyF7
  1026.     If (KH = KeyboardF10) Then Call KeyF10
  1027.     If (KH = KeyboardF11) Then Call KeyF11
  1028.     If (KH = KeyboardF12) Then Call KeyF12
  1029.     If (KH = KeyboardHome) Then Call KeyHome
  1030.     If (KH = KeyboardUpArrow) Then Call KeyUpArrow
  1031.     If (KH = KeyboardPgUp) Then Call KeyPgUp
  1032.     If (KH = KeyboardLeftArrow) Then Call KeyLeftArrow
  1033.     If (KH = KeyboardRightArrow) Then Call KeyRightArrow
  1034.     If (KH = KeyboardEnd) Then Call KeyEnd
  1035.     If (KH = KeyboardDnArrow) Then Call KeyDwnArrow
  1036.     If (KH = KeyboardPgDn) Then Call KeyPgDn
  1037.     If (KH = KeyboardIns) Then Call KeyIns
  1038.     If (KH = KeyboardDel) Then Call KeyDel
  1039.  
  1040.     ' Exit sequence
  1041.     TheReturn = 0
  1042.     If ((MH <> 0) Or (KH > 0)) Then
  1043.         TheReturn = 1
  1044.         Call MapText
  1045.         Call CalibrateCursor(ID1)
  1046.         Call CalibrateCursor(ID2)
  1047.  
  1048.         ' Cursor sync and autoscrolling.
  1049.         Do While (Cursor1.Y > TopIndent + TextHeight - 1)
  1050.             StartIndex = NthP&(StartIndex, Len(LineAsMapped(1)) + 1)
  1051.             Call MapText
  1052.             Call CalibrateCursor(ID1)
  1053.             Call CalibrateCursor(ID2)
  1054.         Loop
  1055.         If (TextWrapping = 2) Then '''
  1056.             Do While (Cursor1.X > LeftIndent + TextWidth - 0)
  1057.                 HScroll = HScroll + 1
  1058.                 Cursor1.X = Cursor1.X - 1
  1059.             Loop
  1060.         End If
  1061.  
  1062.     End If
  1063.     MH = 0
  1064.     KH = 0
  1065.     _KeyClear
  1066.     StateChange% = TheReturn
  1067.  
  1068. Function MouseButton1%
  1069.     Dim As Double mx, my
  1070.     mx = _MouseX ' Int(_MouseX / 8)
  1071.     my = _MouseY ' Int(_MouseY / 16)
  1072.     If ((mx > LeftIndent) And (mx < TextWidth + LeftIndent + 1) And (my > TopIndent) And (my < TopIndent + TextHeight)) Then
  1073.         Call MouseButton1Cursor
  1074.     End If
  1075.     If (mx = WindowWidth) Then
  1076.         Call MouseButton1VScroll
  1077.     End If
  1078.     If (my = WindowHeight - 1) Then
  1079.         Call MouseButton1Hscroll
  1080.     End If
  1081.     MouseButton1% = 1
  1082.  
  1083. Sub MouseButton1VScroll
  1084.     ' This sub does things wrong.
  1085.     Dim i As Long
  1086.     Dim j As Long
  1087.     Dim k As Long
  1088.     Dim t As Long
  1089.     Dim r As Double
  1090.     Dim f As Double
  1091.     Dim As Double mx, my
  1092.     mx = _MouseX ' Int(_MouseX / 8)
  1093.     my = _MouseY ' Int(_MouseY / 16)
  1094.     If ((my > TopIndent) And (my < (TopIndent + TextHeight))) Then
  1095.         i = NthL&(ID1, ChainLimit + 1)
  1096.         j = NthP&(ID1, ChainLimit + 1)
  1097.         If (my = 1 + TopIndent) Then
  1098.             i = i ' clicked at top
  1099.         ElseIf (my = (TopIndent + TextHeight - 1)) Then
  1100.             i = j ' clicked at bottom
  1101.         Else
  1102.             t = LinearCount&(i, j)
  1103.             f = (my - TopIndent + 1) / (WindowHeight - TopIndent)
  1104.             For k = 1 To t
  1105.                 r = k / t
  1106.                 If (r >= f) Then Exit For
  1107.                 i = TheChain(i).Pointer
  1108.             Next
  1109.             If (TextWrapping <> 2) Then
  1110.                 'i = BackBreak&(i)
  1111.             End If
  1112.         End If
  1113.         StartIndex = i
  1114.         ID1 = i
  1115.     End If
  1116.  
  1117. Sub MouseButton1Hscroll
  1118.     Dim i As Long
  1119.     Dim j As Long
  1120.     Dim k As Integer
  1121.     Dim t As Integer
  1122.     Dim r As Double
  1123.     Dim f As Double
  1124.     Dim As Double mx, my
  1125.     mx = _MouseX ' Int(_MouseX / 8)
  1126.     my = _MouseY ' Int(_MouseY / 16)
  1127.     If ((mx > LeftIndent) And (mx < (LeftIndent + 1 + TextWidth))) Then
  1128.         j = ID1
  1129.         i = NthP&(StartIndex, FindID%(LeftIndent + 1, Cursor1.Y))
  1130.         t = Len(LineAsMapped(Cursor1.Y - TopIndent))
  1131.         f = (mx - LeftIndent) / (WindowWidth - LeftIndent)
  1132.         For k = 1 To t
  1133.             r = k / t
  1134.             If (r >= f) Then Exit For
  1135.             i = TheChain(i).Pointer
  1136.         Next
  1137.         ID1 = i
  1138.         k = LinearCount&(StartIndex, i) - LinearCount&(StartIndex, j)
  1139.         If (TextWrapping = 2) Then HScroll = HScroll + k
  1140.         If (HScroll < 1) Then HScroll = 1
  1141.     End If
  1142.  
  1143. Sub MouseButton1Cursor
  1144.     Dim k As Integer
  1145.     Dim As Double mx, my
  1146.     mx = _MouseX ' Int(_MouseX / 8)
  1147.     my = _MouseY ' Int(_MouseY / 16)
  1148.     Cursor1.X = mx
  1149.     k = LeftIndent + Len(LineAsMapped(my - TopIndent)) - (HScroll - 1)
  1150.     If (Cursor1.X > k) Then
  1151.         If (k < 0) Then
  1152.             If (Len(LineAsMapped(my - TopIndent)) > TextWidth) Then
  1153.                 HScroll = 1 + Len(LineAsMapped(my - TopIndent)) - (Cursor1.X - LeftIndent)
  1154.             Else
  1155.                 HScroll = 1
  1156.                 Cursor1.X = LeftIndent + Len(LineAsMapped(my - TopIndent))
  1157.             End If
  1158.         Else
  1159.             Cursor1.X = k
  1160.         End If
  1161.     End If
  1162.     Cursor1.Y = my
  1163.     Call ReassignID1
  1164.  
  1165. Function MouseButton2%
  1166.     ' Move Cursor2.
  1167.     Dim k As Integer
  1168.     Dim As Double mx, my
  1169.     mx = _MouseX ' Int(_MouseX / 8)
  1170.     my = _MouseY ' Int(_MouseY / 16)
  1171.     If (mx > LeftIndent) And (mx < TextWidth + LeftIndent + 1) And (my > TopIndent) And (my < TopIndent + TextHeight + 1) Then
  1172.         Cursor2.X = mx
  1173.         k = LeftIndent + Len(LineAsMapped(my - TopIndent)) - (HScroll - 1)
  1174.         If (Cursor2.X > k) Then
  1175.             If (k < 0) Then
  1176.             Else
  1177.                 Cursor2.X = k
  1178.             End If
  1179.         End If
  1180.         Cursor2.Y = my
  1181.         Call ReassignID2
  1182.     End If
  1183.     MouseButton2% = 1
  1184.  
  1185. Function MouseButton3%
  1186.     Call PasteClipboard(ID1, _Clipboard$)
  1187.     MouseButton3% = 1
  1188.  
  1189. Function MouseWheelUp%
  1190.     Call KeyUpArrow
  1191.     MouseWheelUp% = 1
  1192.  
  1193. Function MouseWheelDown%
  1194.     Call KeyDwnArrow
  1195.     MouseWheelDown% = 1
  1196.  
  1197. Sub KeyBksp
  1198.     Dim qq As Long
  1199.     Dim q As Long
  1200.     Dim p As Long
  1201.     q = TheChain(ID1).Lagger
  1202.     p = TheChain(ID1).Pointer
  1203.     If (q = BOC) Then
  1204.         ' Do nothing.
  1205.     End If
  1206.     If (q <> BOC) Then
  1207.         If ((TextWrapping = 2) And (Cursor1.X - LeftIndent = 1)) Then
  1208.             If (HScroll > 1) Then
  1209.                 HScroll = HScroll - 1
  1210.                 Call CalibrateCursor(ID1)
  1211.             End If
  1212.         End If
  1213.         qq = TheChain(q).Lagger
  1214.         TheChain(ID1).Lagger = qq
  1215.         TheChain(q).Identity = 0
  1216.         If (qq <> BOC) Then
  1217.             If (StartIndex = q) Then StartIndex = BackBreak&(StartIndex)
  1218.             TheChain(qq).Pointer = ID1
  1219.         End If
  1220.         If (qq = BOC) Then
  1221.             StartIndex = ID1
  1222.         End If
  1223.     End If
  1224.     ID2 = StartIndex
  1225.  
  1226. Sub KeyDel
  1227.     Dim i As _Integer64
  1228.     Dim q As Long
  1229.     Dim p As Long
  1230.     Dim q2 As Long
  1231.     Dim p2 As Long
  1232.  
  1233.     If (LinearCount(StartIndex, ID2) = LinearCount&(StartIndex, EOC)) Then
  1234.         i = -1
  1235.     Else
  1236.         i = LinearCount&(StartIndex, ID2) - LinearCount&(StartIndex, ID1)
  1237.     End If
  1238.  
  1239.     If (i <= 0) Then
  1240.         q = TheChain(ID1).Lagger
  1241.         p = TheChain(ID1).Pointer
  1242.         If (q = BOC) And (p = EOC) Then
  1243.             ' Never delete the only character.
  1244.             TheChain(ID1).Content = " "
  1245.         End If
  1246.         If (q <> BOC) And (p <> EOC) Then
  1247.             If (StartIndex = ID1) Then StartIndex = p
  1248.             TheChain(p).Lagger = q
  1249.             TheChain(ID1).Identity = 0
  1250.             TheChain(q).Pointer = p
  1251.             ID1 = p
  1252.         End If
  1253.         If ((q = BOC) And (p <> EOC)) Then
  1254.             StartIndex = p
  1255.             TheChain(p).Lagger = q
  1256.             TheChain(ID1).Identity = 0
  1257.             ID1 = p
  1258.         End If
  1259.         If ((q <> BOC) And (p = EOC)) Then
  1260.             If (StartIndex = ID1) Then StartIndex = q
  1261.             TheChain(ID1).Identity = 0
  1262.             TheChain(q).Pointer = p
  1263.             ID1 = q
  1264.         End If
  1265.     End If
  1266.  
  1267.     If (i > 0) Then
  1268.         q = TheChain(ID1).Lagger
  1269.         p = TheChain(ID1).Pointer
  1270.         q2 = TheChain(ID2).Lagger
  1271.         p2 = TheChain(ID2).Pointer
  1272.  
  1273.         If ((q <> BOC) And (p2 <> EOC)) Then
  1274.             If (StartIndex = ID1) Then StartIndex = p2
  1275.             Call UnlinkRange(ID1, ID2)
  1276.             ID1 = TheChain(q).Pointer
  1277.         End If
  1278.         If ((q = BOC) And (p2 <> EOC)) Then
  1279.             StartIndex = p2
  1280.             Call UnlinkRange(p, ID2)
  1281.             TheChain(p2).Lagger = q
  1282.             ID1 = p2
  1283.         End If
  1284.         If ((q <> BOC) And (p2 = EOC)) Then
  1285.             If (StartIndex = ID1) Then StartIndex = q
  1286.             Call UnlinkRange(ID1, q2)
  1287.             TheChain(ID2).Identity = 0
  1288.             TheChain(q).Pointer = p2
  1289.             ID1 = q
  1290.         End If
  1291.         If ((q = BOC) And (p2 = EOC)) Then
  1292.             StartIndex = ID1 '''
  1293.             Call UnlinkRange(p, q2)
  1294.             TheChain(ID2).Identity = 0
  1295.             TheChain(ID1).Content = " "
  1296.             TheChain(ID1).Lagger = BOC
  1297.             TheChain(ID1).Pointer = EOC
  1298.         End If
  1299.     End If
  1300.  
  1301.     ID2 = StartIndex
  1302.  
  1303. Sub UnlinkRange (a As Long, b As Long)
  1304.     Dim q As Long
  1305.     Dim u As Long
  1306.     Dim p As Long
  1307.     q = TheChain(a).Lagger
  1308.     u = a
  1309.     Do
  1310.         TheChain(u).Identity = 0
  1311.         p = TheChain(u).Pointer
  1312.         If (u = b) Then Exit Do
  1313.         If (p <> EOC) Then u = p
  1314.     Loop
  1315.     TheChain(p).Lagger = q
  1316.     If (q <> BOC) Then TheChain(q).Pointer = p
  1317.  
  1318. Sub KeyEsc
  1319.     If (ID2 <> ID1) Then
  1320.         ID2 = ID1
  1321.     Else
  1322.         ID2 = StartIndex
  1323.     End If
  1324.  
  1325. Sub KeyEnterAlphaNumer (k As Integer)
  1326.     Dim z As Long
  1327.     Dim a As String
  1328.     Dim b As String
  1329.     Dim c As String
  1330.     Dim n As Integer
  1331.     If (_KeyDown(KeyboardLeftCtrl) Or _KeyDown(KeyboardRightCtrl)) Then
  1332.  
  1333.         If (k = KeyboardEnter) Then
  1334.             z = BackBreak2&(ID1)
  1335.             a = Projection$(z, TheChain(ID1).Lagger)
  1336.  
  1337.             If (Left$(a, 1) = ">") Then
  1338.                 a = Right$(a, Len(a) - 1)
  1339.                 a = _Trim$(a)
  1340.                 a = pipecom_lite$(a)
  1341.                 Do While ((Right$(a, 1) = CR) Or (Right$(a, 1) = LF))
  1342.                     a = Left$(a, Len(a) - 1)
  1343.                 Loop
  1344.                 z = InsertString&(CR + "(" + a + ")" + CR + ">", ID1)
  1345.             End If
  1346.  
  1347.             If (Left$(a, 6) = "]save ") Then
  1348.                 a = Right$(a, Len(a) - 6)
  1349.                 n = InStr(a, " ")
  1350.                 b = Left$(a, n - 1)
  1351.                 c = Right$(a, Len(a) - n)
  1352.                 If (b <> "") Then
  1353.                     Open b For Output As #1
  1354.                     Print #1, c
  1355.                     Close #1
  1356.                     z = InsertString&(CR + "(" + b + ")" + CR + "]", ID1)
  1357.                 Else
  1358.                     z = InsertString&(CR + "(" + "Error" + ")" + CR + "]", ID1)
  1359.                 End If
  1360.             End If
  1361.  
  1362.             ID2 = StartIndex
  1363.         End If
  1364.  
  1365.  
  1366.         If (k = Asc("c")) Or (k = Asc("C")) Then
  1367.             _Clipboard$ = Projection$(ID1, ID2)
  1368.             ID2 = StartIndex
  1369.         End If
  1370.  
  1371.         If (k = Asc("v")) Or (k = Asc("V")) Then
  1372.             Call PasteClipboard(ID1, _Clipboard$)
  1373.             ID2 = StartIndex
  1374.         End If
  1375.  
  1376.         '''
  1377.     Else
  1378.  
  1379.         Call InsertCharacter(k)
  1380.  
  1381.         If ((k = KeyboardEnter) And (TextWrapping = 2)) Then HScroll = 1
  1382.         If ((k = KeyboardEnter) And (Cursor1.Y = TextHeight)) Then
  1383.             Call KeyDwnArrow
  1384.             Call KeyHome
  1385.         End If
  1386.  
  1387.     End If
  1388.  
  1389.  
  1390. Sub KeyF1
  1391.     Dim h0 As Integer
  1392.     h0 = HScroll
  1393.     Call KeyLeftArrow
  1394.     If (h0 = HScroll) Then
  1395.         If (TextWrapping = 2) Then
  1396.             HScroll = HScroll - 1
  1397.             If (HScroll < 1) Then HScroll = 1
  1398.         End If
  1399.     End If
  1400.  
  1401. Sub KeyF2
  1402.     Dim h0 As Integer
  1403.     h0 = HScroll
  1404.     Call KeyRightArrow
  1405.     If ((HScroll = h0) And (HScroll <> 1)) Then
  1406.         If (TextWrapping = 2) Then
  1407.             HScroll = HScroll + 1
  1408.         End If
  1409.     End If
  1410.  
  1411. Sub KeyF3
  1412.     Dim j As Integer
  1413.     Dim k As Integer
  1414.     For k = 2 To _Width - 1
  1415.         For j = Int(_Height / 3) - 2 To Int(_Height / 3) + 2
  1416.             Color BackgroundColor, BackgroundColor
  1417.             Call StringPrint("", k, j, " ")
  1418.         Next
  1419.         Color Cursor1Back, Cursor1Back
  1420.         Call StringPrint("", k, Int(_Height / 3) - 2, " ")
  1421.         Color Cursor1Back, Cursor1Back
  1422.         Call StringPrint("", k, Int(_Height / 3) + 2, " ")
  1423.     Next
  1424.     Color TextFaceColor, BackgroundColor
  1425.     Cls
  1426.     Locate 1, 1: Line Input "Text to highlight: ", Highlight
  1427.  
  1428. Sub KeyF4
  1429.     Cursor1.X = LeftIndent + 1
  1430.     Call ReassignID1
  1431.     Cursor2.X = LeftIndent + Len(LineAsMapped(Cursor1.Y - TopIndent))
  1432.     Cursor2.Y = Cursor1.Y
  1433.     Call ReassignID2
  1434.  
  1435. Sub KeyF5
  1436.     Dim a As Long
  1437.     Dim b As Long
  1438.     Dim c As String
  1439.     Dim k As Long
  1440.     a = NthL&(ID1, ChainLimit + 1)
  1441.     b = NthP&(ID1, ChainLimit + 1)
  1442.     c = Projection$(a, b) + CR
  1443.     For k = 1 To ChainLimit
  1444.         TheChain(k).Identity = 0
  1445.     Next
  1446.     a = Assimilate&(c, BOC, EOC)
  1447.  
  1448. Sub KeyF6
  1449.     Dim c As String
  1450.     Open WorkingFileName For Output As #1
  1451.     c = Projection$(NthL&(ID1, ChainLimit + 1), NthP&(ID1, ChainLimit + 1))
  1452.     Print #1, c
  1453.     Close #1
  1454.  
  1455. Sub KeyF7
  1456.     GOLSwitch = -GOLSwitch
  1457.  
  1458. Sub KeyF10
  1459.     ColorTheme = -ColorTheme
  1460.     Call SetPalette
  1461.  
  1462. Sub KeyF11
  1463.     TextFormatting = -TextFormatting
  1464.  
  1465. Sub KeyF12
  1466.     TextWrapping = TextWrapping + 1
  1467.     If (TextWrapping > 2) Then
  1468.         TextWrapping = 0
  1469.     End If
  1470.     If (TextWrapping <> 2) Then
  1471.         HScroll = 1
  1472.     End If
  1473.  
  1474. Sub KeyHome
  1475.     If (TextWrapping = 2) Then HScroll = 1
  1476.     Cursor1.X = LeftIndent + 1
  1477.     Call ReassignID1
  1478.  
  1479. Sub KeyUpArrow
  1480.     Dim k As Integer
  1481.     If (Cursor1.Y > TopIndent + 1) Then
  1482.         Cursor1.Y = Cursor1.Y - 1
  1483.     Else
  1484.         StartIndex = BackBreak&(StartIndex)
  1485.     End If
  1486.     k = LeftIndent + Len(LineAsMapped(Cursor1.Y - TopIndent)) - (HScroll - 1)
  1487.     If (Cursor1.X > k) Then
  1488.         If (k < 0) Then
  1489.             If (Len(LineAsMapped(Cursor1.Y - TopIndent)) > TextWidth) Then
  1490.                 HScroll = 1 + Len(LineAsMapped(Cursor1.Y - TopIndent)) - (Cursor1.X - LeftIndent)
  1491.             Else
  1492.                 HScroll = 1
  1493.                 Cursor1.X = LeftIndent + Len(LineAsMapped(Cursor1.Y - TopIndent))
  1494.             End If
  1495.         Else
  1496.             Cursor1.X = k
  1497.         End If
  1498.     End If
  1499.     Call ReassignID1
  1500.  
  1501. Sub KeyPgUp
  1502.     Dim k As Integer
  1503.     For k = 1 To Int(TextHeight / 2)
  1504.         StartIndex = BackBreak&(StartIndex)
  1505.     Next
  1506.     Call ReassignID1
  1507.  
  1508. Sub KeyLeftArrow
  1509.     Dim j As Integer
  1510.     Dim k As Integer
  1511.     ID1 = NthL&(ID1, 2)
  1512.     If (TextWrapping = 2) Then
  1513.         If (Cursor1.X = LeftIndent + 1) Then
  1514.             If (HScroll > 1) Then
  1515.                 HScroll = HScroll - 1
  1516.             Else
  1517.                 j = Cursor1.Y - TopIndent - 1
  1518.                 If (j >= 1) Then
  1519.                     k = Len(LineAsMapped(j)) - TextWidth + 1
  1520.                     If (k >= 1) Then
  1521.                         HScroll = k
  1522.                     End If
  1523.                 End If
  1524.             End If
  1525.         End If
  1526.     Else
  1527.         If ((Cursor1.X - LeftIndent = 1) And Cursor1.Y - TopIndent = 1) Then
  1528.             StartIndex = BackBreak&(StartIndex)
  1529.         End If
  1530.     End If
  1531.  
  1532. Sub KeyRightArrow
  1533.     Dim i As Integer
  1534.     Dim j As Integer
  1535.     Dim k As Integer
  1536.     ID1 = NthP&(ID1, 2)
  1537.     i = Cursor1.X - LeftIndent
  1538.     j = Len(LineAsMapped(Cursor1.Y - TopIndent)) - HScroll + 1
  1539.     If (TextWrapping = 2) Then
  1540.         If (i >= TextWidth) Then
  1541.             HScroll = HScroll + 1
  1542.             Call ReassignID1
  1543.         End If
  1544.         If (i >= j) Then
  1545.             k = Cursor1.Y - TopIndent + 1
  1546.             If ((k <= TextHeight) And (VisibleLines > 1)) Then HScroll = 1
  1547.         End If
  1548.     Else
  1549.         If ((i >= j) And (Cursor1.Y - TopIndent = VisibleLines)) Then
  1550.             If (VisibleLines > 1) Then StartIndex = NthP&(StartIndex, Len(LineAsMapped(1)) + 1)
  1551.         End If
  1552.     End If
  1553.  
  1554. Sub KeyEnd
  1555.     Dim k As Integer
  1556.     If (TextWrapping <> 2) Then
  1557.         Cursor1.X = LeftIndent + Len(LineAsMapped(Cursor1.Y - TopIndent))
  1558.         Call ReassignID1
  1559.     End If
  1560.     If (TextWrapping = 2) Then
  1561.         Do
  1562.             If (TheChain(ID1).Content = CR) Then Exit Do
  1563.             If (TheChain(ID1).Pointer = EOC) Then Exit Do
  1564.             ID1 = TheChain(ID1).Pointer
  1565.         Loop
  1566.         k = Len(LineAsMapped(Cursor1.Y - TopIndent)) - TextWidth + 1
  1567.         If (k >= 1) Then
  1568.             HScroll = k
  1569.             Call CalibrateCursor(ID1)
  1570.         End If
  1571.     End If
  1572.  
  1573. Sub KeyTab
  1574.     Dim z As Long
  1575.     z = InsertString&(Chr$(KeyboardTab), ID1)
  1576.  
  1577. Sub KeyDwnArrow
  1578.     Dim k As Integer
  1579.     If (Cursor1.Y = TopIndent + VisibleLines) Then
  1580.         If (VisibleLines > 1) Then
  1581.             StartIndex = NthP&(StartIndex, Len(LineAsMapped(1)) + 1)
  1582.             Call MapText
  1583.         End If
  1584.     Else
  1585.         Cursor1.Y = Cursor1.Y + 1
  1586.     End If
  1587.     k = LeftIndent + Len(LineAsMapped(Cursor1.Y - TopIndent)) - (HScroll - 1)
  1588.     If (Cursor1.X > k) Then
  1589.         If (k < 0) Then
  1590.             If (Len(LineAsMapped(Cursor1.Y - TopIndent)) > TextWidth) Then
  1591.                 HScroll = 1 + Len(LineAsMapped(Cursor1.Y - TopIndent)) - (Cursor1.X - LeftIndent)
  1592.             Else
  1593.                 HScroll = 1
  1594.                 Cursor1.X = LeftIndent + Len(LineAsMapped(Cursor1.Y - TopIndent))
  1595.             End If
  1596.         Else
  1597.             Cursor1.X = k
  1598.         End If
  1599.     End If
  1600.     Call ReassignID1
  1601.  
  1602. Sub KeyPgDn
  1603.     Dim k As Integer
  1604.     For k = 1 To Int(TextHeight / 2)
  1605.         If (VisibleLines > 1) Then
  1606.             StartIndex = NthP&(StartIndex, Len(LineAsMapped(1)) + 1)
  1607.             Call MapText
  1608.         End If
  1609.     Next
  1610.     Call ReassignID1
  1611.  
  1612. Sub KeyIns
  1613.     InsertKey = -InsertKey
  1614.  
  1615. Sub ConvertToGrid
  1616.     Dim i As Integer
  1617.     Dim j As Integer
  1618.     Dim c As String
  1619.     For j = 1 To VisibleLines
  1620.         c = LineAsMapped(j)
  1621.         For i = 1 To Len(c) - 1 ' BR offset to exclude CR at line end.
  1622.             AuxGrid(i, j, 1) = Mid$(c, i, 1)
  1623.         Next
  1624.     Next
  1625.  
  1626. Sub ConvertFromGrid
  1627.     Dim i As Integer
  1628.     Dim j As Integer
  1629.     Dim k As Long
  1630.     Dim c As String
  1631.     c = ""
  1632.     For j = 1 To VisibleLines
  1633.         For i = 1 To Len(LineAsMapped(j)) - 1
  1634.             c = c + AuxGrid(i, j, 1)
  1635.         Next
  1636.         c = c + CR ' Undoes BR offset.
  1637.     Next
  1638.     For k = 1 To ChainLimit
  1639.         TheChain(k).Identity = 0
  1640.     Next
  1641.     k = Assimilate&(c, BOC, EOC)
  1642.  
  1643. Sub GOL
  1644.     Dim i As Integer
  1645.     Dim j As Integer
  1646.     Dim c As String
  1647.     Dim a1 As Integer
  1648.     Dim a2 As Integer
  1649.     Dim a3 As Integer
  1650.     Dim a4 As Integer
  1651.     Dim a6 As Integer
  1652.     Dim a7 As Integer
  1653.     Dim a8 As Integer
  1654.     Dim a9 As Integer
  1655.     Dim t As Integer
  1656.     For j = 1 To VisibleLines
  1657.         For i = 1 To Len(LineAsMapped(j)) - 1
  1658.             c = AuxGrid(i, j, 1)
  1659.             If (c = " ") Then c = "0" Else c = "1"
  1660.             AuxGrid(i, j, 1) = c
  1661.             AuxGrid(i, j, 2) = c
  1662.         Next
  1663.     Next
  1664.     For j = 2 To VisibleLines - 2 ' BR offset.
  1665.         For i = 2 To Len(LineAsMapped(j)) - 2 ' BR offset.
  1666.             c = AuxGrid(i, j, 1)
  1667.             a1 = Val(AuxGrid(i - 1, j + 1, 1))
  1668.             a2 = Val(AuxGrid(i, j + 1, 1))
  1669.             a3 = Val(AuxGrid(i + 1, j + 1, 1))
  1670.             a4 = Val(AuxGrid(i - 1, j, 1))
  1671.             a6 = Val(AuxGrid(i + 1, j, 1))
  1672.             a7 = Val(AuxGrid(i - 1, j - 1, 1))
  1673.             a8 = Val(AuxGrid(i, j - 1, 1))
  1674.             a9 = Val(AuxGrid(i + 1, j - 1, 1))
  1675.             t = a1 + a2 + a3 + a4 + a6 + a7 + a8 + a9
  1676.             If (c = "1") Then
  1677.                 Select Case t
  1678.                     Case Is < 2
  1679.                         AuxGrid(i, j, 2) = "0"
  1680.                     Case 2
  1681.                         AuxGrid(i, j, 2) = "1"
  1682.                     Case 3
  1683.                         AuxGrid(i, j, 2) = "1"
  1684.                     Case Is > 3
  1685.                         AuxGrid(i, j, 2) = "0"
  1686.                 End Select
  1687.             Else
  1688.                 If (t = 3) Then AuxGrid(i, j, 2) = "1"
  1689.             End If
  1690.         Next
  1691.     Next
  1692.     For j = 1 To VisibleLines
  1693.         For i = 1 To Len(LineAsMapped(j)) - 1
  1694.             c = AuxGrid(i, j, 2)
  1695.             If (c = "0") Then c = " " Else c = Chr$(219)
  1696.             AuxGrid(i, j, 1) = c
  1697.             AuxGrid(i, j, 2) = c
  1698.         Next
  1699.     Next
  1700.  
  1701. '''
  1702.  
  1703. $If PIPECOM = UNDEFINED Then
  1704.     $Let PIPECOM = TRUE
  1705.     Function pipecom& (cmd As String, stdout As String, stderr As String)
  1706.         stdout = "": stderr = ""
  1707.         $If WIN Then
  1708.             Type SECURITY_ATTRIBUTES
  1709.                 As _Unsigned Long nLength
  1710.                 $If 64BIT Then
  1711.                     As String * 4 padding
  1712.                 $End If
  1713.                 As _Offset lpSecurityDescriptor
  1714.                 As Long bInheritHandle
  1715.                 $If 64BIT Then
  1716.                     As String * 4 padding2
  1717.                 $End If
  1718.             End Type
  1719.  
  1720.             Type STARTUPINFO
  1721.                 As Long cb
  1722.                 $If 64BIT Then
  1723.                     As String * 4 padding
  1724.                 $End If
  1725.                 As _Offset lpReserved, lpDesktop, lpTitle
  1726.                 As _Unsigned Long dwX, dwY, dwXSize, dwYSize, dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags
  1727.                 As _Unsigned Integer wShowWindow, cbReserved2
  1728.                 $If 64BIT Then
  1729.                     As String * 4 padding2
  1730.                 $End If
  1731.                 As _Offset lpReserved2, hStdInput, hStdOutput, hStdError
  1732.             End Type
  1733.  
  1734.             Type PROCESS_INFORMATION
  1735.                 As _Offset hProcess, hThread
  1736.                 As _Unsigned Long dwProcessId
  1737.                 $If 64BIT Then
  1738.                     As String * 4 padding
  1739.                 $End If
  1740.             End Type
  1741.  
  1742.             Const STARTF_USESTDHANDLES = &H00000100
  1743.             Const CREATE_NO_WINDOW = &H8000000
  1744.  
  1745.             Const INFINITE = 4294967295
  1746.             Const WAIT_FAILED = &HFFFFFFFF
  1747.  
  1748.             Declare CustomType Library
  1749.                 Function CreatePipe& (ByVal hReadPipe As _Offset, Byval hWritePipe As _Offset, Byval lpPipeAttributes As _Offset, Byval nSize As _Unsigned Long)
  1750.                 Function CreateProcess& (ByVal lpApplicationName As _Offset, Byval lpCommandLine As _Offset, Byval lpProcessAttributes As _Offset, Byval lpThreadAttributes As _Offset, Byval bInheritHandles As Long, Byval dwCreationFlags As _Unsigned Long, Byval lpEnvironment As _Offset, Byval lpCurrentDirectory As _Offset, Byval lpStartupInfo As _Offset, Byval lpProcessInformation As _Offset)
  1751.                 Function GetExitCodeProcess& (ByVal hProcess As _Offset, Byval lpExitCode As _Offset)
  1752.                 Sub HandleClose Alias "CloseHandle" (ByVal hObject As _Offset)
  1753.                 Function ReadFile& (ByVal hFile As _Offset, Byval lpBuffer As _Offset, Byval nNumberOfBytesToRead As _Unsigned Long, Byval lpNumberOfBytesRead As _Offset, Byval lpOverlapped As _Offset)
  1754.                 Function WaitForSingleObject~& (ByVal hHandle As _Offset, Byval dwMilliseconds As _Unsigned Long)
  1755.             End Declare
  1756.  
  1757.             Dim As Long ok: ok = 1
  1758.             Dim As _Offset hStdOutPipeRead, hStdOutPipeWrite, hStdReadPipeError, hStdOutPipeError
  1759.             Dim As SECURITY_ATTRIBUTES sa: sa.nLength = Len(sa): sa.lpSecurityDescriptor = 0: sa.bInheritHandle = 1
  1760.  
  1761.             If CreatePipe(_Offset(hStdOutPipeRead), _Offset(hStdOutPipeWrite), _Offset(sa), 0) = 0 Then
  1762.                 pipecom = -1
  1763.                 Exit Function
  1764.             End If
  1765.  
  1766.             If CreatePipe(_Offset(hStdReadPipeError), _Offset(hStdOutPipeError), _Offset(sa), 0) = 0 Then
  1767.                 pipecom = -1
  1768.                 Exit Function
  1769.             End If
  1770.  
  1771.             Dim As STARTUPINFO si
  1772.             si.cb = Len(si)
  1773.             si.dwFlags = STARTF_USESTDHANDLES
  1774.             si.hStdError = hStdOutPipeError
  1775.             si.hStdOutput = hStdOutPipeWrite
  1776.             si.hStdInput = 0
  1777.             Dim As PROCESS_INFORMATION procinfo
  1778.             Dim As _Offset lpApplicationName
  1779.             Dim As String lpCommandLine: lpCommandLine = "cmd /c " + cmd + Chr$(0)
  1780.             Dim As _Offset lpProcessAttributes, lpThreadAttributes
  1781.             Dim As Long bInheritHandles: bInheritHandles = 1
  1782.             Dim As _Unsigned Long dwCreationFlags: dwCreationFlags = CREATE_NO_WINDOW
  1783.             Dim As _Offset lpEnvironment, lpCurrentDirectory
  1784.             ok = CreateProcess(lpApplicationName, _Offset(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, _Offset(si), _Offset(procinfo))
  1785.  
  1786.             If ok = 0 Then
  1787.                 pipecom = -1
  1788.                 Exit Function
  1789.             End If
  1790.  
  1791.             HandleClose hStdOutPipeWrite
  1792.             HandleClose hStdOutPipeError
  1793.  
  1794.             Dim As String buf: buf = Space$(4096 + 1)
  1795.             Dim As _Unsigned Long dwRead
  1796.             While ReadFile(hStdOutPipeRead, _Offset(buf), 4096, _Offset(dwRead), 0) <> 0 And dwRead > 0
  1797.                 buf = Mid$(buf, 1, dwRead)
  1798.                 GoSub RemoveChr13
  1799.                 stdout = stdout + buf
  1800.                 buf = Space$(4096 + 1)
  1801.             Wend
  1802.  
  1803.             While ReadFile(hStdReadPipeError, _Offset(buf), 4096, _Offset(dwRead), 0) <> 0 And dwRead > 0
  1804.                 buf = Mid$(buf, 1, dwRead)
  1805.                 GoSub RemoveChr13
  1806.                 stderr = stderr + buf
  1807.                 buf = Space$(4096 + 1)
  1808.             Wend
  1809.  
  1810.             Dim As Long exit_code, ex_stat
  1811.             If WaitForSingleObject(procinfo.hProcess, INFINITE) <> WAIT_FAILED Then
  1812.                 If GetExitCodeProcess(procinfo.hProcess, _Offset(exit_code)) Then
  1813.                     ex_stat = 1
  1814.                 End If
  1815.             End If
  1816.  
  1817.             HandleClose hStdOutPipeRead
  1818.             HandleClose hStdReadPipeError
  1819.             If ex_stat = 1 Then
  1820.                 pipecom = exit_code
  1821.             Else
  1822.                 pipecom = -1
  1823.             End If
  1824.  
  1825.             Exit Function
  1826.  
  1827.             RemoveChr13:
  1828.             Dim As Long j
  1829.             j = InStr(buf, Chr$(13))
  1830.             Do While j
  1831.                 buf = Left$(buf, j - 1) + Mid$(buf, j + 1)
  1832.                 j = InStr(buf, Chr$(13))
  1833.             Loop
  1834.             Return
  1835.         $Else
  1836.             Declare CustomType Library
  1837.             Function popen%& (cmd As String, readtype As String)
  1838.             Function feof& (ByVal stream As _Offset)
  1839.             Function fgets$ (str As String, Byval n As Long, Byval stream As _Offset)
  1840.             Function pclose& (ByVal stream As _Offset)
  1841.             End Declare
  1842.  
  1843.             Declare Library
  1844.             Function WEXITSTATUS& (ByVal stat_val As Long)
  1845.             End Declare
  1846.  
  1847.             Dim As _Offset stream
  1848.  
  1849.             Dim buffer As String * 4096
  1850.             If _FileExists("pipestderr") Then
  1851.             Kill "pipestderr"
  1852.             End If
  1853.             stream = popen(cmd + " 2>pipestderr", "r")
  1854.             If stream Then
  1855.             While feof(stream) = 0
  1856.             If fgets(buffer, 4096, stream) <> "" And feof(stream) = 0 Then
  1857.             stdout = stdout + Mid$(buffer, 1, InStr(buffer, Chr$(0)) - 1)
  1858.             End If
  1859.             Wend
  1860.             Dim As Long status, exit_code
  1861.             status = pclose(stream)
  1862.             exit_code = WEXITSTATUS(status)
  1863.             If _FileExists("pipestderr") Then
  1864.             Dim As Integer errfile
  1865.             errfile = FreeFile
  1866.             Open "pipestderr" For Binary As #errfile
  1867.             If LOF(errfile) > 0 Then
  1868.             stderr = Space$(LOF(errfile))
  1869.             Get #errfile, , stderr
  1870.             End If
  1871.             Close #errfile
  1872.             Kill "pipestderr"
  1873.             End If
  1874.             pipecom = exit_code
  1875.             Else
  1876.             pipecom = -1
  1877.             End If
  1878.         $End If
  1879.  
  1880.     Function pipecom_lite$ (cmd As String)
  1881.         Dim As Long a
  1882.         Dim As String stdout, stderr
  1883.         a = pipecom(cmd, stdout, stderr)
  1884.         If stderr <> "" Then
  1885.             pipecom_lite = stderr
  1886.         Else
  1887.             pipecom_lite = stdout
  1888.         End If
  1889.  

10
Programs / Binary Sequence Predictor "game"?
« on: December 09, 2021, 09:57:14 pm »
SKIP RIGHT TO THE BEST ANSWER -> https://www.qb64.org/forum/index.php?topic=4473.msg139248#msg139248
(Ignore everything between here and there.)

Alright I feel like not highjacking r1's thread anymore, so I will show this work here instead. What I've got is a thing that lets you type any random sequence of 1's and 0's, and the program will EERILY predict the next number. You can give this probably any pre-cooked, esoteric sequence you can think of - I know I did - and the program gets the next digit right.

Now, for the cases when you don't know the next digit - such as when you're whimsically flipping a coin or whatever - of course a program cannot *predict* that. That was never the goal, stay away from that straw man. What this thing *does*, is it will tell you the next digit in the sequence according to patterns you had no clue you were inputting. When I test this thing, trying to be random, I can always see why the answer it gives is the most "expected" next result. It's kinda wild.

So in this program, you get a prompt. Press 1011101000101 blah blah your heart's content. Then the thing shows you a few stats that you don't really need to see. For the curious, these are "scores" that say how random you are at different "frequencies". Finally, after a few of those screens, you get the final summary and the computer's prediction. Try this on a few sequences where you know what the next digit *should* be. Watch it get those right, and then "try to be random"... And watch the program understand what you type better than you do! Test data is still included but that mode is commented out.

Code: QB64: [Select]
  1.  
  2. ' Version: 5 OLD AS HELL, DO NOT RUN
  3.  
  4. Type LetterBin
  5.     Signature As String
  6.     Count As Integer
  7.  
  8. Dim Shared TheInput(1000, 2) As String
  9.  
  10. Dim Shared FingerPrint(16) As String
  11.  
  12. Dim Shared Alphabet1(2) As LetterBin
  13. Alphabet1(1).Signature = "0"
  14. Alphabet1(2).Signature = "1"
  15.  
  16. Dim Shared Alphabet2(4) As LetterBin
  17. Dim Shared Alphabet3(8) As LetterBin
  18. Dim Shared Alphabet4(16) As LetterBin
  19. Dim Shared Alphabet5(32) As LetterBin
  20. Dim Shared Alphabet6(64) As LetterBin
  21. Dim Shared Alphabet7(128) As LetterBin
  22. Dim Shared Alphabet8(256) As LetterBin
  23. Dim Shared Alphabet9(512) As LetterBin
  24. Dim Shared Alphabet10(1024) As LetterBin
  25. Dim Shared Alphabet11(2048) As LetterBin
  26. Dim Shared Alphabet12(4096) As LetterBin
  27. Dim Shared Alphabet13(8192) As LetterBin
  28.  
  29. Call NewAlphabet(Alphabet1(), Alphabet2())
  30. Call NewAlphabet(Alphabet2(), Alphabet3())
  31. Call NewAlphabet(Alphabet3(), Alphabet4())
  32. Call NewAlphabet(Alphabet4(), Alphabet5())
  33. Call NewAlphabet(Alphabet5(), Alphabet6())
  34. Call NewAlphabet(Alphabet6(), Alphabet7())
  35. Call NewAlphabet(Alphabet7(), Alphabet8())
  36. Call NewAlphabet(Alphabet8(), Alphabet9())
  37. Call NewAlphabet(Alphabet9(), Alphabet10())
  38. Call NewAlphabet(Alphabet10(), Alphabet11())
  39. Call NewAlphabet(Alphabet11(), Alphabet12())
  40. Call NewAlphabet(Alphabet12(), Alphabet13())
  41.  
  42. Call LoadInput
  43.  
  44.  
  45. m = 1
  46.  
  47.     Cls
  48.     Call Analyze(m)
  49.     Print
  50.     Print "Press ESC to try again."
  51.  
  52.     _KeyClear: Do: k = _KeyHit: _Limit 30: Loop Until k = 27: _KeyClear
  53.  
  54.     'Select Case k
  55.     '    Case 19712
  56.     '        m = m + 1
  57.     '    Case 19200
  58.     '        m = m - 1
  59.     '    Case Else
  60.     '        Cls: _Display
  61.     'End Select
  62.     '_KeyClear
  63.  
  64.  
  65.  
  66. Sub Analyze (TheIndex As Integer)
  67.     Dim actual As String
  68.     Dim k As Integer
  69.     Dim As Double p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13
  70.  
  71.     'FingerPrint(1) = TheInput(TheIndex, 1)
  72.     'actual = TheInput(TheIndex, 2)
  73.  
  74.     FingerPrint(1) = ""
  75.     actual = "?"
  76.     Do While (Len(FingerPrint(1)) < 32)
  77.         Print "Type random 1's and 0's and press Enter (at least 32, preferably way more):"
  78.         Print "  ................................"
  79.         _KeyClear
  80.         Input FingerPrint(1)
  81.         Print
  82.     Loop
  83.  
  84.     For k = 2 To UBound(FingerPrint)
  85.         FingerPrint(k) = Right$(FingerPrint(k - 1), Len(FingerPrint(k - 1)) - 1) + Left$(FingerPrint(k - 1), 1)
  86.     Next
  87.  
  88.     Call CreateHisto(Alphabet2(), 2)
  89.     Call CreateHisto(Alphabet3(), 3)
  90.     Call CreateHisto(Alphabet4(), 4)
  91.     Call CreateHisto(Alphabet5(), 5)
  92.     Call CreateHisto(Alphabet6(), 6)
  93.     Call CreateHisto(Alphabet7(), 7)
  94.     Call CreateHisto(Alphabet8(), 8)
  95.     Call CreateHisto(Alphabet9(), 9)
  96.     Call CreateHisto(Alphabet10(), 10)
  97.     Call CreateHisto(Alphabet11(), 11)
  98.     Call CreateHisto(Alphabet12(), 12)
  99.     Call CreateHisto(Alphabet13(), 13)
  100.  
  101.     Call PrintHisto(Alphabet2(), 0) ' Turn these numbers high to see stats for that alphabet.
  102.     Call PrintHisto(Alphabet3(), 10)
  103.     Call PrintHisto(Alphabet4(), 10)
  104.     Call PrintHisto(Alphabet5(), 10)
  105.     Call PrintHisto(Alphabet6(), 0)
  106.     Call PrintHisto(Alphabet7(), 0)
  107.     Call PrintHisto(Alphabet8(), 0)
  108.     Call PrintHisto(Alphabet9(), 5)
  109.     Call PrintHisto(Alphabet10(), 5)
  110.     Call PrintHisto(Alphabet11(), 5)
  111.     Call PrintHisto(Alphabet12(), 0)
  112.     Call PrintHisto(Alphabet13(), 0)
  113.  
  114.     p2 = MakeGuess(Alphabet2(), 2)
  115.     p3 = MakeGuess(Alphabet3(), 3)
  116.     p4 = MakeGuess(Alphabet4(), 4)
  117.     p5 = MakeGuess(Alphabet5(), 5)
  118.     p6 = MakeGuess(Alphabet6(), 6)
  119.     p7 = MakeGuess(Alphabet7(), 7)
  120.     p8 = MakeGuess(Alphabet8(), 8)
  121.     p9 = MakeGuess(Alphabet9(), 9)
  122.     p10 = MakeGuess(Alphabet10(), 10)
  123.     p11 = MakeGuess(Alphabet11(), 11)
  124.     p12 = MakeGuess(Alphabet12(), 12)
  125.     p13 = MakeGuess(Alphabet13(), 13)
  126.  
  127.     Cls
  128.     'Print "String ID:"; TheIndex
  129.     Print "Conclusions:"
  130.     Print
  131.     Print FingerPrint(1)
  132.     Print
  133.     Print "Thinking:  "; p2; p3; p4; p5; p6; p7; p8; p9; p10; p11; p12; p13
  134.     Print
  135.     Print "Predicted next number:"; (1 / 4) * (p10 + p11 + p12 + p13)
  136.     Print
  137.     'Print "Actual next number:    "; actual
  138.  
  139. Function MakeGuess (arr() As LetterBin, w As Integer)
  140.     Dim TheReturn As Double
  141.     Dim As Integer k
  142.     For k = 1 To UBound(arr)
  143.         If (Left$(arr(k).Signature, w - 1) = Right$(FingerPrint(1), w - 1)) Then
  144.             Print "..."; arr(k).Signature; arr(k).Count
  145.             TheReturn = Val(Right$(arr(k).Signature, 1))
  146.             If (arr(k).Count = 0) Then TheReturn = .5
  147.             Exit For
  148.         End If
  149.     Next
  150.     MakeGuess = TheReturn
  151.  
  152. Sub CreateHisto (arr() As LetterBin, w As Integer)
  153.     Dim As Integer m, n, k
  154.     For k = 1 To UBound(arr)
  155.         arr(k).Count = 0
  156.     Next
  157.     For m = 1 To w
  158.         For n = 1 To Len(FingerPrint(m)) - w Step w 'added the -w
  159.             For k = 1 To UBound(arr)
  160.                 If (Mid$(FingerPrint(m), n, w) = arr(k).Signature) Then
  161.                     arr(k).Count = arr(k).Count + 1
  162.                 End If
  163.             Next
  164.         Next
  165.     Next
  166.     Call BubbleSort(arr())
  167.  
  168. Sub NewAlphabet (arrold() As LetterBin, arrnew() As LetterBin)
  169.     Dim As Integer n, j, k
  170.     n = 0
  171.     For j = 1 To 2
  172.         For k = 1 To UBound(arrold)
  173.             n = n + 1
  174.             arrnew(n).Signature = arrold(k).Signature
  175.         Next
  176.     Next
  177.     For k = 1 To UBound(arrnew)
  178.         If (k <= UBound(arrnew) / 2) Then
  179.             arrnew(k).Signature = "0" + arrnew(k).Signature
  180.         Else
  181.             arrnew(k).Signature = "1" + arrnew(k).Signature
  182.         End If
  183.     Next
  184.  
  185. Sub PrintHisto (arr() As LetterBin, w As Integer)
  186.     Dim As Integer n, k
  187.     If (w > 0) Then
  188.         Cls
  189.         Print "Unscaled randomness scores (top "; _Trim$(Str$(w)); "), Alphabet size:"; UBound(arr)
  190.         If w > UBound(arr) Then k = UBound(arr) Else k = w
  191.         For n = 1 To k
  192.             Print arr(n).Signature; arr(n).Count
  193.         Next
  194.         Print
  195.         Print "Press any key..."
  196.         Sleep
  197.         _KeyClear
  198.         '_KeyClear: Do: k = _KeyHit: Loop Until k
  199.     End If
  200.  
  201. Sub BubbleSort (arr() As LetterBin)
  202.     Dim As Integer i, j
  203.     Dim As Integer u, v
  204.     For j = UBound(arr) To 1 Step -1
  205.         For i = 2 To UBound(arr)
  206.             u = arr(i - 1).Count
  207.             v = arr(i).Count
  208.             If (u < v) Then
  209.                 Swap arr(i - 1), arr(i)
  210.             End If
  211.         Next
  212.     Next
  213.  
  214. Sub LoadInput
  215.     Dim n As Integer
  216.     '''
  217.     n = 0
  218.     '''
  219.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "0"
  220.     n = n + 1: TheInput(n, 1) = "01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101": TheInput(n, 2) = "0"
  221.     n = n + 1: TheInput(n, 1) = "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010": TheInput(n, 2) = "1"
  222.     n = n + 1: TheInput(n, 1) = "00100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100": TheInput(n, 2) = "1"
  223.     n = n + 1: TheInput(n, 1) = "01001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001": TheInput(n, 2) = "0"
  224.     n = n + 1: TheInput(n, 1) = "10010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010010": TheInput(n, 2) = "0"
  225.     n = n + 1: TheInput(n, 1) = "00010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001": TheInput(n, 2) = "0"
  226.     n = n + 1: TheInput(n, 1) = "00100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010": TheInput(n, 2) = "0"
  227.     n = n + 1: TheInput(n, 1) = "01000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100": TheInput(n, 2) = "0"
  228.     n = n + 1: TheInput(n, 1) = "10001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000100010001000": TheInput(n, 2) = "1"
  229.     n = n + 1: TheInput(n, 1) = "00001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000": TheInput(n, 2) = "0"
  230.     n = n + 1: TheInput(n, 1) = "00010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000": TheInput(n, 2) = "1"
  231.     n = n + 1: TheInput(n, 1) = "00100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001": TheInput(n, 2) = "0"
  232.     n = n + 1: TheInput(n, 1) = "01000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010": TheInput(n, 2) = "0"
  233.     n = n + 1: TheInput(n, 1) = "10000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100": TheInput(n, 2) = "0"
  234.     n = n + 1: TheInput(n, 1) = "00000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100": TheInput(n, 2) = "0"
  235.     n = n + 1: TheInput(n, 1) = "00001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000": TheInput(n, 2) = "0"
  236.     n = n + 1: TheInput(n, 1) = "00010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000": TheInput(n, 2) = "0"
  237.     n = n + 1: TheInput(n, 1) = "00100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000100000": TheInput(n, 2) = "1"
  238.     n = n + 1: TheInput(n, 1) = "01000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001000001": TheInput(n, 2) = "0"
  239.     n = n + 1: TheInput(n, 1) = "10000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010000010": TheInput(n, 2) = "0"
  240.     n = n + 1: TheInput(n, 1) = "00000010000001000000100000010000001000000100000010000001000000100000010000001000000100000010000001000000100000010000001000000100": TheInput(n, 2) = "0"
  241.     n = n + 1: TheInput(n, 1) = "00100000010000001000000100000010000001000000100000010000001000000100000010000001000000100000010000001000000100000010000001000000": TheInput(n, 2) = "1"
  242.     n = n + 1: TheInput(n, 1) = "00000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001": TheInput(n, 2) = "0"
  243.     n = n + 1: TheInput(n, 1) = "10000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000100000001000000010000000": TheInput(n, 2) = "1"
  244.     n = n + 1: TheInput(n, 1) = "00110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011": TheInput(n, 2) = "0"
  245.     n = n + 1: TheInput(n, 1) = "01100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110": TheInput(n, 2) = "0"
  246.     n = n + 1: TheInput(n, 1) = "11001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100": TheInput(n, 2) = "1"
  247.     n = n + 1: TheInput(n, 1) = "10011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001100110011001": TheInput(n, 2) = "1"
  248.     n = n + 1: TheInput(n, 1) = "00011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100": TheInput(n, 2) = "0"
  249.     n = n + 1: TheInput(n, 1) = "00111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000": TheInput(n, 2) = "1"
  250.     n = n + 1: TheInput(n, 1) = "01110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001": TheInput(n, 2) = "1"
  251.     n = n + 1: TheInput(n, 1) = "11100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011100011": TheInput(n, 2) = "1"
  252.     n = n + 1: TheInput(n, 1) = "11000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111000111": TheInput(n, 2) = "0"
  253.     n = n + 1: TheInput(n, 1) = "10001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110001110": TheInput(n, 2) = "0"
  254.     n = n + 1: TheInput(n, 1) = "01001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100": TheInput(n, 2) = "0"
  255.     n = n + 1: TheInput(n, 1) = "10011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000": TheInput(n, 2) = "1"
  256.     n = n + 1: TheInput(n, 1) = "00110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001": TheInput(n, 2) = "1"
  257.     n = n + 1: TheInput(n, 1) = "01100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011": TheInput(n, 2) = "1"
  258.     n = n + 1: TheInput(n, 1) = "11000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111010011000111": TheInput(n, 2) = "0"
  259.     n = n + 1: TheInput(n, 1) = "10001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110100110001110": TheInput(n, 2) = "1"
  260.     n = n + 1: TheInput(n, 1) = "00011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101001100011101": TheInput(n, 2) = "0"
  261.     n = n + 1: TheInput(n, 1) = "01001010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001": TheInput(n, 2) = "0"
  262.     n = n + 1: TheInput(n, 1) = "10010101010100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010": TheInput(n, 2) = "1"
  263.     n = n + 1: TheInput(n, 1) = "00101010101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101": TheInput(n, 2) = "0"
  264.     n = n + 1: TheInput(n, 1) = "01010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001010": TheInput(n, 2) = "1"
  265.     n = n + 1: TheInput(n, 1) = "10101010100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101": TheInput(n, 2) = "0"
  266.     n = n + 1: TheInput(n, 1) = "01010101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010": TheInput(n, 2) = "1"
  267.     n = n + 1: TheInput(n, 1) = "10101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001010101": TheInput(n, 2) = "0"
  268.     n = n + 1: TheInput(n, 1) = "01010100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010": TheInput(n, 2) = "0"
  269.     n = n + 1: TheInput(n, 1) = "10101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010100": TheInput(n, 2) = "0"
  270.     n = n + 1: TheInput(n, 1) = "01010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010001110100101010101001010101000": TheInput(n, 2) = "1"
  271.     n = n + 1: TheInput(n, 1) = "10100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010001": TheInput(n, 2) = "1"
  272.     n = n + 1: TheInput(n, 1) = "10100101010100011101001010101010010101010001110100101010101001010101000111010010101010100101010100011101001010101010010101010001": TheInput(n, 2) = "?"
  273.     n = n + 1: TheInput(n, 1) = "0001000001011100000011000100011000010010000000000000000011000000000000000001110010000000000001111000000001001110000000000000100000000011110000000000000000000000000000010100000000000000000100000000000000110001111000010001000000000000000000011010000000000000000010001101100000100001000000110011000011010010000000000000000000100001000011000110001010000000100000000000000000000000000000000000010000000000100000000000000010100000100000000000000000000000000000000000100001000000000000000010110100000000000010010000000000000000000100000000001100000011000000000000000000000000000000110010000110000100000": TheInput(n, 2) = "?"
  274.     '''
  275.     'n = 0
  276.     '''
  277.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  278.     n = n + 1: TheInput(n, 1) = "00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  279.     n = n + 1: TheInput(n, 1) = "00000100000101110000001100010001100001001000000000000000001100000000000000000111001000000000000111100000000100111000000000000010000000001111000000000000000000000000000001010000000000000000010000000000000011000111100001000100000000000000000001101000000000000000001000110110000010000100000011001100001101001000000000000000000010000100001100011000101000000010000000000000000000000000000000000001000000000010000000000000001010000010000000000000000000000000000000000010000100000000000000001011010000000000": TheInput(n, 2) = "?"
  280.     n = n + 1: TheInput(n, 1) = "00011101100000000001011100001011101000100111101100011000000011001010101000101000111111011000111000100000000000000110110000000001001001110110100001011011101100000011001010001111111110101100001101100001100011000111101100110000000101101101110000001110110111000011000110000000001101111000110000000011111100110001111000011101111101010011111111101111010011011001111101100010001100101101001011000010100111111101111010111111010110001100011000000100010001100111111001101101111000000010110111110000001011010011": TheInput(n, 2) = "?"
  281.     n = n + 1: TheInput(n, 1) = "00000000100000000000110000000000000000010000000000000000010000000000000000001000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000011000000000000000001000000001000000000000000000000000000000000000000001001011001000000000000110000000000000000000000000000000000100010000000000000000000000000000000000001100000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  282.     n = n + 1: TheInput(n, 1) = "01111011010110000100001000011001101101000011000011000000000100110010001010000100010000001110111000001000000000101110101100000000100011100101101110000010110101111001011010100000111011100110100001100100111010111110000010000110010000000100111100110000000101010100111001000000101000100101111001001001000010000100110011011010011011101000110011000000101000000100010000101101000101000110000100010101010111100000000001100000110010000001000011100001001000100000011100000101000001010101000100011010000100010011": TheInput(n, 2) = "?"
  283.     n = n + 1: TheInput(n, 1) = "11000110011000111000001101000010001000001110001001110010000110000111010001010001100010101100001111100000111100101100000011000111101101110010101101010000101010000001111100000111110101010000000011011100100110101100111101000000100100101000011010000000010110101010011001110011111000010001100110001111111001100010011100010101001100000101010101100000000001001010000011011100010011001000001001110111100110010010000010000111111101100011010101010101000111010110101000000010001001001011011011100101111110110010": TheInput(n, 2) = "?"
  284.     n = n + 1: TheInput(n, 1) = "10101101010001010110010110011111011111111101110100010011101110000000100011010000100111111001110110100011011110011101110001110011110000111011011110111011101100000010100111100010000010100111110010100100010001010101111000111010011101010111001110110000101101110001110010011101010110101110001111000101011001001101001011111101110010110101001100110010111101010111010010000010110100010001101110110101101110000101101010001001101101011000111110100000011101110010101111011110111110100110101001111101110001010110": TheInput(n, 2) = "?"
  285.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  286.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000100000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000": TheInput(n, 2) = "?"
  287.     n = n + 1: TheInput(n, 1) = "00000110110101110000001100100101000001001111101111100000011000000000001001000100011000000000100011100000100000001001000001000010000000010111001101000001100000010101100011010011111000100111010000000000001010001011101110010100000000000010001011101000010000100000101100110100000011111000000001110000010101010000111111110000000110000100111110011000100000010001010100000000000110000000011000100000000111110011110010000100001010000010011100000000010001101010000000000110010000000110000000110011000000000000": TheInput(n, 2) = "?"
  288.     n = n + 1: TheInput(n, 1) = "11011001010011000110101011011010000110001001010001001111100111001011110110111010001111010110010100100101011010110010010100111010111001101011100100001010011111111010011100101101000011011011000111011011010110111100110011100010100001101010110101110101110111010111010010011001110100011010011010101111101110100100100111101101001011100001001100100111010101100100101000111111111001001111100111010110111100001000000111101000111000001101011001001110001000010100110011111001001010101001110111010101111001100001": TheInput(n, 2) = "?"
  289.     n = n + 1: TheInput(n, 1) = "00000000000000000000010000000001100000000000000000000001010000000000110010000000000000000000000000000000000000000000000000001100000000000111000101000000000000000000000000000100010001000000000000000000000000000000001100010010000000000000000001100000000000000000000000000001000000000000000000000000000000000010000011000000000000010000000000000001000000001000000000000000000000000000000000000100100000000000100000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000": TheInput(n, 2) = "?"
  290.     n = n + 1: TheInput(n, 1) = "11101000011011010000101000100000010001001000000110011110001011010001001101101010001100111000000101001000011000001010010100010011100110101000101000000000010100111001010100010010101010100011000011000001011010000000010000000001011110110111000010000001011011100000000111001110100000110000000011000101100000001001000100110011000100100000100001001000000011010010100000000100100000101001100000110001001001110101010001000000011000000010101000110010000100001011000001101000101010011011001110010110000010000000": TheInput(n, 2) = "?"
  291.     n = n + 1: TheInput(n, 1) = "00000010100110101001001000100000010100100100101101010010000001001100000000001011001110011011000010000111111001100010110011000010100110110000000000011010011010010100100011011011001100110001101001110000101001001100100010001101001000001011111100011011100000011001001010111000000000111101111001111001111111101000000000101100011001001011011010010000100001100010011110010000001011000001010111010010011111001001001110111100110010000110100111101000000101110100101010001111001111101100010101001001010101000101": TheInput(n, 2) = "?"
  292.     n = n + 1: TheInput(n, 1) = "00111100000000000111001001100000111010010010010011100010001100001100000011011000100010000101110010110100110110011100010001111110011011000110010000001001101111111000011000010001101110011101111010100110100110000111011101001111110011011111100110111000001101101110001001001000011110100110000111110111010000001100100100100111110110100001001011100110111000100011110100100100110010011110011011100011101111010010000110000011101100000111001011000110000010001101111011111011001100000010000101000000000000101110": TheInput(n, 2) = "?"
  293.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  294.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000100000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000": TheInput(n, 2) = "?"
  295.     n = n + 1: TheInput(n, 1) = "00000000010111101100110000001011000001001011001100000001001100001001000001001100010000111111000011100001000000001111010010000100001000000010001101001011101011011010000101010011110110110001100001000010000010100011000000110001000000011101110001000000000000110000100000101100000001011010000101000000100100011000111111110010110101010100011110100110110000010001101000000000101001000010100110000100010100111000010010100100001000110000000100010100010000000010000100011100010010110100010000010010001001000010": TheInput(n, 2) = "?"
  296.     n = n + 1: TheInput(n, 1) = "11111111011001010010001100000100110110101110100011010010111011110100101000100000000101100000000100110010111110111000110101101010111111011101101010011111100100110100010011011001100000001110111110000101000000001100110101011110011111101100001110011101111100111100011100010010110111100001010000010001101001001111000000000101001000100100000110011000101011100100000100111011010110100000010001011010101011010010100111011000100011001000001010001011101010000100001011001011100001001011101110100110110010111100": TheInput(n, 2) = "?"
  297.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000010000000000000000000000000000000100000000100000000000000000000011100000000000000000000000000001000000000000000000000000000011001000000000000100000000000000000000000000010010000000000000000000000000000000000000000000000000000000000000000000000000000010001000000000000000000000000000000000000010000000000000000000000010000000000000000000000000000000000000000000000001001000000000011100000000000000001000000000000000000100000000100010000110100000000000000000000000000000000000": TheInput(n, 2) = "?"
  298.     n = n + 1: TheInput(n, 1) = "01011000100010001000011010000010010010000100100101000100011001000010000010110110010110001100010001000010110110000011010100000100100010010011111101111100110010101100000001000000100111010000010000100000000111100110000101110001100100000001000001001100100100010000001001000110000000000100011100110110000101100011100010110100000011001001011000010001001000101010010010000001000000100101100101001110110010010000100010100010000000100111001100000000001000111111010100001000001010000010101010110101101000001100": TheInput(n, 2) = "?"
  299.     n = n + 1: TheInput(n, 1) = "00000101000010010110000110001101111110010001110010000010101001111111010000011011100000110000010101101110101111110101001100000100000000100110001000000000000001110011101011011110000001000110101001000000000000010100010010110110000010001100100010011001010011111011001110110000110100010010000010010110011000010110110010101000111000000100000001101100100110010100110111001110110101010001101100000000110010100010000001000101011100000000000111101110101011001011001100100000001101110000001001101010000000111011": TheInput(n, 2) = "?"
  300.     n = n + 1: TheInput(n, 1) = "10100010000111100111110001101101100001100111001010011110011001101110100111000111001010100111100010110010101010100100100000101010111100100000010111001000101110010010111000001100011011001011010100101101101110001001111100110000001011100000010110011010001000001101101111001000011101001000110010110111100011111011001100011110100110100111001110000101010001010001101001101001011001111010011001101010000001111010110011100001010100011100110100011011110011100101000001110010010111100111110011001110011111001010": TheInput(n, 2) = "?"
  301.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  302.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000100000000000001100000000000000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000001000000000000100000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  303.     n = n + 1: TheInput(n, 1) = "00100000011101101100000000000000000000001010001010001010010000000011101000010100001000000110000110100000000010001000111100100100001010110000011000001010110100110011000010001000110101001001100001011000001000000000000010110000100000110000001001000000100000110100100100100001010011000000010101010010100101000000001011100010000000001100000110100010100010000001110000000100000001110010100100001110000001100110000100001000001000000000010000001000001000000001001100000000010011110100000000001010100001111111": TheInput(n, 2) = "?"
  304.     n = n + 1: TheInput(n, 1) = "01010110100011101001111011101011111111101001100000010100001001111110010111100011101100011111110001101101111000110011010011010011110000101111110110010001000001010100100100110011010010010110101011100000111111111101111110110011111101010011110000111101000010010011010000011100001000011011000011001101100011011101000101010101111011000100001111010100111001011100011100011011011000000010011010010100110010011001111011010010110011111000101110010111111100100100111110111010101001101011010100000001011010010000": TheInput(n, 2) = "?"
  305.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000100000001000000000000000000000000000000000000000001000000000000000000000000000000000000000010000000000000010010100000000000001000000000001000100000000000000000000001000000000000000000000000000000010000000010000000000000000000000001000000010000000000000000000000000000000000000000010000000110000000000000000000000001000000000010000100000000000000000100000001000000010000000000000000000000010000000000000000001000000000000000": TheInput(n, 2) = "?"
  306.     n = n + 1: TheInput(n, 1) = "00000001100010111010101010001001000011001100000000000000010011000111001101001010110010010010010100101010000001001000111000000010110000010001001110100000000101101001110100010100000101000100000101000000010000110000010011010000100101001111000000011110001000001101101100000001000101000000011001011001110111100010010001000011110011110010010001000001110100100010101001110000010100000010010100000000101001000100101000011000000001001010111010110100000011001100101010000000100100100111111001110101000100000001": TheInput(n, 2) = "?"
  307.     n = n + 1: TheInput(n, 1) = "11010010010101000010000011010000101110111010011001101000101111011101001110000001011110100101101111000100000010110001010101000110100001100000111000111100011110110011101101101111101010100100011101000000010010101110000011011100010010101110101010000001110001001111110011011101000010110000101111000000101100011100101100001001100001111110000101110000010010000001001010000000011011000001000101000100000111101100110011000111010000001000010000000000100101010001100001011000001010001000111111110110101000011111": TheInput(n, 2) = "?"
  308.     n = n + 1: TheInput(n, 1) = "11011111000111100000010011111111101111001100100010111010010000011000110100111010011000111101000111010000110110101010011010101011100110011101000001011011111110011100110100001001010000001000010010100101111011000101001000000011110011110001100100100011011001010000101101111110101011011100000111000111000011110101111011101000101010000111011110000111111101011101110110001000011000111011011011111100110000001011011010110101101111011001011000111100101100111010011100110111101100110110100110000010011111110101": TheInput(n, 2) = "?"
  309.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  310.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  311.     n = n + 1: TheInput(n, 1) = "00100000000000000011000000000000000000000110000010011111100000000000000001000000001000000000000000010110000110000001100010000000000011110000000001100000000000110011000011000000010000001110000000011000001000010000110100000010000000111101000000000000000000100000000001100000100011000000000100000000000101000000000011010000001100010100000110110010100001010000110000001000000001100000110000001100000000011010000000000000101001100000000000000000100000011010100000000010010000100100010000000000000001111000": TheInput(n, 2) = "?"
  312.     n = n + 1: TheInput(n, 1) = "00010100011101010101100000101000001100111001101101000000011001111001100110110111010111111011110001100000000001100000011001111000111001000110011010001110100110011001110111100000101000110001100110100111000111001000001001110101101110000000110000000000011001010101000110011101011001100011001001011001101100011110000101101001100011001010011000001100110000101000001111110110000000001100001100010010101111100101001101010000000110011011111100011111010000000101000000100101100111010110001101111010101010000110": TheInput(n, 2) = "?"
  313.     n = n + 1: TheInput(n, 1) = "00000010000000000001100000000000000001000000000000000000000000000000000000000000000001001000000000000000000100000000000000000000010000000000000000100100000101000001000000100001100000000000000000000000000010110000000000000000100001000000000000001000000001100010000000010000010000000000000110000000001000000000001000010000000000010000000000000000000000000000000000000100001000000000000100001000000000000000000100000000000100000000000000000000000001001000000000000000000001000010000000000010000011000000": TheInput(n, 2) = "?"
  314.     n = n + 1: TheInput(n, 1) = "11010000111110000000000011000001011000010011010100100000000000110011011101010010100100000000000000010001101001000001001010011000100101101000111011000001000010010000010000010100001000100110100001100100001001001001100011110010011000110111000011000000011000000000100110001000101101100000001000000000000100000000000001001110001110100000010100001011101010110100001001001000000010010100001010100111011111000100001010000011010001000011001101110001101110000011010101101001010100110100010001011100110100110111": TheInput(n, 2) = "?"
  315.     n = n + 1: TheInput(n, 1) = "00000000110110001000000011001000100000001110011010100010101101111100101100101000001010000000101101010100101011010000010001001110001001100001110101011010111010000100001011001010010100011001011000010000100001000000000100001111001000101011111110100001110010011000100001101000101001101011110001011111000110111010010101000001001011101101110000001011110000011001100011111001010100010101110011000100110000101101010010110000000000010011001001101101000010000010001110000011111100111101100100110000001000110000": TheInput(n, 2) = "?"
  316.     n = n + 1: TheInput(n, 1) = "00101101111001100011001000011101001000000001100000101001000010110101000011001101110010110011000010101100111010101111100101100111000010110111010100000000001010000111111011001000111011100100011111101010010101011111111010010110010001101010100101010110111010111000101111001101001101101111010101010010110001000110110110101000010100001000010011101010011110001000001111001100110001011010100011101011100000100000111001000111001010101111010010010100110111001000100011010110100011111011101001101010111101101010": TheInput(n, 2) = "?"
  317.     n = n + 1: TheInput(n, 1) = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000": TheInput(n, 2) = "?"
  318.     n = n + 1: TheInput(n, 1) = "10000000100000000000000001001001000000100011010001010100000100000000010101100110101000000000000100000101010000000101000000000101100000000000010000001000001011000110100110100010010100010111000100000100001010000000101010001000111001000000010000100100000000000000100000001001000000110001010001001010010000000010101001000111011000100100100000010010000100100000000000001000010010000110010110000110100000000000101001010100000110010001110000111000000110000000000000000000000100101100001010000100000101100010": TheInput(n, 2) = "?"
  319.     n = n + 1: TheInput(n, 1) = "00001101011011101101111110010000011011010000101110101011001001111000101010010001010111100001110011011010100011011010101010111010001010100110101100000110110100101001011001010000001010100000111010111011100100110111010101010100000010000010101110001011010011001111011110110000110010001010001000110100101111101100000110111000000000000010001111101001011011010111110110000100101000111000101001110001010011110100010100100011110000001100001011000100100000011110111111100011000011000011100101111010111010010101": TheInput(n, 2) = "?"
  320.     n = n + 1: TheInput(n, 1) = "01110011000100111110101110110110101110011100101000000011111010011111101010001000000000111110011010111010001110111000111111010010011101111101100111110001000000011000001000001101101001001000010001011000010001111100010001100111000100111111100011010001101101110110000001010110001111000100101110010001101101010001010110110000100111011001010100101101110000001111001111110111100101101001001001111001011111111011000010101001001001101010001111000011011001111111001011111101111001010010110000100001010000011000": TheInput(n, 2) = "?"
  321.     '''
[/s]

11
Programs / Digital Circuit Simulator
« on: December 07, 2021, 08:33:55 pm »
Hello all, time for a mega-post.

Intro:

I was recently motivated to code something that produces much more than it assumes. Projects like this are usually more egg-headed, like creating programming languages, experimental computation paradigms, cellular automata, and so on. After fiddling with each of these for a while, I settled on something that should have been obvious from the start: binary circuits. After all, these are what computers are made of, so I should be able to simulate these kinds of things on a computer.

Remarks:

After deciding on a proper data structure, the evaluation algorithm turned out to be quite simple to code. This thing works for highly parallelized, feedback-ridden, super ugly circuits, as well as pretty circuits. In fact, it's behavior is... dare I say 100% like what you get on a breadboard. I know this because I scoured YouTube for good videos, some of which are linked in this study, for working examples of known circuits. To my delight, the program I've got can easily handle any test I throw it. By "handle", I mean get *exactly* what the real circuit gives.

The reason I gather you here in this thread is not only to show off this program, but to offer a self-teaching crash course in digital electronics. (See the link below.) I had a lot of fun rediscovering precisely how data latches and other computing essentials were done.

More Remarks:

So far, I've tested the heck out of "static state" circuits, along with "edge detection" circuits. We all know that *real* electronics depend on some rather subtle principles, yet this program ignores things like capacitance, inductance - even resistance, because we never had to worry about these in the first place. We're strictly making logic circuits, where if you test for voltage at any place, you'll find a 0 or a 1, no exceptions.

The code takes zero shortcuts to simulate circuit state and edge detection - there is no use of the timer, internal variables, cheat variables, loops, recursion, nothing. Everything is done with a minima of components, namely six: AND, OR, NOT, NOR, XOR, and Split.

Example:

For one example, of which there are a total sixteen in the program, we simulate the four-bit adder, thereby creating a primitive "computer" out of logic gates. Observe the following schematic and program screenshot:

 
Example10Diagram.png


 
Example10Screenshot.png


Manual:

To understand what's going on here, it's highly recommended that you read the manual. I drafted this thing in Notepad with no spell check, so it's subject to updates. Anyway, on this page:

http://barnes.x10host.com/pages/Logic-Circuits.php

... you'll see how circuits are modeled, how they're evaluated, and how the user interacts with the circuit. This program is exceedingly simple to use, and designing circuits turned out to be not as daunting as initially believed. I'll refrain from further explaining anything here, and defer to the above link for all elaboration.

Closing Remarks:

While this program is a perfectly nice breadboard simulator, it begs to be expanded in any number of directions. Surely it needs a GUI. Surely it needs more inputs and outputs. Surely it needs a better way to skirt the arrays-in-types issue. I'm still deciding what the next direction, if any, will be.

Thanks for your attention

12
Programs / Sanctum 2021
« on: November 09, 2021, 08:13:14 pm »
Hello all,

I recently ran the code for Sanctum (various versions floating around on forums) and realized my local copy is a whole lot newer, so it's time for an update post on this. I also made the mistake of fiddling with the code a few days ago, and of course fell into the abyss, and had to take the code in a new direction to find my way out. I may or may not keep (all of) the results, but I figured it would be worth sharing what exists now.

For those who remember more recent versions of this program, everything is now gone. The land, the trees, the air, (I sound like Churchill right now), the snowmen, all the planets, the black hole, the different layers of ground and hell, all gone gone gone. ASCII plotting, gone.

Here is some of what's going on:

Terrain model:
* Terrain is no longer flat, but is procedurally generated (same seed creates same map).
* Created by choosing pseudo-random extreme points and using relaxation algorithm (to basically solve Laplace's equation treating peaks as charges).
* Contains several pre-flattened plateaus for specialized use (nothing specific implemented yet).

Terrain volume:
* Surface supported by layer of dirt and sand.
* Low spots are filled with water.

Terrain surface:
* Surface features generated and relaxed in analogy to terrain model.
* Elevation-specific coloring.
* Elevation-specific plant-life: Parametric clover, Fractal fern, Grass

Sun and Moon:
* As an experimental feature, the sun and moon are always visible if above the horizon. (There is at least one GOTO in the code because of this. It won't last.)
* When observed form below water level, the sun and moon lose their color.
* The sun/moon phases are loosely tied to your system clock.
* If you're lucky, you'll see a solar eclipse.

Weather:
* Clouds occur in different stratified layers. Different speeds, heights, etc.
* Rain falls from randomly-chosen clouds.
* Weather patterns move and adjust height to pass over mountains, etc.
* Tornadoes will mess you up.

Fish:
* If you look in the deepest water, toward the middle, you will see fish.
* Each view of a fish is actually trimmed from what is best described as a three-dimensional sprite sheet.
* At a given moment, the view of the fish is determined by its velocity.
*** This successful proof-of-concept demonstrates motion of asymmetric things like birds, planes, etc. No longer limited to spheres and UFOs.

Movement/controls:
* Player follows the main terrain mesh while walking.
* Recommended "posture" is WSAD plus Numpad. (Mouse is disabled but works if you find and uncomment the code.)
* Use the Z key to zoom, as if using a telescope. Thought this feature was cute, will probably keep it.
* Press F to throw a breakable thing. Looks like a potion I guess.

Very crude building system:
* Press B to spawn a block. The block will fall to the ground, crudely.
* Press B again to stack a block on top of another block.
* Make stairs or primitive towers this way.
* You can stand blocks like they're part of the terrain.
* Super primitive, no need to tell me about floating blocks.

As usual, this project is perpetually unfinished. This is all done using LINE and CIRCLE, and maybe I've done *all* I can in this area without going the way of textures and the like. Let me know what kind of FPS you get. (I stay around 60, which is the target.)

Code: QB64: [Select]
  1.  
  2. _Title "Sanctum 2021"
  3.  
  4. '$ExeIcon:'sanctum.ico'
  5.  
  6. ' Hardware.
  7.  
  8. 'Screen _NewImage(640, 480, 32)
  9. Screen _NewImage(800, 600, 32)
  10. 'Screen _NewImage(1024, 768, 32)
  11.  
  12.  
  13. ' Performance.
  14. Dim Shared As Integer FPSTarget
  15. FPSTarget = 60
  16.  
  17. ' Color constants.
  18. Const Aquamarine = _RGB32(127, 255, 212)
  19. Const Black = _RGB32(0, 0, 0)
  20. Const Blue = _RGB32(0, 0, 255)
  21. Const BlueViolet = _RGB32(138, 43, 226)
  22. Const Chocolate = _RGB32(210, 105, 30)
  23. Const Cyan = _RGB32(0, 255, 255)
  24. Const DarkBlue = _RGB32(0, 0, 139)
  25. Const DarkGoldenRod = _RGB32(184, 134, 11)
  26. Const DarkGray = _RGB32(169, 169, 169)
  27. Const DarkKhaki = _RGB32(189, 183, 107)
  28. Const DeepPink = _RGB32(255, 20, 147)
  29. Const DodgerBlue = _RGB32(30, 144, 255)
  30. Const ForestGreen = _RGB32(34, 139, 34)
  31. Const Gray = _RGB32(128, 128, 128)
  32. Const Green = _RGB32(0, 128, 0)
  33. Const Indigo = _RGB32(75, 0, 130)
  34. Const Ivory = _RGB32(255, 255, 240)
  35. Const LightSeaGreen = _RGB32(32, 178, 170)
  36. Const Lime = _RGB32(0, 255, 0)
  37. Const LimeGreen = _RGB32(50, 205, 50)
  38. Const Magenta = _RGB32(255, 0, 255)
  39. Const PaleGoldenRod = _RGB32(238, 232, 170)
  40. Const Purple = _RGB32(128, 0, 128)
  41. Const Red = _RGB32(255, 0, 0)
  42. Const RoyalBlue = _RGB32(65, 105, 225)
  43. Const SaddleBrown = _RGB32(139, 69, 19)
  44. Const Sienna = _RGB32(160, 82, 45)
  45. Const SlateGray = _RGB32(112, 128, 144)
  46. Const Snow = _RGB32(200, 200, 200) '''(255, 250, 250)
  47. Const Sunglow = _RGB32(255, 207, 72)
  48. Const SunsetOrange = _RGB32(253, 94, 83)
  49. Const Teal = _RGB32(0, 128, 128)
  50. Const White = _RGB32(255, 255, 255)
  51. Const Yellow = _RGB32(255, 255, 0)
  52.  
  53. ' Mathematical constants.
  54. Const pi = 4 * Atn(1)
  55. Const ee = Exp(1)
  56.  
  57. ' Divine numbers.
  58. Dim Shared bignumber As Long
  59. Dim Shared WorldSeed As Long
  60. bignumber = 10 ^ 7
  61. WorldSeed = 3 'Int(Timer)
  62.  
  63. ' Fundamental types.
  64.  
  65. Type Vector3
  66.     x As Double
  67.     y As Double
  68.     z As Double
  69.  
  70. Type Vector2
  71.     u As Double
  72.     v As Double
  73.  
  74. Type Camera
  75.     Position As Vector3
  76.     Velocity As Vector3
  77.     Acceleration As Vector3
  78.     Shade As _Unsigned Long
  79.  
  80. Type GroupElement
  81.     Identity As Long
  82.     Label As String
  83.     Pointer As Long
  84.     Lagger As Long
  85.     Volume As Vector3
  86.     FirstVector As Long
  87.     LastVector As Long
  88.     Centroid As Vector3
  89.     Velocity As Vector3
  90.     Visible As Integer
  91.     Distance2 As Double
  92.     PlotMode As Integer
  93.     FrameLength As Long
  94.     ActiveFrame As Integer
  95.  
  96. Type ClusterElement
  97.     Identity As Long
  98.     Pointer As Long
  99.     Lagger As Long
  100.     FirstGroup As Long
  101.     LastGroup As Long
  102.     Centroid As Vector3
  103.     Velocity As Vector3
  104.     Acceleration As Vector3
  105.     Visible As Integer
  106.     MotionType As Integer
  107.     Framed As Integer
  108.     DeathTimer As Long
  109.  
  110. ' World-specific types.
  111.  
  112. Type StrataElement
  113.     Height As Double
  114.     Label As String
  115.     Shade As _Unsigned Long
  116.  
  117. Type PlateauElement
  118.     Location As Vector3
  119.     Radius As Double
  120.  
  121. ' Vectors to specify points.
  122. Dim Shared vec3Dpos(bignumber) As Vector3 ' Absolute position
  123. Dim Shared vec3Dvel(UBound(vec3Dpos)) As Vector3 ' Linear velocity
  124. Dim Shared vec3Dvis(UBound(vec3Dpos)) As Integer ' Visibility toggle
  125. Dim Shared vec2D(UBound(vec3Dpos)) As Vector2 ' Projection onto 2D plane
  126. Dim Shared vec3Dcolor(UBound(vec3Dpos)) As Long ' Original color
  127. Dim Shared vec2Dcolor(UBound(vec3Dpos)) As Long ' Projected color
  128.  
  129. ' A collection of vectors is a Group.
  130. Dim Shared Group(UBound(vec3Dpos) / 10) As GroupElement
  131. Dim Shared GroupIdTicker As Long
  132. GroupIdTicker = 0
  133.  
  134. ' Groups will eventually be sorted based on distance^2.
  135. Dim Shared SortedGroups(1000) As Long
  136. Dim Shared SortedGroupsCount As Integer
  137.  
  138. ' A collection of groups is a Cluster.
  139. Dim Shared ClusterIdTicker As Long
  140. Dim Shared ClusterFillCounter As Integer
  141. Dim Shared Cluster(UBound(Group) / 10) As ClusterElement
  142. ClusterIdTicker = 0
  143. ClusterFillCounter = 0
  144.  
  145. ' Main terrain setup. This is a surface z=f(x,y).
  146. Dim Shared WorldMesh(180, 180) As Double
  147. Dim Shared WorldMeshAddress(UBound(WorldMesh, 1), UBound(WorldMesh, 2)) As Long
  148.  
  149. ' Terrain elements are formally groups whose size and density are specified here.
  150. Dim Shared BlockSize As Integer
  151. Dim Shared BlockStep As Integer
  152. BlockSize = 40
  153. BlockStep = Int(BlockSize / 8)
  154.  
  155. ' World features.
  156. Dim Shared Strata(5) As StrataElement
  157. Dim Shared CloudLayer(5) As StrataElement
  158. Dim Shared Plateau(5) As PlateauElement
  159. Dim Shared SunClusterAddress As Long
  160. Dim Shared MoonClusterAddress As Long
  161.  
  162. ' Fixed paths. Primary ticks are one per second, with total cycle of one day.
  163. Dim Shared FixedPath(500, 86400) As Vector3
  164. Dim Shared FixedPathIndexTicker As Long
  165. FixedPathIndexTicker = 0
  166.  
  167. ' Three-space basis vectors.
  168. Dim Shared As Double xhat(3), yhat(3), zhat(3)
  169. xhat(1) = 1: xhat(2) = 0: xhat(3) = 0
  170. yhat(1) = 0: yhat(2) = 1: yhat(3) = 0
  171. zhat(1) = 0: zhat(2) = 0: zhat(3) = 1
  172.  
  173. ' Camera orientation vectors.
  174. Dim Shared As Double uhat(3), vhat(3), nhat(3)
  175.  
  176. ' Camera position.
  177. Dim Shared PlayerCamera As Camera
  178.  
  179. ' Field-of-view distance.
  180. fovd = -192
  181.  
  182. ' Clipping planes.
  183. Dim Shared As Double nearplane(4), farplane(4), rightplane(4), leftplane(4), topplane(4), bottomplane(4)
  184. nearplane(4) = 1
  185. farplane(4) = -256
  186. rightplane(4) = -BlockSize / 2
  187. leftplane(4) = -BlockSize / 2
  188. topplane(4) = -BlockSize / 2
  189. bottomplane(4) = -BlockSize / 2
  190.  
  191. ' Temporary counters.
  192. Dim Shared NumClusterVisible As Long
  193. Dim Shared NumVectorVisible As Long
  194. Dim Shared NumGroupVisible As Long
  195.  
  196. ' Interface.
  197. Dim Shared ToggleAnimate As Integer
  198. Dim Shared FPSReport As Integer
  199. Dim Shared ClosestGroup As Long
  200.  
  201. ' Prime and start main loop.
  202. Randomize WorldSeed
  203. Call InitWorld
  204. Call CreateWorld
  205. Call InitCamera
  206. Call MainLoop
  207.  
  208. ' Subs and Functions
  209.  
  210. Sub MainLoop
  211.     Dim fps As Integer
  212.     Dim fpstimer As Long
  213.     Dim tt As Long
  214.     fps = 0
  215.     fpstimer = Int(Timer)
  216.  
  217.     Do
  218.         Call PlayerDynamics
  219.         Call ComputeVisibleScene
  220.         Call PlotWorld
  221.         Call DisplayHUD
  222.         Call DisplayMiniMap
  223.         Call KeyDownProcess
  224.         Call KeyHitProcess
  225.  
  226.         fps = fps + 1
  227.         tt = Timer
  228.         If (tt = fpstimer + 1) Then
  229.             fpstimer = tt
  230.             FPSReport = fps
  231.             fps = 0
  232.         End If
  233.  
  234.         _Display
  235.         _Limit FPSTarget + 1
  236.     Loop
  237.  
  238. Sub InitWorld
  239.     Dim k As Integer
  240.     Dim As Double u, v, w
  241.  
  242.     k = 0
  243.     k = k + 1: Strata(k).Height = -50: Strata(k).Label = "Water": Strata(k).Shade = RoyalBlue
  244.     k = k + 1: Strata(k).Height = 0: Strata(k).Label = "Meadow": Strata(k).Shade = ForestGreen
  245.     k = k + 1: Strata(k).Height = 50: Strata(k).Label = "Grassland": Strata(k).Shade = DarkKhaki
  246.     k = k + 1: Strata(k).Height = 100: Strata(k).Label = "Rocky Terrain": Strata(k).Shade = DarkGoldenRod
  247.     k = k + 1: Strata(k).Height = 150: Strata(k).Label = "Snowy Terrain": Strata(k).Shade = White
  248.  
  249.     k = 0
  250.     k = k + 1: CloudLayer(k).Height = 140: CloudLayer(k).Label = "Dark Cloud": CloudLayer(k).Shade = SlateGray
  251.     k = k + 1: CloudLayer(k).Height = 160: CloudLayer(k).Label = "Gray Cloud": CloudLayer(k).Shade = Gray
  252.     k = k + 1: CloudLayer(k).Height = 180: CloudLayer(k).Label = "Azul Cloud": CloudLayer(k).Shade = DarkBlue
  253.     k = k + 1: CloudLayer(k).Height = 200: CloudLayer(k).Label = "Heavy Cloud": CloudLayer(k).Shade = Snow
  254.     k = k + 1: CloudLayer(k).Height = 220: CloudLayer(k).Label = "Icy Cloud": CloudLayer(k).Shade = Ivory
  255.  
  256.     u = Rnd * 2 * pi
  257.     w = Sqr((UBound(WorldMesh, 1) / 2) ^ 2 + (UBound(WorldMesh, 2) / 2) ^ 2)
  258.     For k = 1 To UBound(Plateau)
  259.         Select Case k
  260.             Case 1 ' Water
  261.                 u = u + pi / 2
  262.                 v = (w / 2) * (.8 + Rnd * .5)
  263.                 Plateau(k).Location.x = Int(v * Cos(u))
  264.                 Plateau(k).Location.y = Int(v * Sin(u))
  265.                 Plateau(k).Location.z = -250
  266.             Case 2 ' Meadow
  267.                 Plateau(k).Location.x = 0
  268.                 Plateau(k).Location.y = 0
  269.                 Plateau(k).Location.z = Strata(k).Height
  270.             Case Else
  271.                 u = u + pi / 2
  272.                 v = (w / 2) * (.8 + Rnd * .5)
  273.                 Plateau(k).Location.x = Int(v * Cos(u))
  274.                 Plateau(k).Location.y = Int(v * Sin(u))
  275.                 Plateau(k).Location.z = Strata(k).Height
  276.         End Select
  277.         Plateau(k).Radius = 15
  278.     Next
  279.  
  280. Sub CreateWorld
  281.     Dim g As Long
  282.     Dim k As Integer
  283.     ' Initialize and populate list.
  284.     k = 0
  285.     k = k + 1: Call TextCenter(".:. Let there be light .:.", k * 16, DarkKhaki)
  286.     k = k + 1: Call TextCenter("(Initialize linked list)", k * 16, ForestGreen)
  287.     g = NewGroup&(0, 0, 0, 0, 1, 0, 0)
  288.     k = k + 2: Call TextCenter(".:. Let there be a firmament .:.", k * 16, DarkKhaki)
  289.     k = k + 1: Call TextCenter("(Using seed " + LTrim$(RTrim$(Str$(WorldSeed))) + ")", k * 16, ForestGreen)
  290.     k = k + 1: Call TextCenter("(Generate random terrain)", k * 16, ForestGreen)
  291.     g = CreateTerrainGroups&(g)
  292.     k = k + 2: Call TextCenter(".:. Let the dry land appear; bring forth the grass .:.", k * 16, DarkKhaki)
  293.     k = k + 1: Call TextCenter("(Relax terrain mesh)", k * 16, ForestGreen)
  294.     k = k + 1: Call TextCenter("(Fill terrain volumes)", k * 16, ForestGreen)
  295.     k = k + 1: Call TextCenter("(Cover terrain surfaces)", k * 16, ForestGreen)
  296.     g = CreateTerrainVectors&(g)
  297.     g = CreateTerrainVolume&(g)
  298.     g = CreateClover&(g)
  299.     g = CreateFern&(g)
  300.     g = CreateGrass&(g)
  301.     k = k + 2: Call TextCenter(".:. Divide the day from the night .:.", k * 16, DarkKhaki)
  302.     k = k + 1: Call TextCenter("(Create celestial objects)", k * 16, ForestGreen)
  303.     k = k + 1: Call TextCenter("(Create weather events)", k * 16, ForestGreen)
  304.     g = CreateSun&(g)
  305.     g = CreateMoon&(g)
  306.     g = CreateTornado&(g)
  307.     g = CreateWeather&(g)
  308.     k = k + 2: Call TextCenter(".:. Let waters bring forth .:.", k * 16, DarkKhaki)
  309.     k = k + 1: Call TextCenter("(Create fish)", k * 16, ForestGreen)
  310.     g = CreateFish&(g)
  311.     k = k + 2: Call TextCenter(".:. Let us make man .:.", k * 16, DarkKhaki)
  312.     k = k + 1: Call TextCenter("(Initialize player)", k * 16, ForestGreen)
  313.     k = k + 2: Call TextCenter(".:. ...blessed the seventh day and Sanctified it .:.", k * 16, DarkKhaki)
  314.     k = k + 1: Call TextCenter("(Rest)", k * 16, ForestGreen)
  315.     k = k + 3: Call TextCenter("PRESS ANY KEY", k * 16, Sunglow)
  316.     Sleep
  317.     _KeyClear
  318.  
  319. ' High-order clusters and groups.
  320.  
  321. Function CreateTerrainGroups& (LagAddressIn As Long)
  322.     Dim g As Long
  323.     Dim As Integer i, j, k
  324.     Dim As Integer ii, jj
  325.     Dim As Double u, v, w
  326.     g = LagAddressIn
  327.  
  328.     ' Create world mesh and set extreme points.
  329.     Dim tempworldmesh1(UBound(WorldMesh, 1), UBound(WorldMesh, 2))
  330.     Dim tempworldmesh2(UBound(WorldMesh, 1), UBound(WorldMesh, 2), 2)
  331.  
  332.     u = 1 + .5 * (Rnd - .5)
  333.     v = 1 + .5 * (Rnd - .5)
  334.     For i = 1 To UBound(WorldMesh, 1)
  335.         For j = 1 To UBound(WorldMesh, 2)
  336.  
  337.             ' Overall slant of world.
  338.             tempworldmesh2(i, j, 1) = (u * i + v * j - UBound(WorldMesh, 1) / 2 - UBound(WorldMesh, 2) / 2)
  339.  
  340.             ' Peaks and valleys.
  341.             Select Case Rnd
  342.                 Case Is < .005
  343.                     tempworldmesh2(i, j, 1) = tempworldmesh2(i, j, 1) - (100 + Rnd * 100)
  344.                     tempworldmesh2(i, j, 2) = 1 ' fixed
  345.                 Case Is > .995
  346.                     tempworldmesh2(i, j, 1) = tempworldmesh2(i, j, 1) + (100 + Rnd * 300)
  347.                     tempworldmesh2(i, j, 2) = 1 ' fixed
  348.                 Case Else
  349.                     tempworldmesh2(i, j, 1) = tempworldmesh2(i, j, 1) + 0
  350.                     tempworldmesh2(i, j, 2) = 0 'free
  351.             End Select
  352.  
  353.             ' Plateaus.
  354.             For k = 1 To UBound(Plateau)
  355.                 ii = i - Plateau(k).Location.x - UBound(WorldMesh, 1) / 2
  356.                 jj = j - Plateau(k).Location.y - UBound(WorldMesh, 2) / 2
  357.                 If (ii ^ 2 + jj ^ 2 < Plateau(k).Radius ^ 2) Then
  358.                     tempworldmesh2(i, j, 1) = Plateau(k).Location.z
  359.                     tempworldmesh2(i, j, 2) = 1 ' fixed
  360.                 End If
  361.             Next
  362.         Next
  363.     Next
  364.  
  365.     ' Relax the world mesh to generate terrain.
  366.     Dim SmoothFactor As Integer
  367.     SmoothFactor = 30
  368.     For k = SmoothFactor To 1 Step -1
  369.         For i = 1 To UBound(WorldMesh, 1)
  370.             For j = 1 To UBound(WorldMesh, 2)
  371.                 tempworldmesh1(i, j) = tempworldmesh2(i, j, 1)
  372.                 ' Before last iteration, allow extreme points to relax.
  373.                 If (k = 1) Then tempworldmesh2(i, j, 2) = 0
  374.             Next
  375.         Next
  376.         For i = 2 To UBound(WorldMesh, 1) - 1
  377.             For j = 2 To UBound(WorldMesh, 2) - 1
  378.                 If (tempworldmesh2(i, j, 2) = 0) Then
  379.                     tempworldmesh2(i, j, 1) = (1 / 4) * (tempworldmesh1(i - 1, j) + tempworldmesh1(i + 1, j) + tempworldmesh1(i, j - 1) + tempworldmesh1(i, j + 1))
  380.                 End If
  381.             Next
  382.         Next
  383.     Next
  384.     For i = 1 To UBound(WorldMesh, 1)
  385.         For j = 1 To UBound(WorldMesh, 2)
  386.             WorldMesh(i, j) = tempworldmesh2(i, j, 1)
  387.         Next
  388.     Next
  389.  
  390.     ' Create terrain groups.
  391.     Dim g0 As Long
  392.     For i = 1 To UBound(WorldMesh, 1)
  393.         For j = 1 To UBound(WorldMesh, 2)
  394.             u = BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  395.             v = BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  396.             w = WorldMesh(i, j)
  397.             ' Store first address.
  398.             If ((i = 1) And (j = 1)) Then g0 = g
  399.             g = NewGroup&(g, u, v, w, 10, 0, 0)
  400.             Group(g).Label = TerrainHeightLabel$(w)
  401.             Group(g).Volume.x = BlockSize
  402.             Group(g).Volume.y = BlockSize
  403.             Group(g).Volume.z = Sqr(BlockSize * BlockSize + BlockSize * BlockSize)
  404.             Group(g).PlotMode = 0
  405.             WorldMeshAddress(i, j) = g
  406.         Next
  407.         Call ClusterPinch(g)
  408.     Next
  409.     Call ClusterPinch(g)
  410.  
  411.     CreateTerrainGroups& = g0
  412.  
  413. Function CreateTerrainVectors& (LagAddressIn As Long)
  414.     Dim g As Long
  415.     Dim As Integer i, j, k
  416.     Dim As Integer ii, jj
  417.     Dim Smoothfactor As Integer
  418.     g = LagAddressIn
  419.  
  420.     ' Create fine-grain block mesh to relax terrain.
  421.     Dim vindex As Long
  422.     Dim BlockBins As Integer
  423.     BlockBins = BlockSize / BlockStep
  424.     Dim blockmesh1(BlockBins, BlockBins)
  425.     Dim blockmesh2(BlockBins, BlockBins, 2)
  426.     vindex = Group(Group(g).Lagger).LastVector
  427.     For i = 1 To UBound(WorldMesh, 1)
  428.         For j = 1 To UBound(WorldMesh, 2)
  429.  
  430.             g = WorldMeshAddress(i, j)
  431.             Group(g).FirstVector = vindex + 1
  432.  
  433.             ' For each world mesh location, use the block mesh whose boundary heights are determined by neighbors.
  434.             For ii = 1 To UBound(blockmesh2, 1)
  435.                 For jj = 1 To UBound(blockmesh2, 2)
  436.  
  437.                     ' Lock boundaries.
  438.                     If (ii = 1) Or (ii = UBound(blockmesh2, 1)) Then
  439.                         blockmesh2(ii, jj, 2) = 1
  440.                     End If
  441.                     If (jj = 1) Or (jj = UBound(blockmesh2, 2)) Then
  442.                         blockmesh2(ii, jj, 2) = 1
  443.                     End If
  444.  
  445.                     ' Set boundary values.
  446.                     If (i > 1) Then
  447.                         If (ii = 1) Then
  448.                             blockmesh2(ii, jj, 1) = -WorldMesh(i, j) + (1 / 2) * (WorldMesh(i, j) + WorldMesh(i - 1, j))
  449.                         End If
  450.                     End If
  451.                     If (j > 1) Then
  452.                         If (jj = 1) Then
  453.                             blockmesh2(ii, jj, 1) = -WorldMesh(i, j) + (1 / 2) * (WorldMesh(i, j) + WorldMesh(i, j - 1))
  454.                         End If
  455.                     End If
  456.                     If (i < UBound(WorldMesh, 1)) Then
  457.                         If (ii = UBound(blockmesh2, 1)) Then
  458.                             blockmesh2(ii, jj, 1) = -WorldMesh(i, j) + (1 / 2) * (WorldMesh(i, j) + WorldMesh(i + 1, j))
  459.                         End If
  460.                     End If
  461.                     If (j < UBound(WorldMesh, 2)) Then
  462.                         If (jj = UBound(blockmesh2, 2)) Then
  463.                             blockmesh2(ii, jj, 1) = -WorldMesh(i, j) + (1 / 2) * (WorldMesh(i, j) + WorldMesh(i, j + 1))
  464.                         End If
  465.                     End If
  466.  
  467.                     ' Set extreme points.
  468.                     If ((ii > 1) And (ii < UBound(blockmesh2, 1)) And (jj > 1) And (jj < UBound(blockmesh2, 1))) Then
  469.                         Select Case Rnd
  470.                             Case Is < .01
  471.                                 blockmesh2(ii, jj, 1) = -Rnd * 20
  472.                                 blockmesh2(ii, jj, 2) = 1 ' fixed
  473.                             Case Is > .99
  474.                                 blockmesh2(ii, jj, 1) = Rnd * 20
  475.                                 blockmesh2(ii, jj, 2) = 1 ' fixed
  476.                             Case Else
  477.                                 blockmesh2(ii, jj, 1) = 0
  478.                                 blockmesh2(ii, jj, 2) = 0 'free
  479.                         End Select
  480.                     End If
  481.  
  482.                     ' Copy mesh.
  483.                     blockmesh1(ii, jj) = blockmesh2(ii, jj, 1)
  484.  
  485.                 Next
  486.             Next
  487.  
  488.             ' Relax mesh body.
  489.             Smoothfactor = 30
  490.             For k = Smoothfactor To 1 Step -1
  491.                 For ii = 2 To UBound(blockmesh1, 1) - 1
  492.                     For jj = 2 To UBound(blockmesh1, 2) - 1
  493.                         ' Before last iteration, allow extreme points to relax.
  494.                         If (k = 5) Then blockmesh2(ii, jj, 2) = 0
  495.                         If (blockmesh2(ii, jj, 2) = 0) Then
  496.                             blockmesh2(ii, jj, 1) = (1 / 4) * (blockmesh1(ii - 1, jj) + blockmesh1(ii + 1, jj) + blockmesh1(ii, jj - 1) + blockmesh1(ii, jj + 1))
  497.                         End If
  498.                     Next
  499.                 Next
  500.  
  501.                 ' Upate mesh with relaxed version.
  502.                 For ii = 1 To UBound(blockmesh1, 1)
  503.                     For jj = 1 To UBound(blockmesh1, 2)
  504.                         blockmesh1(ii, jj) = blockmesh2(ii, jj, 1)
  505.                     Next
  506.                 Next
  507.             Next
  508.  
  509.             ' Relax mesh boundaries once.
  510.             For ii = 2 To UBound(blockmesh1, 1) - 1
  511.                 jj = 1
  512.                 blockmesh2(ii, jj, 1) = (1 / 3) * (blockmesh1(ii - 1, jj) + blockmesh1(ii + 1, jj) + blockmesh1(ii, jj + 1))
  513.                 jj = UBound(blockmesh1, 2)
  514.                 blockmesh2(ii, jj, 1) = (1 / 3) * (blockmesh1(ii - 1, jj) + blockmesh1(ii + 1, jj) + blockmesh1(ii, jj - 1))
  515.             Next
  516.             For jj = 2 To UBound(blockmesh1, 2) - 1
  517.                 ii = 1
  518.                 blockmesh2(ii, jj, 1) = (1 / 3) * (blockmesh1(ii + 1, jj) + blockmesh1(ii, jj - 1) + blockmesh1(ii, jj + 1))
  519.                 ii = UBound(blockmesh1, 1)
  520.                 blockmesh2(ii, jj, 1) = (1 / 3) * (blockmesh1(ii - 1, jj) + blockmesh1(ii, jj - 1) + blockmesh1(ii, jj + 1))
  521.             Next
  522.  
  523.             ii = 1
  524.             jj = 1
  525.             blockmesh2(ii, jj, 1) = (1 / 2) * (blockmesh1(ii + 1, jj) + blockmesh1(ii, jj + 1))
  526.  
  527.             ii = UBound(blockmesh1, 1)
  528.             jj = UBound(blockmesh1, 2)
  529.             blockmesh2(ii, jj, 1) = (1 / 2) * (blockmesh1(ii - 1, jj) + blockmesh1(ii, jj - 1))
  530.  
  531.             ii = 1
  532.             jj = UBound(blockmesh1, 2)
  533.             blockmesh2(ii, jj, 1) = (1 / 2) * (blockmesh1(ii + 1, jj) + blockmesh1(ii, jj - 1))
  534.  
  535.             ii = UBound(blockmesh1, 1)
  536.             jj = 1
  537.             blockmesh2(ii, jj, 1) = (1 / 2) * (blockmesh1(ii - 1, jj) + blockmesh1(ii, jj + 1))
  538.  
  539.             ' Upate mesh with relaxed version.
  540.             For ii = 1 To UBound(blockmesh1, 1)
  541.                 For jj = 1 To UBound(blockmesh1, 2)
  542.                     blockmesh1(ii, jj) = blockmesh2(ii, jj, 1)
  543.                 Next
  544.             Next
  545.  
  546.             ' Set particle positions relative to group center. Add random fuzz.
  547.             Dim cc As _Unsigned Long
  548.             Dim dd As _Unsigned Long
  549.             For ii = 1 To UBound(blockmesh1, 1)
  550.                 For jj = 1 To UBound(blockmesh1, 2)
  551.                     vindex = vindex + 1
  552.                     vec3Dpos(vindex).x = BlockStep * ii - BlockSize / 2 + 3 * (Rnd - .5)
  553.                     vec3Dpos(vindex).y = BlockStep * jj - BlockSize / 2 + 3 * (Rnd - .5)
  554.                     vec3Dpos(vindex).z = blockmesh1(ii, jj)
  555.                     cc = TerrainHeightShade~&(WorldMesh(i, j) + blockmesh1(ii, jj))
  556.                     dd = TerrainHeightShade~&(WorldMesh(i, j) + blockmesh1(ii, jj) + BlockSize)
  557.                     vec3Dcolor(vindex) = ShadeMix~&(cc, ShadeMix~&(cc, dd, blockmesh1(ii, jj) / 10), .5)
  558.                 Next
  559.             Next
  560.  
  561.             Group(g).LastVector = vindex + 1 ''' why on earth is this +1?
  562.         Next
  563.     Next
  564.  
  565.     CreateTerrainVectors& = g
  566.  
  567. Function CreateTerrainVolume& (LagAddressIn As Long)
  568.     Dim g As Long
  569.     Dim As Integer i, j
  570.     Dim k As Long
  571.     Dim As Double u, v, z
  572.     Dim groupcount As Integer
  573.     Dim clustertick As Integer
  574.     g = LagAddressIn
  575.     groupcount = 0
  576.     clustertick = 0
  577.     For i = 1 To UBound(WorldMesh, 1)
  578.         For j = 1 To UBound(WorldMesh, 2)
  579.             z = WorldMesh(i, j) + BlockSize / 2
  580.             If (z < 0) Then
  581.                 groupcount = groupcount + 1
  582.                 u = BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  583.                 v = BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  584.                 g = NewCube&(g, "Water", 50, u, v, WorldMesh(i, j) - z / 2, BlockSize, BlockSize, -z, Blue, RoyalBlue, DarkBlue, 0, 0)
  585.                 For k = Group(g).FirstVector To Group(g).LastVector
  586.                     vec3Dvel(k).x = (Rnd - .5) * .20
  587.                     vec3Dvel(k).y = (Rnd - .5) * .20
  588.                     vec3Dvel(k).z = 0
  589.                 Next
  590.             End If
  591.             clustertick = clustertick + 1
  592.             If (clustertick = 12) Then
  593.                 clustertick = 0
  594.                 If (groupcount > 0) Then
  595.                     groupcount = 0
  596.                     Call ClusterPinch(g)
  597.                 End If
  598.             End If
  599.         Next
  600.         Call ClusterPinch(g)
  601.     Next
  602.     Call ClusterPinch(g)
  603.  
  604.     groupcount = 0
  605.     clustertick = 0
  606.     For i = 1 To UBound(WorldMesh, 1)
  607.         For j = 1 To UBound(WorldMesh, 2)
  608.             z = WorldMesh(i, j) + BlockSize / 2
  609.             If (z > 0) Then
  610.                 groupcount = groupcount + 1
  611.                 u = BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  612.                 v = BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  613.                 g = NewCube&(g, "Dirt and Sand", 20, u, v, WorldMesh(i, j) / 2 - BlockSize / 4, BlockSize, BlockSize, WorldMesh(i, j), SaddleBrown, DarkKhaki, Sienna, 0, 0)
  614.                 g = NewCube&(g, "Dirt and Sand", 20, u, v, -50, BlockSize, BlockSize, 80, SaddleBrown, DarkKhaki, Sienna, 0, 0)
  615.             End If
  616.             clustertick = clustertick + 1
  617.             If (clustertick = 12) Then
  618.                 clustertick = 0
  619.                 If (groupcount > 0) Then
  620.                     groupcount = 0
  621.                     Call ClusterPinch(g)
  622.                 End If
  623.             End If
  624.         Next
  625.         Call ClusterPinch(g)
  626.     Next
  627.     Call ClusterPinch(g)
  628.  
  629.     groupcount = 0
  630.     clustertick = 0
  631.     For i = 1 To UBound(WorldMesh, 1)
  632.         For j = 1 To UBound(WorldMesh, 2)
  633.             groupcount = groupcount + 1
  634.             u = BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  635.             v = BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  636.             z = WorldMesh(i, j)
  637.             If (z < 0) Then z = 0
  638.             g = NewCube&(g, "Atmospheric Dust", 30, u, v, 100 + BlockSize * (3 - 1 / 2) + z, BlockSize, BlockSize, BlockSize * 3, DarkGray, White, Snow, 0, 0)
  639.             clustertick = clustertick + 1
  640.             If (clustertick = 12) Then
  641.                 clustertick = 0
  642.                 If (groupcount > 0) Then
  643.                     groupcount = 0
  644.                     Call ClusterPinch(g)
  645.                 End If
  646.             End If
  647.         Next
  648.         Call ClusterPinch(g)
  649.     Next
  650.     Call ClusterPinch(g)
  651.  
  652.     CreateTerrainVolume& = g
  653.  
  654. Function CreateTornado& (LagAddressIn As Long)
  655.     Dim As Integer n, k
  656.     Dim As Double u, v, w, x0, y0, z0
  657.     Dim As Long p, g
  658.     Dim wi As Integer
  659.     Dim wj As Integer
  660.     g = LagAddressIn
  661.     For n = 1 To 4
  662.         u = Rnd * 2 * pi
  663.         FixedPathIndexTicker = FixedPathIndexTicker + 1
  664.         For p = 1 To 86400
  665.             x0 = BlockSize * 30 * Cos(u + 2 * pi * (6 * 30) * (p - 1) / 86400)
  666.             y0 = BlockSize * 30 * Sin(u + 2 * pi * (6 * 30) * (p - 1) / 86400)
  667.             FixedPath(FixedPathIndexTicker, p).x = x0
  668.             FixedPath(FixedPathIndexTicker, p).y = y0
  669.             wi = 1 + Int(x0 / BlockSize + UBound(WorldMesh, 1) / 2)
  670.             wj = 1 + Int(y0 / BlockSize + UBound(WorldMesh, 2) / 2)
  671.             z0 = WorldMesh(wi, wj)
  672.             If (z0 < 0) Then z0 = 0
  673.             FixedPath(FixedPathIndexTicker, p).z = z0 + 50
  674.         Next
  675.         For k = 1 To 30
  676.             u = Rnd * 100
  677.             v = Rnd * u / 3
  678.             w = Rnd * 2 * pi
  679.             g = NewCube&(g, "Tornado", 35, v * Cos(w), v * Sin(w), u, 15, 15, 15, DarkGray, SunsetOrange, DarkGoldenRod, FixedPathIndexTicker, 0)
  680.             Call SetParticleVelocity(g, -Sin(w), Cos(w), 0)
  681.         Next
  682.         Call ClusterPinch(g)
  683.     Next
  684.     CreateTornado& = g
  685.  
  686. Function CreateWeather& (LagAddressIn As Long)
  687.     Dim As Integer n, k
  688.     Dim As Double u, v, w, x0, y0, z0, tallness
  689.     Dim As Long p, g
  690.     Dim wi As Integer
  691.     Dim wj As Integer
  692.     g = LagAddressIn
  693.     For n = 1 To 100
  694.         FixedPathIndexTicker = FixedPathIndexTicker + 1
  695.         u = Rnd * 2 * pi
  696.         v = Rnd * .7 * BlockSize * Sqr((UBound(WorldMesh, 1) / 2) ^ 2 + (UBound(WorldMesh, 2) / 2) ^ 2)
  697.         w = pi / 2
  698.         tallness = Rnd * (CloudLayer(UBound(CloudLayer)).Height - CloudLayer(1).Height)
  699.         For p = 1 To 86400
  700.             x0 = v * Cos(u + 2 * pi * (1 * 30) * (p - 1) / 86400 + w)
  701.             y0 = v * Sin(u + 4 * pi * (1 * 30) * (p - 1) / 86400)
  702.             FixedPath(FixedPathIndexTicker, p).x = x0
  703.             FixedPath(FixedPathIndexTicker, p).y = y0
  704.             wi = 1 + Int(x0 / BlockSize + UBound(WorldMesh, 1) / 2)
  705.             wj = 1 + Int(y0 / BlockSize + UBound(WorldMesh, 2) / 2)
  706.             z0 = WorldMesh(wi, wj)
  707.             If (z0 < 0) Then z0 = 0
  708.             z0 = z0 + CloudLayer(1).Height + tallness
  709.             FixedPath(FixedPathIndexTicker, p).z = z0
  710.         Next
  711.         For k = 1 To 20 '30
  712.             u = Rnd * 80
  713.             v = u
  714.             w = Rnd * 2 * pi
  715.             z0 = z0 + 10 * (Rnd - .5)
  716.             g = NewCube&(g, CloudHeightLabel$(z0), 20, v * Cos(w), v * Sin(w), z0, BlockSize / 2, BlockSize / 2, BlockSize / 2, Red, Red, Red, FixedPathIndexTicker, 0)
  717.             Call SetParticleVelocity(g, .01 * (Rnd - .5), .01 * (Rnd - .5), 0)
  718.             For p = Group(g).FirstVector To Group(g).LastVector
  719.                 vec3Dcolor(p) = CloudHeightShade~&(Group(g).Centroid.z + vec3Dpos(p).z)
  720.             Next
  721.             Group(g).PlotMode = 0
  722.  
  723.             If (Rnd < .2) Then
  724.                 z0 = Group(g).Centroid.z
  725.                 g = NewCube&(g, "Rain", 20, v * Cos(w), v * Sin(w), z0 / 2 - BlockSize / 2, BlockSize / 2, BlockSize / 2, z0, Blue, RoyalBlue, DodgerBlue, 0, 0)
  726.                 Call SetParticleVelocity(g, 0, 0, -1)
  727.             End If
  728.  
  729.         Next
  730.         Call ClusterPinch(g)
  731.     Next
  732.     CreateWeather& = g
  733.  
  734. Function CreateClover& (LagAddressIn As Long)
  735.     Dim As Long g, vindex
  736.     Dim As Integer i, j
  737.     Dim As Double x, y, z, u, t
  738.     Dim As Integer pedals
  739.     Dim As Double scale
  740.     Dim As Double height
  741.     g = LagAddressIn
  742.     For i = 1 To UBound(WorldMesh, 1)
  743.         For j = 1 To UBound(WorldMesh, 2)
  744.             z = WorldMesh(i, j)
  745.             If (TerrainHeightIndex(z) = 1) Then
  746.                 If (Rnd < .1) Then
  747.                     x = (Rnd - .5) * BlockSize + BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  748.                     y = (Rnd - .5) * BlockSize + BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  749.                     scale = 1 / (4 + Rnd * 3)
  750.                     g = NewGroup&(g, x, y, z, 12, 0, 0)
  751.                     Group(g).Label = "Clover"
  752.                     Group(g).Volume.x = BlockSize
  753.                     Group(g).Volume.y = BlockSize
  754.                     Group(g).Volume.z = BlockSize
  755.                     vindex = Group(Group(g).Lagger).LastVector
  756.                     Group(g).FirstVector = vindex + 1
  757.                     Group(g).PlotMode = 1
  758.                     pedals = 2 + Int(Rnd * 4)
  759.                     height = 2 + Rnd
  760.                     t = Rnd * 2 * pi
  761.                     For u = 0 To 2 * pi Step .1
  762.                         vindex = vindex + 1
  763.                         vec3Dpos(vindex).x = scale * ((Group(g).Volume.x) * (0 + Cos(pedals * u) * Cos(u))) * Cos(t)
  764.                         vec3Dpos(vindex).y = scale * ((Group(g).Volume.y) * (0 + Cos(pedals * u) * Cos(u))) * Sin(t)
  765.                         vec3Dpos(vindex).z = scale * ((Group(g).Volume.z) * (height + Cos(pedals * u) * Sin(u)))
  766.                         Select Case pedals
  767.                             Case 3
  768.                                 vec3Dcolor(vindex) = Magenta
  769.                             Case Else
  770.                                 vec3Dcolor(vindex) = Lime
  771.                         End Select
  772.                     Next
  773.                     For u = (Group(g).Volume.z) * height To 0 Step -(Group(g).Volume.z) * height / 10
  774.                         vindex = vindex + 1
  775.                         vec3Dpos(vindex).x = scale * (0 + (Rnd - .5))
  776.                         vec3Dpos(vindex).y = scale * (0 + (Rnd - .5))
  777.                         vec3Dpos(vindex).z = scale * (u)
  778.                         vec3Dcolor(vindex) = LimeGreen
  779.                     Next
  780.                     Group(g).LastVector = vindex '''+ 1 ''' why on earth is this +1?
  781.                     Call ClusterPinch(g)
  782.                 End If
  783.             End If
  784.         Next
  785.     Next
  786.     CreateClover& = g
  787.  
  788. Function CreateGrass& (LagAddressIn As Long)
  789.     Dim As Long g, vindex
  790.     Dim As Integer i, j, k
  791.     Dim As Double x0, y0, x, y, z, u, t
  792.     Dim As Double scale
  793.     Dim As Double height
  794.     g = LagAddressIn
  795.     For i = 1 To UBound(WorldMesh, 1)
  796.         For j = 1 To UBound(WorldMesh, 2)
  797.             z = WorldMesh(i, j)
  798.             If (TerrainHeightIndex(z) = 2) Then
  799.                 For k = 1 To 5
  800.                     If (Rnd < .5) Then
  801.                         x = (Rnd - .5) * BlockSize + BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  802.                         y = (Rnd - .5) * BlockSize + BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  803.                         scale = 1 / (4 + Rnd * 3)
  804.                         g = NewGroup&(g, x, y, z, 16, 0, 0)
  805.                         Group(g).Label = "Grass"
  806.                         Group(g).Volume.x = BlockSize
  807.                         Group(g).Volume.y = BlockSize
  808.                         Group(g).Volume.z = BlockSize
  809.                         vindex = Group(Group(g).Lagger).LastVector
  810.                         Group(g).FirstVector = vindex + 1
  811.                         Group(g).PlotMode = 1
  812.                         height = 1 + Rnd
  813.                         t = Rnd * 2 * pi
  814.                         x0 = BlockSize * 1 * (Rnd - .5)
  815.                         y0 = BlockSize * 1 * (Rnd - .5)
  816.                         For u = (Group(g).Volume.z) * height To 0 Step -(Group(g).Volume.z) * height / 5
  817.                             vindex = vindex + 1
  818.                             vec3Dpos(vindex).x = scale * (x0 + (Rnd - .5))
  819.                             vec3Dpos(vindex).y = scale * (y0 + (Rnd - .5))
  820.                             vec3Dpos(vindex).z = scale * (u)
  821.                             vec3Dcolor(vindex) = ShadeMix~&(DarkGoldenRod, Sienna, Rnd)
  822.                         Next
  823.                         Group(g).LastVector = vindex '''+ 1 ''' why on earth is this +1?
  824.                     End If
  825.                 Next
  826.             End If
  827.         Next
  828.         Call ClusterPinch(g)
  829.     Next
  830.     CreateGrass& = g
  831.  
  832. Function CreateFern& (LagAddressIn As Long)
  833.     Dim As Long g, vindex
  834.     Dim As Integer i, j, k
  835.     Dim As Double xx, yy, zz, x, y, z, t
  836.     Dim As Double scale
  837.     g = LagAddressIn
  838.     For i = 1 To UBound(WorldMesh, 1)
  839.         For j = 1 To UBound(WorldMesh, 2)
  840.             z = WorldMesh(i, j)
  841.             If (TerrainHeightIndex(z) = 1) Then
  842.                 If (Rnd < .1) Then
  843.                     x = (Rnd - .5) * BlockSize + BlockSize * (i - (UBound(WorldMesh, 1) / 2))
  844.                     y = (Rnd - .5) * BlockSize + BlockSize * (j - (UBound(WorldMesh, 2) / 2))
  845.                     scale = .05 + Rnd * .05
  846.                     g = NewGroup&(g, x, y, z, 12, 0, 0)
  847.                     Group(g).Label = "Fern"
  848.                     Group(g).Volume.x = BlockSize
  849.                     Group(g).Volume.y = BlockSize
  850.                     Group(g).Volume.z = BlockSize
  851.                     vindex = Group(Group(g).Lagger).LastVector
  852.                     Group(g).FirstVector = vindex + 1
  853.                     Group(g).PlotMode = 2
  854.                     t = Rnd * 2 * pi
  855.                     xx = 0
  856.                     yy = xx
  857.                     zz = 0
  858.                     For k = 1 To 100
  859.                         Select Case Rnd * 100
  860.                             Case Is < 1
  861.                                 xx = 0
  862.                                 zz = .16 * zz
  863.                             Case Is < 86
  864.                                 xx = .85 * xx + .04 * zz
  865.                                 zz = -.04 * xx + .85 * zz + 1.6
  866.                             Case Is < 93
  867.                                 xx = .2 * xx - .26 * zz
  868.                                 zz = .23 * xx + .22 * zz + 1.6
  869.                             Case Else
  870.                                 xx = -.15 * xx + .28 * zz
  871.                                 zz = .26 * xx + .24 * zz + .44
  872.                         End Select
  873.                         yy = xx
  874.                         vindex = vindex + 1
  875.                         vec3Dpos(vindex).x = scale * Group(g).Volume.x * xx * Cos(t)
  876.                         vec3Dpos(vindex).y = scale * Group(g).Volume.y * yy * Sin(t)
  877.                         vec3Dpos(vindex).z = scale * Group(g).Volume.z * zz
  878.                         vec3Dcolor(vindex) = Lime
  879.                     Next
  880.                     Group(g).LastVector = vindex '''+ 1 ''' why on earth is this +1?
  881.                     Call ClusterPinch(g)
  882.                 End If
  883.             End If
  884.         Next
  885.     Next
  886.     CreateFern& = g
  887.  
  888. Function CreateSun& (LagAddressIn As Long)
  889.     Dim As Integer k
  890.     Dim As Double xx, yy, zz, x0, y0, z0, phase
  891.     Dim As Long p, g
  892.     g = LagAddressIn
  893.     FixedPathIndexTicker = FixedPathIndexTicker + 1
  894.     For p = 1 To 86400
  895.         phase = -2 * pi * (24) * (p - 1) / 86400 - pi / 2
  896.         x0 = 5000 * Cos(phase)
  897.         y0 = 0
  898.         z0 = 3000 * Sin(phase)
  899.         FixedPath(FixedPathIndexTicker, p).x = x0
  900.         FixedPath(FixedPathIndexTicker, p).y = y0
  901.         FixedPath(FixedPathIndexTicker, p).z = z0
  902.     Next
  903.     For k = 1 To 30
  904.         Do
  905.             xx = (Rnd - .5) * 6 * BlockSize
  906.             yy = (Rnd - .5) * 6 * BlockSize
  907.             zz = (Rnd - .5) * 6 * BlockSize
  908.         Loop Until ((xx ^ 2 + yy ^ 2 + zz ^ 2) < (.5 * 6 * BlockSize) ^ 2)
  909.         g = NewCube&(g, "Sun", 50, xx, yy, zz, BlockSize * 6, BlockSize * 6, BlockSize * 6, Red, Red, Red, FixedPathIndexTicker, 0)
  910.         For p = Group(g).FirstVector To Group(g).LastVector
  911.             vec3Dcolor(p) = ShadeMix~&(Sunglow, SunsetOrange, Rnd)
  912.         Next
  913.         Call SetParticleVelocity(g, .5 * (Rnd - .5), .5 * (Rnd - .5), .5 * (Rnd - .5))
  914.         Group(g).PlotMode = 0
  915.     Next
  916.     SunClusterAddress = ClusterIdTicker
  917.     Call ClusterPinch(g)
  918.     CreateSun& = g
  919.  
  920. Function CreateMoon& (LagAddressIn As Long)
  921.     Dim As Integer k
  922.     Dim As Double xx, yy, zz, x0, y0, z0, phase
  923.     Dim As Long p, g
  924.     g = LagAddressIn
  925.     FixedPathIndexTicker = FixedPathIndexTicker + 1
  926.     For p = 1 To 86400
  927.         phase = -2 * pi * (48) * (p - 1) / 86400 + pi / 2
  928.         x0 = 0
  929.         y0 = 4000 * Cos(phase)
  930.         z0 = 2000 * Sin(phase)
  931.         FixedPath(FixedPathIndexTicker, p).x = x0
  932.         FixedPath(FixedPathIndexTicker, p).y = y0
  933.         FixedPath(FixedPathIndexTicker, p).z = z0
  934.     Next
  935.     For k = 1 To 30
  936.         Do
  937.             xx = (Rnd - .5) * 5 * BlockSize
  938.             yy = (Rnd - .5) * 5 * BlockSize
  939.             zz = (Rnd - .5) * 5 * BlockSize
  940.         Loop Until ((xx ^ 2 + yy ^ 2 + zz ^ 2) < (.5 * 5 * BlockSize) ^ 2)
  941.         g = NewCube&(g, "Moon", 50, xx, yy, zz, 5 * BlockSize, 5 * BlockSize, 5 * BlockSize, Gray, DarkGray, SlateGray, FixedPathIndexTicker, 0)
  942.         Group(g).PlotMode = 0
  943.     Next
  944.     MoonClusterAddress = ClusterIdTicker
  945.     Call ClusterPinch(g)
  946.     CreateMoon& = g
  947.  
  948. Function CreateFish& (LagAddressIn As Long)
  949.     Dim As Integer n, m, wi, wj
  950.     Dim As Double u, v, x0, y0, z0
  951.     Dim As Long p, g, p0
  952.     g = LagAddressIn
  953.     For n = 1 To 12
  954.         u = Rnd * 2 * pi
  955.         FixedPathIndexTicker = FixedPathIndexTicker + 1
  956.         For p = 1 To 86400
  957.             x0 = BlockSize * Plateau(1).Location.x + BlockSize * (4 + Cos(2 * pi * n / 12)) * Cos(u + 2 * pi * (24 * 30) * (p - 1) / 86400)
  958.             y0 = BlockSize * Plateau(1).Location.y + BlockSize * (4 + Cos(2 * pi * n / 12)) * Sin(u + 2 * pi * (24 * 30) * (p - 1) / 86400)
  959.             FixedPath(FixedPathIndexTicker, p).x = x0
  960.             FixedPath(FixedPathIndexTicker, p).y = y0
  961.             wi = 1 + Int(x0 / BlockSize + UBound(WorldMesh, 1) / 2)
  962.             wj = 1 + Int(y0 / BlockSize + UBound(WorldMesh, 2) / 2)
  963.             z0 = WorldMesh(wi, wj) + 100 + 80 * Cos(2 * pi * n / 12) * Cos(2 * pi * (24 * 30) * (p - 1) / 86400)
  964.             FixedPath(FixedPathIndexTicker, p).z = z0
  965.         Next
  966.         ' In the following group, there are 48 frames with 36 vectors per frame. The +1 offset is fishy, no pun.
  967.         g = NewCube&(g, "Fish", 36 * (48 + 1), 0, 0, 0, BlockSize / 4, BlockSize / 4, BlockSize / 4, LimeGreen, SunsetOrange, DarkGoldenRod, FixedPathIndexTicker, 1)
  968.         Group(g).FrameLength = 36
  969.         u = 0
  970.         For p = Group(g).FirstVector To Group(g).FirstVector + Group(g).FrameLength - 1
  971.             u = u + 2 * pi / Group(g).FrameLength
  972.             vec3Dpos(p).x = Group(g).Volume.x * (Cos(u) - Sin(u) ^ 2 / Sqr(2))
  973.             vec3Dpos(p).y = 0
  974.             vec3Dpos(p).z = Group(g).Volume.z * (Cos(u) * Sin(u))
  975.         Next
  976.         v = 0
  977.         For m = 1 To 48
  978.             v = v - 2 * pi / 48
  979.             p0 = 0
  980.             For p = Group(g).FirstVector + Group(g).FrameLength * (m) To Group(g).FirstVector + Group(g).FrameLength * (m + 1) - 1
  981.                 vec3Dpos(p).x = Cos(v) * vec3Dpos(Group(g).FirstVector + p0).x + Sin(v) * vec3Dpos(Group(g).FirstVector + p0).y
  982.                 vec3Dpos(p).y = -Sin(v) * vec3Dpos(Group(g).FirstVector + p0).x + Cos(v) * vec3Dpos(Group(g).FirstVector + p0).y
  983.                 vec3Dpos(p).z = vec3Dpos(Group(g).FirstVector + p0).z
  984.                 p0 = p0 + 1
  985.             Next
  986.         Next
  987.         Call ClusterPinch(g)
  988.     Next
  989.     CreateFish& = g
  990.  
  991. Sub InitCamera
  992.     ToggleAnimate = 1
  993.     PlayerCamera.Position.x = 0
  994.     PlayerCamera.Position.y = 0
  995.     PlayerCamera.Position.z = 100 + 40 + WorldMesh(UBound(WorldMesh, 1) / 2, UBound(WorldMesh, 2) / 2)
  996.     PlayerCamera.Velocity.x = 0
  997.     PlayerCamera.Velocity.y = 0
  998.     PlayerCamera.Velocity.z = .1
  999.     PlayerCamera.Acceleration.x = 0
  1000.     PlayerCamera.Acceleration.y = 0
  1001.     PlayerCamera.Acceleration.z = -.5
  1002.     uhat(1) = 1: uhat(2) = 0: uhat(3) = 0
  1003.     vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  1004.     Call CalculateScreenVectors
  1005.  
  1006. Sub RegulateCamera
  1007.     Dim As Double dx, dy, t
  1008.     dx = -nhat(1)
  1009.     dy = -nhat(2)
  1010.     If ((dx > 0) And (dy > 0)) Then t = -pi / 2 + (Atn(dy / dx))
  1011.     If ((dx < 0) And (dy > 0)) Then t = -pi / 2 + pi + (Atn(dy / dx))
  1012.     If ((dx < 0) And (dy < 0)) Then t = -pi / 2 + pi + (Atn(dy / dx))
  1013.     If ((dx > 0) And (dy < 0)) Then t = -pi / 2 + 2 * pi + (Atn(dy / dx))
  1014.     uhat(1) = Cos(t): uhat(2) = Sin(t): uhat(3) = 0
  1015.     vhat(1) = 0: vhat(2) = 0: vhat(3) = 1
  1016.     Call CalculateScreenVectors
  1017.  
  1018. ' Terrain tools.
  1019.  
  1020. Function TerrainHeightIndex (z0 As Double)
  1021.     Dim j As Integer
  1022.     Dim h0 As Integer
  1023.     h0 = -1
  1024.     For j = 1 To UBound(Strata)
  1025.         If (z0 <= Strata(j).Height) Then
  1026.             h0 = j - 1
  1027.             Exit For
  1028.         End If
  1029.     Next
  1030.     If (h0 = -1) Then h0 = UBound(Strata)
  1031.     TerrainHeightIndex = h0
  1032.  
  1033. Function TerrainHeightShade~& (z0 As Double)
  1034.     Dim j As Integer
  1035.     Dim h0 As Integer
  1036.     h0 = -1
  1037.     For j = 1 To UBound(Strata)
  1038.         If (z0 <= Strata(j).Height) Then
  1039.             h0 = j - 1
  1040.             Exit For
  1041.         End If
  1042.     Next
  1043.     If (h0 = -1) Then h0 = UBound(Strata)
  1044.     Dim u As Double
  1045.     Dim v As Double
  1046.     Dim alpha As Double
  1047.     Dim sh1 As _Unsigned Long
  1048.     Dim sh2 As _Unsigned Long
  1049.     Select Case h0
  1050.         Case 0
  1051.             sh1 = Strata(1).Shade
  1052.             sh2 = Strata(1).Shade
  1053.             alpha = 0
  1054.         Case UBound(Strata)
  1055.             sh1 = Strata(h0).Shade
  1056.             sh2 = Strata(h0).Shade
  1057.             alpha = 0
  1058.         Case Else
  1059.             sh1 = Strata(h0).Shade
  1060.             sh2 = Strata(h0 + 1).Shade
  1061.             u = z0 - Strata(h0).Height
  1062.             v = Strata(h0 + 1).Height - Strata(h0).Height
  1063.             alpha = u / v
  1064.     End Select
  1065.     TerrainHeightShade~& = ShadeMix~&(sh1, sh2, alpha)
  1066.  
  1067. Function TerrainHeightLabel$ (z0 As Double)
  1068.     Dim TheReturn As String
  1069.     Dim j As Integer
  1070.     Dim h0 As Integer
  1071.     h0 = -1
  1072.     For j = 1 To UBound(Strata)
  1073.         If (z0 <= Strata(j).Height) Then
  1074.             h0 = j
  1075.             Exit For
  1076.         End If
  1077.     Next
  1078.     If (h0 = -1) Then h0 = UBound(Strata)
  1079.     Select Case h0
  1080.         Case 0
  1081.             TheReturn = Strata(1).Label
  1082.         Case UBound(Strata)
  1083.             TheReturn = Strata(h0).Label
  1084.         Case Else
  1085.             TheReturn = Strata(h0).Label
  1086.     End Select
  1087.     TerrainHeightLabel$ = TheReturn
  1088.  
  1089. Function CloudHeightShade~& (z0 As Double)
  1090.     Dim j As Integer
  1091.     Dim h0 As Integer
  1092.     h0 = -1
  1093.     For j = 1 To UBound(CloudLayer)
  1094.         If (z0 <= CloudLayer(j).Height) Then
  1095.             h0 = j - 1
  1096.             Exit For
  1097.         End If
  1098.     Next
  1099.     If (h0 = -1) Then h0 = UBound(CloudLayer)
  1100.     Dim u As Double
  1101.     Dim v As Double
  1102.     Dim alpha As Double
  1103.     Dim sh1 As _Unsigned Long
  1104.     Dim sh2 As _Unsigned Long
  1105.     Select Case h0
  1106.         Case 0
  1107.             sh1 = CloudLayer(1).Shade
  1108.             sh2 = CloudLayer(1).Shade
  1109.             alpha = 0
  1110.         Case UBound(CloudLayer)
  1111.             sh1 = CloudLayer(h0).Shade
  1112.             sh2 = CloudLayer(h0).Shade
  1113.             alpha = 0
  1114.         Case Else
  1115.             sh1 = CloudLayer(h0).Shade
  1116.             sh2 = CloudLayer(h0 + 1).Shade
  1117.             u = z0 - CloudLayer(h0).Height
  1118.             v = CloudLayer(h0 + 1).Height - CloudLayer(h0).Height
  1119.             alpha = u / v
  1120.     End Select
  1121.     CloudHeightShade~& = ShadeMix~&(sh1, sh2, alpha)
  1122.  
  1123. Function CloudHeightLabel$ (z0 As Double)
  1124.     Dim TheReturn As String
  1125.     Dim j As Integer
  1126.     Dim h0 As Integer
  1127.     h0 = -1
  1128.     For j = 1 To UBound(CloudLayer)
  1129.         If (z0 <= CloudLayer(j).Height) Then
  1130.             h0 = j
  1131.             Exit For
  1132.         End If
  1133.     Next
  1134.     If (h0 = -1) Then h0 = UBound(CloudLayer)
  1135.     Select Case h0
  1136.         Case 0
  1137.             TheReturn = CloudLayer(1).Label
  1138.         Case UBound(CloudLayer)
  1139.             TheReturn = CloudLayer(h0).Label
  1140.         Case Else
  1141.             TheReturn = CloudLayer(h0).Label
  1142.     End Select
  1143.     CloudHeightLabel$ = TheReturn
  1144.  
  1145. ' Low-order groups.
  1146.  
  1147. Function NewCube& (LagAddressIn As Long, TheName As String, Weight As Integer, PosX As Double, PosY As Double, PosZ As Double, VolX As Double, VolY As Double, VolZ As Double, ShadeA As _Unsigned Long, ShadeB As _Unsigned Long, ShadeC As _Unsigned Long, TheDynamic As Integer, Framing As Integer)
  1148.     Dim k As Integer
  1149.     Dim g As Long
  1150.     Dim q As Long
  1151.     Dim vindex As Long
  1152.     q = LagAddressIn
  1153.     vindex = Group(q).LastVector
  1154.     g = NewGroup&(q, PosX, PosY, PosZ, 64, TheDynamic, Framing)
  1155.     Group(g).Label = TheName
  1156.     Group(g).Volume.x = VolX
  1157.     Group(g).Volume.y = VolY
  1158.     Group(g).Volume.z = VolZ
  1159.     Group(g).FirstVector = vindex + 1
  1160.     Group(g).PlotMode = 1
  1161.     For k = 1 To Weight
  1162.         vindex = vindex + 1
  1163.         vec3Dpos(vindex).x = (Rnd - .5) * VolX
  1164.         vec3Dpos(vindex).y = (Rnd - .5) * VolY
  1165.         vec3Dpos(vindex).z = (Rnd - .5) * VolZ
  1166.         If (Rnd > .5) Then
  1167.             vec3Dcolor(vindex) = ShadeA
  1168.         Else
  1169.             If (Rnd > .5) Then
  1170.                 vec3Dcolor(vindex) = ShadeB
  1171.             Else
  1172.                 vec3Dcolor(vindex) = ShadeC
  1173.             End If
  1174.         End If
  1175.     Next
  1176.     Group(g).LastVector = vindex
  1177.     NewCube& = g
  1178.  
  1179. Function NewWireCube& (LagAddressIn As Long, TheName As String, PosX As Double, PosY As Double, PosZ As Double, VolX As Double, VolY As Double, VolZ As Double, ShadeA As _Unsigned Long, TheDynamic As Integer)
  1180.     Dim g As Long
  1181.     Dim q As Long
  1182.     Dim vindex As Long
  1183.     q = LagAddressIn
  1184.     vindex = Group(q).LastVector
  1185.     g = NewGroup&(q, PosX, PosY, PosZ, 64, TheDynamic, 0)
  1186.     Group(g).Label = TheName
  1187.     Group(g).Volume.x = VolX
  1188.     Group(g).Volume.y = VolY
  1189.     Group(g).Volume.z = VolZ
  1190.     Group(g).FirstVector = vindex + 1
  1191.     Group(g).PlotMode = -1
  1192.  
  1193.     vindex = vindex + 1
  1194.     vec3Dpos(vindex).x = (0 - .5) * VolX
  1195.     vec3Dpos(vindex).y = (0 - .5) * VolY
  1196.     vec3Dpos(vindex).z = (0 - .5) * VolZ
  1197.     vec3Dcolor(vindex) = ShadeA
  1198.     vindex = vindex + 1
  1199.     vec3Dpos(vindex).x = (1 - .5) * VolX
  1200.     vec3Dpos(vindex).y = (0 - .5) * VolY
  1201.     vec3Dpos(vindex).z = (0 - .5) * VolZ
  1202.     vec3Dcolor(vindex) = ShadeA
  1203.     vindex = vindex + 1
  1204.     vec3Dpos(vindex).x = (0 - .5) * VolX
  1205.     vec3Dpos(vindex).y = (1 - .5) * VolY
  1206.     vec3Dpos(vindex).z = (0 - .5) * VolZ
  1207.     vec3Dcolor(vindex) = ShadeA
  1208.     vindex = vindex + 1
  1209.     vec3Dpos(vindex).x = (1 - .5) * VolX
  1210.     vec3Dpos(vindex).y = (1 - .5) * VolY
  1211.     vec3Dpos(vindex).z = (0 - .5) * VolZ
  1212.     vec3Dcolor(vindex) = ShadeA
  1213.  
  1214.     vindex = vindex + 1
  1215.     vec3Dpos(vindex).x = (0 - .5) * VolX
  1216.     vec3Dpos(vindex).y = (0 - .5) * VolY
  1217.     vec3Dpos(vindex).z = (1 - .5) * VolZ
  1218.     vec3Dcolor(vindex) = ShadeA
  1219.     vindex = vindex + 1
  1220.     vec3Dpos(vindex).x = (1 - .5) * VolX
  1221.     vec3Dpos(vindex).y = (0 - .5) * VolY
  1222.     vec3Dpos(vindex).z = (1 - .5) * VolZ
  1223.     vec3Dcolor(vindex) = ShadeA
  1224.     vindex = vindex + 1
  1225.     vec3Dpos(vindex).x = (0 - .5) * VolX
  1226.     vec3Dpos(vindex).y = (1 - .5) * VolY
  1227.     vec3Dpos(vindex).z = (1 - .5) * VolZ
  1228.     vec3Dcolor(vindex) = ShadeA
  1229.     vindex = vindex + 1
  1230.     vec3Dpos(vindex).x = (1 - .5) * VolX
  1231.     vec3Dpos(vindex).y = (1 - .5) * VolY
  1232.     vec3Dpos(vindex).z = (1 - .5) * VolZ
  1233.     vec3Dcolor(vindex) = ShadeA
  1234.  
  1235.     Group(g).LastVector = vindex
  1236.     NewWireCube& = g
  1237.  
  1238. ' Linked list utility.
  1239.  
  1240. Function LatestGroupIdentity& (StartingID As Long)
  1241.     Dim TheReturn As Long
  1242.     Dim As Long p, q
  1243.     p = StartingID
  1244.     If (p = 0) Then
  1245.         q = 0
  1246.     Else
  1247.         Do
  1248.             q = p
  1249.             p = Group(q).Pointer
  1250.             If (p = -999) Then Exit Do
  1251.         Loop
  1252.     End If
  1253.     TheReturn = q
  1254.     LatestGroupIdentity& = TheReturn
  1255.  
  1256. Function LatestClusterIdentity& (StartingID As Long)
  1257.     Dim TheReturn As Long
  1258.     Dim As Long p, q
  1259.     p = StartingID
  1260.     If (p = 0) Then
  1261.         q = 0
  1262.     Else
  1263.         Do
  1264.             q = p
  1265.             p = Cluster(q).Pointer
  1266.             If (p = -999) Then Exit Do
  1267.         Loop
  1268.     End If
  1269.     TheReturn = q
  1270.     LatestClusterIdentity& = TheReturn
  1271.  
  1272. Function NewGroup& (LagAddressIn As Long, CenterX As Double, CenterY As Double, CenterZ As Double, ClusterSize As Integer, TheDynamic As Integer, Framing As Integer)
  1273.     Dim As Long g0
  1274.     g0 = LatestGroupIdentity&(LagAddressIn)
  1275.     GroupIdTicker = GroupIdTicker + 1
  1276.     Group(GroupIdTicker).Identity = GroupIdTicker
  1277.     Group(GroupIdTicker).Pointer = -999
  1278.     Group(GroupIdTicker).Lagger = g0
  1279.     Group(GroupIdTicker).Centroid.x = CenterX
  1280.     Group(GroupIdTicker).Centroid.y = CenterY
  1281.     Group(GroupIdTicker).Centroid.z = CenterZ
  1282.     Group(GroupIdTicker).FrameLength = 0
  1283.     Group(GroupIdTicker).ActiveFrame = 0
  1284.     If (Group(GroupIdTicker).Lagger <> 0) Then
  1285.         Group(g0).Pointer = GroupIdTicker
  1286.     End If
  1287.  
  1288.     ' Adjust corresponding cluster.
  1289.     ClusterFillCounter = ClusterFillCounter + 1
  1290.     If (ClusterFillCounter = 1) Then
  1291.         Call NewCluster(1, Group(GroupIdTicker).Identity, TheDynamic, Framing) '''
  1292.     End If
  1293.     If (ClusterFillCounter = ClusterSize) Then
  1294.         Call ClusterPinch(Group(GroupIdTicker).Identity)
  1295.     End If
  1296.  
  1297.     NewGroup& = Group(GroupIdTicker).Identity
  1298.  
  1299.  
  1300. Sub NewCluster (ClusterLagIn As Long, FirstGroupIn As Long, TheDynamic As Integer, Framing As Integer)
  1301.     Dim As Long k0
  1302.     If (ClusterIdTicker = 0) Then
  1303.         k0 = -1
  1304.     Else
  1305.         k0 = LatestClusterIdentity&(ClusterLagIn)
  1306.     End If
  1307.     ClusterIdTicker = ClusterIdTicker + 1
  1308.     Cluster(ClusterIdTicker).Identity = ClusterIdTicker
  1309.     Cluster(ClusterIdTicker).Pointer = -999
  1310.     Cluster(ClusterIdTicker).Lagger = k0
  1311.     Cluster(ClusterIdTicker).FirstGroup = FirstGroupIn
  1312.     Cluster(ClusterIdTicker).MotionType = TheDynamic
  1313.     Cluster(ClusterIdTicker).Framed = Framing
  1314.     If (ClusterIdTicker > 1) Then Cluster(k0).Pointer = ClusterIdTicker
  1315.  
  1316.  
  1317.  
  1318. Sub RemoveGroup (TheAddressIn As Long)
  1319.     Dim As Long g, p, l, k, ci
  1320.     Dim As Integer f
  1321.     g = TheAddressIn
  1322.  
  1323.     f = 0
  1324.     k = 1
  1325.     Do
  1326.         If (Cluster(k).FirstGroup = g) And (Cluster(k).LastGroup <> g) Then
  1327.             f = 1
  1328.             ci = k
  1329.             Exit Do
  1330.         End If
  1331.         If (Cluster(k).FirstGroup <> g) And (Cluster(k).LastGroup = g) Then
  1332.             f = 2
  1333.             ci = k
  1334.             Exit Do
  1335.         End If
  1336.         If ((Cluster(k).LastGroup = g) And (Cluster(k).LastGroup = g)) Then
  1337.             f = 3
  1338.             ci = k
  1339.             Exit Do
  1340.         End If
  1341.         k = Cluster(k).Pointer
  1342.         If (k = -999) Then Exit Do
  1343.     Loop
  1344.  
  1345.     Select Case f
  1346.         Case 0
  1347.             p = Group(g).Pointer
  1348.             l = Group(g).Lagger
  1349.             Group(l).Pointer = p
  1350.             If (p <> -999) Then
  1351.                 Group(p).Lagger = l
  1352.             End If
  1353.  
  1354.         Case 1
  1355.             p = Group(g).Pointer
  1356.             l = Group(g).Lagger
  1357.             Group(l).Pointer = p
  1358.             If (p <> -999) Then
  1359.                 Group(p).Lagger = l
  1360.             End If
  1361.  
  1362.             Cluster(ci).FirstGroup = p
  1363.             Call ClusterCentroidCalc(ci)
  1364.         Case 2
  1365.             p = Group(g).Pointer
  1366.             l = Group(g).Lagger
  1367.             Group(l).Pointer = p
  1368.             If (p <> -999) Then
  1369.                 Group(p).Lagger = l
  1370.             End If
  1371.  
  1372.             Cluster(ci).LastGroup = l
  1373.             Call ClusterCentroidCalc(ci)
  1374.         Case 3
  1375.             p = Group(g).Pointer
  1376.             l = Group(g).Lagger
  1377.             Group(l).Pointer = p
  1378.             If (p <> -999) Then
  1379.                 Group(p).Lagger = l
  1380.             End If
  1381.  
  1382.             Call RemoveCluster(ci)
  1383.     End Select
  1384.  
  1385. Sub RemoveCluster (TheAddressIn As Long)
  1386.     Dim As Long k, p, l
  1387.     k = TheAddressIn
  1388.     p = Cluster(k).Pointer
  1389.     l = Cluster(k).Lagger
  1390.     If (l <> -1) Then
  1391.         Cluster(l).Pointer = p
  1392.     End If
  1393.     If (p <> -999) Then
  1394.         Cluster(p).Lagger = l
  1395.     End If
  1396.  
  1397. Sub ClusterPinch (TheLastGroup As Long)
  1398.     ClusterFillCounter = 0
  1399.     Cluster(ClusterIdTicker).LastGroup = TheLastGroup
  1400.     Call ClusterCentroidCalc(ClusterIdTicker)
  1401.  
  1402. Sub ClusterCentroidCalc (TheCluster As Long)
  1403.     Dim As Long g
  1404.     Dim As Integer n
  1405.     Cluster(TheCluster).Centroid.x = 0
  1406.     Cluster(TheCluster).Centroid.y = 0
  1407.     Cluster(TheCluster).Centroid.z = 0
  1408.     g = Cluster(TheCluster).FirstGroup
  1409.     n = 0
  1410.     Do
  1411.         Cluster(TheCluster).Centroid.x = Cluster(TheCluster).Centroid.x + Group(g).Centroid.x
  1412.         Cluster(TheCluster).Centroid.y = Cluster(TheCluster).Centroid.y + Group(g).Centroid.y
  1413.         Cluster(TheCluster).Centroid.z = Cluster(TheCluster).Centroid.z + Group(g).Centroid.z
  1414.         n = n + 1
  1415.         If (g = Cluster(TheCluster).LastGroup) Then Exit Do
  1416.         g = Group(g).Pointer
  1417.     Loop
  1418.     Cluster(TheCluster).Centroid.x = Cluster(TheCluster).Centroid.x / n
  1419.     Cluster(TheCluster).Centroid.y = Cluster(TheCluster).Centroid.y / n
  1420.     Cluster(TheCluster).Centroid.z = Cluster(TheCluster).Centroid.z / n
  1421.  
  1422. ' Player Dynamics
  1423.  
  1424. Sub PlayerDynamics
  1425.     If (ToggleAnimate = 1) Then
  1426.  
  1427.         ' Player kinematics
  1428.         PlayerCamera.Velocity.x = PlayerCamera.Velocity.x + PlayerCamera.Acceleration.x
  1429.         PlayerCamera.Velocity.y = PlayerCamera.Velocity.y + PlayerCamera.Acceleration.y
  1430.         PlayerCamera.Velocity.z = PlayerCamera.Velocity.z + PlayerCamera.Acceleration.z
  1431.         PlayerCamera.Velocity.x = .95 * PlayerCamera.Velocity.x
  1432.         PlayerCamera.Velocity.y = .95 * PlayerCamera.Velocity.y
  1433.         PlayerCamera.Velocity.z = .95 * PlayerCamera.Velocity.z
  1434.         PlayerCamera.Position.x = PlayerCamera.Position.x + PlayerCamera.Velocity.x
  1435.         PlayerCamera.Position.y = PlayerCamera.Position.y + PlayerCamera.Velocity.y
  1436.         PlayerCamera.Position.z = PlayerCamera.Position.z + PlayerCamera.Velocity.z
  1437.  
  1438.         ' Terrain traversal.
  1439.         Dim As Double qi, qj
  1440.         Dim As Integer wi, wj
  1441.         qi = (PlayerCamera.Position.x) / BlockSize + UBound(WorldMesh, 1) / 2
  1442.         qj = (PlayerCamera.Position.y) / BlockSize + UBound(WorldMesh, 2) / 2
  1443.         wi = 1 + Int(qi)
  1444.         wj = 1 + Int(qj)
  1445.         If (wi < 1) Then wi = 1
  1446.         If (wj < 1) Then wj = 1
  1447.         If (wi > UBound(WorldMesh, 1)) Then wi = UBound(WorldMesh, 1)
  1448.         If (wj > UBound(WorldMesh, 2)) Then wj = UBound(WorldMesh, 2)
  1449.         If (PlayerCamera.Velocity.z = 0) Then
  1450.             PlayerCamera.Position.z = PlayerCamera.Position.z + .15 * ((40 + WorldMesh(wi, wj) - PlayerCamera.Position.z))
  1451.         End If
  1452.  
  1453.         ' Collision with ground after jump.
  1454.         If ((PlayerCamera.Velocity.z <> 0) And (PlayerCamera.Position.z < (40 + WorldMesh(wi, wj)))) Then
  1455.             PlayerCamera.Acceleration.z = 0
  1456.             PlayerCamera.Velocity.z = 0
  1457.         End If
  1458.  
  1459.         ' Collision with tornado.
  1460.         If (Group(ClosestGroup).Label = "Tornado") Then
  1461.             PlayerCamera.Velocity.x = (Rnd - .5) * 20
  1462.             PlayerCamera.Velocity.y = (Rnd - .5) * 20
  1463.             PlayerCamera.Velocity.z = 20
  1464.             PlayerCamera.Acceleration.z = -.5
  1465.         End If
  1466.  
  1467.         'Un-zoom camera.
  1468.         If ((fovd <> -192) And (_KeyDown(90) = 0) And (_KeyDown(122) = 0)) Then
  1469.             fovd = Int(.5 * (fovd - 192)) + 1
  1470.             farplane(4) = -256 'Int(.5 * (farplane(4) - 256))
  1471.             Call CalculateClippingPlanes(_Width, _Height)
  1472.         End If
  1473.  
  1474.     End If
  1475.  
  1476. ' Compute Visible Scene
  1477.  
  1478. Sub ComputeVisibleScene
  1479.     Dim As Long g, k
  1480.     Dim As Double dx, dy, dz
  1481.     Dim closestdist2 As Double
  1482.     Dim fp42 As Double
  1483.     Dim dist2 As Double
  1484.     Dim GroupInView As Integer
  1485.     ClosestGroup = 1
  1486.     closestdist2 = 10000000
  1487.     fp42 = farplane(4) * farplane(4)
  1488.  
  1489.     k = 1
  1490.     Do
  1491.         dx = Cluster(k).Centroid.x - PlayerCamera.Position.x
  1492.         dy = Cluster(k).Centroid.y - PlayerCamera.Position.y
  1493.         dz = Cluster(k).Centroid.z - PlayerCamera.Position.z
  1494.         dist2 = dx * dx + dy * dy + dz * dz
  1495.         '''
  1496.         If k = SunClusterAddress And Cluster(k).Centroid.z > 0 Then GoTo 100
  1497.         If k = MoonClusterAddress And Cluster(k).Centroid.z > 0 Then GoTo 100
  1498.         '''
  1499.         If (dist2 > 600 * 600) Then
  1500.             Cluster(k).Visible = 0
  1501.             If ((Cluster(k).MotionType <> 0) And (ToggleAnimate = 1)) Then
  1502.                 Call EvolveCluster(k)
  1503.             End If
  1504.         Else
  1505.             '''
  1506.            100
  1507.             '''
  1508.             Cluster(k).Visible = 1
  1509.             g = Cluster(k).FirstGroup
  1510.             If ((Cluster(k).MotionType <> 0) And (ToggleAnimate = 1)) Then
  1511.                 Call EvolveCluster(k)
  1512.             End If
  1513.             Do
  1514.                 dx = Group(g).Centroid.x - PlayerCamera.Position.x
  1515.                 dy = Group(g).Centroid.y - PlayerCamera.Position.y
  1516.                 dz = Group(g).Centroid.z - PlayerCamera.Position.z
  1517.                 dist2 = dx * dx + dy * dy + dz * dz
  1518.                 Group(g).Visible = 0
  1519.                 '''
  1520.                 If k = SunClusterAddress Then GoTo 200
  1521.                 If k = MoonClusterAddress Then GoTo 200
  1522.                 '''
  1523.  
  1524.                 If (dist2 < fp42) Then
  1525.                     '''
  1526.                    200
  1527.                     '''
  1528.                     GroupInView = 1
  1529.                     If dx * nearplane(1) + dy * nearplane(2) + dz * nearplane(3) - nearplane(4) < 0 Then GroupInView = 0
  1530.                     'IF dx * farplane(1) + dy * farplane(2) + dz * farplane(3) - farplane(4) < 0 THEN groupinview = 0 ''' Redundant
  1531.                     If dx * rightplane(1) + dy * rightplane(2) + dz * rightplane(3) - rightplane(4) < 0 Then GroupInView = 0
  1532.                     If dx * leftplane(1) + dy * leftplane(2) + dz * leftplane(3) - leftplane(4) < 0 Then GroupInView = 0
  1533.                     If dx * topplane(1) + dy * topplane(2) + dz * topplane(3) - topplane(4) < 0 Then GroupInView = 0
  1534.                     If dx * bottomplane(1) + dy * bottomplane(2) + dz * bottomplane(3) - bottomplane(4) < 0 Then GroupInView = 0
  1535.                     If (GroupInView = 1) Then
  1536.                         Group(g).Visible = 1
  1537.                         If (dist2 < closestdist2) Then
  1538.                             closestdist2 = dist2
  1539.                             ClosestGroup = g
  1540.                         End If
  1541.                         Group(g).Distance2 = dist2
  1542.                         If (ToggleAnimate = 1) And (Group(g).FrameLength = 0) Then Call EvolveVectors(g)
  1543.  
  1544.                         '''
  1545.                         If k = SunClusterAddress Or k = MoonClusterAddress Then
  1546.                             If PlayerCamera.Position.z < -40 Then
  1547.                                 Call ProjectGroup(g, Group(g).FirstVector, Group(g).LastVector, 1)
  1548.                             Else
  1549.                                 Call ProjectGroup(g, Group(g).FirstVector, Group(g).LastVector, 0)
  1550.                             End If
  1551.                         Else
  1552.                             If Group(g).FrameLength <> 0 And Group(g).ActiveFrame <> 0 Then
  1553.                                 Call ProjectGroup(g, Group(g).FirstVector + Group(g).ActiveFrame * Group(g).FrameLength, Group(g).FirstVector + Group(g).ActiveFrame * Group(g).FrameLength + Group(g).FrameLength, 1)
  1554.                             Else
  1555.                                 Call ProjectGroup(g, Group(g).FirstVector, Group(g).LastVector, 1)
  1556.                             End If
  1557.                         End If
  1558.                         '''
  1559.  
  1560.                     End If
  1561.                 End If
  1562.                 If (g = Cluster(k).LastGroup) Then Exit Do
  1563.                 g = Group(g).Pointer
  1564.             Loop
  1565.         End If
  1566.  
  1567.         k = Cluster(k).Pointer
  1568.         If (k = -999) Then Exit Do
  1569.     Loop
  1570.  
  1571. Sub CalculateScreenVectors
  1572.     Dim As Double mag
  1573.     mag = 1 / Sqr(uhat(1) * uhat(1) + uhat(2) * uhat(2) + uhat(3) * uhat(3))
  1574.     uhat(1) = uhat(1) * mag: uhat(2) = uhat(2) * mag: uhat(3) = uhat(3) * mag
  1575.     mag = 1 / Sqr(vhat(1) * vhat(1) + vhat(2) * vhat(2) + vhat(3) * vhat(3))
  1576.     vhat(1) = vhat(1) * mag: vhat(2) = vhat(2) * mag: vhat(3) = vhat(3) * mag
  1577.     nhat(1) = uhat(2) * vhat(3) - uhat(3) * vhat(2)
  1578.     nhat(2) = uhat(3) * vhat(1) - uhat(1) * vhat(3)
  1579.     nhat(3) = uhat(1) * vhat(2) - uhat(2) * vhat(1)
  1580.     Call CalculateClippingPlanes(_Width, _Height)
  1581.  
  1582. Sub CalculateClippingPlanes (TheWidth As Double, TheHeight As Double)
  1583.     Dim As Double h2, w2, h2f, w2f, h2w2, mag
  1584.     h2 = TheHeight * .5
  1585.     w2 = TheWidth * .5
  1586.     h2f = h2 * fovd
  1587.     w2f = w2 * fovd
  1588.     h2w2 = h2 * w2
  1589.     nearplane(1) = -nhat(1)
  1590.     nearplane(2) = -nhat(2)
  1591.     nearplane(3) = -nhat(3)
  1592.     farplane(1) = nhat(1)
  1593.     farplane(2) = nhat(2)
  1594.     farplane(3) = nhat(3)
  1595.     rightplane(1) = h2f * uhat(1) - h2w2 * nhat(1)
  1596.     rightplane(2) = h2f * uhat(2) - h2w2 * nhat(2)
  1597.     rightplane(3) = h2f * uhat(3) - h2w2 * nhat(3)
  1598.     mag = 1 / Sqr(rightplane(1) * rightplane(1) + rightplane(2) * rightplane(2) + rightplane(3) * rightplane(3))
  1599.     rightplane(1) = rightplane(1) * mag
  1600.     rightplane(2) = rightplane(2) * mag
  1601.     rightplane(3) = rightplane(3) * mag
  1602.     leftplane(1) = -h2f * uhat(1) - h2w2 * nhat(1)
  1603.     leftplane(2) = -h2f * uhat(2) - h2w2 * nhat(2)
  1604.     leftplane(3) = -h2f * uhat(3) - h2w2 * nhat(3)
  1605.     mag = 1 / Sqr(leftplane(1) * leftplane(1) + leftplane(2) * leftplane(2) + leftplane(3) * leftplane(3))
  1606.     leftplane(1) = leftplane(1) * mag
  1607.     leftplane(2) = leftplane(2) * mag
  1608.     leftplane(3) = leftplane(3) * mag
  1609.     topplane(1) = w2f * vhat(1) - h2w2 * nhat(1)
  1610.     topplane(2) = w2f * vhat(2) - h2w2 * nhat(2)
  1611.     topplane(3) = w2f * vhat(3) - h2w2 * nhat(3)
  1612.     mag = 1 / Sqr(topplane(1) * topplane(1) + topplane(2) * topplane(2) + topplane(3) * topplane(3))
  1613.     topplane(1) = topplane(1) * mag
  1614.     topplane(2) = topplane(2) * mag
  1615.     topplane(3) = topplane(3) * mag
  1616.     bottomplane(1) = -w2f * vhat(1) - h2w2 * nhat(1)
  1617.     bottomplane(2) = -w2f * vhat(2) - h2w2 * nhat(2)
  1618.     bottomplane(3) = -w2f * vhat(3) - h2w2 * nhat(3)
  1619.     mag = 1 / Sqr(bottomplane(1) * bottomplane(1) + bottomplane(2) * bottomplane(2) + bottomplane(3) * bottomplane(3))
  1620.     bottomplane(1) = bottomplane(1) * mag
  1621.     bottomplane(2) = bottomplane(2) * mag
  1622.     bottomplane(3) = bottomplane(3) * mag
  1623.  
  1624. Sub ProjectGroup (TheGroup As Long, LowIndex As Long, HighIndex As Long, GraySwitch As Integer)
  1625.     Dim As Vector3 vec(UBound(vec3Dpos))
  1626.     Dim As Integer vectorinview
  1627.     Dim As Double vec3ddotnhat
  1628.     Dim i As Long
  1629.     Dim f As Integer
  1630.     For i = LowIndex To HighIndex
  1631.         vec(i).x = Group(TheGroup).Centroid.x + vec3Dpos(i).x - PlayerCamera.Position.x
  1632.         vec(i).y = Group(TheGroup).Centroid.y + vec3Dpos(i).y - PlayerCamera.Position.y
  1633.         vec(i).z = Group(TheGroup).Centroid.z + vec3Dpos(i).z - PlayerCamera.Position.z
  1634.         f = -1
  1635.         vec3Dvis(i) = 0
  1636.         vectorinview = 1
  1637.         If vec(i).x * nearplane(1) + vec(i).y * nearplane(2) + vec(i).z * nearplane(3) - nearplane(4) < 0 Then vectorinview = 0
  1638.         'IF vec(i).x * farplane(1) + vec(i).y * farplane(2) + vec(i).z* farplane(3) - farplane(4) < 0 THEN vectorinview = 0
  1639.         If vec(i).x * farplane(1) + vec(i).y * farplane(2) + vec(i).z * farplane(3) - farplane(4) * .85 < 0 Then f = 1
  1640.         'IF vec(i).x * rightplane(1) + vec(i).y * rightplane(2) + vec(i).z * rightplane(3) - rightplane(4) < 0 THEN vectorinview = 0
  1641.         'IF vec(i).x * leftplane(1) + vec(i).y * leftplane(2) + vec(i).z * leftplane(3) - leftplane(4) < 0 THEN vectorinview = 0
  1642.         'IF vec(i).x * topplane(1) + vec(i).y * topplane(2) + vec(i).z * topplane(3) - topplane(4) < 0 THEN vectorinview = 0
  1643.         'IF vec(i).x * bottomplane(1) + vec(i).y * bottomplane(2) + vec(i).z* bottomplane(3) - bottomplane(4) < 0 THEN vectorinview = 0
  1644.         If (vectorinview = 1) Then
  1645.             vec3Dvis(i) = 1
  1646.             vec3ddotnhat = vec(i).x * nhat(1) + vec(i).y * nhat(2) + vec(i).z * nhat(3)
  1647.             vec2D(i).u = (vec(i).x * uhat(1) + vec(i).y * uhat(2) + vec(i).z * uhat(3)) * fovd / vec3ddotnhat
  1648.             vec2D(i).v = (vec(i).x * vhat(1) + vec(i).y * vhat(2) + vec(i).z * vhat(3)) * fovd / vec3ddotnhat
  1649.             If ((GraySwitch = 1) And (f = 1)) Then
  1650.                 vec2Dcolor(i) = Gray
  1651.             Else
  1652.                 vec2Dcolor(i) = vec3Dcolor(i)
  1653.             End If
  1654.         End If
  1655.     Next
  1656.  
  1657. Sub EvolveCluster (TheCluster As Long)
  1658.     Dim u As Long
  1659.     Dim k As Long
  1660.     Dim As Single xx, yy, zz ' Needs to be single otherwise the fish flip flop. wtf?
  1661.     Dim As Double x0, y0 ', z0
  1662.     Dim As Double dx, dy, dz
  1663.     Dim As Double t
  1664.     Dim As Double v
  1665.     'Dim xx, yy, zz, x0, y0, dx, dy, dz, t, v As Double
  1666.     Select Case Cluster(TheCluster).MotionType
  1667.         Case 0
  1668.             ' Do nothing.
  1669.  
  1670.         Case -1
  1671.             ' Freefall and explode.
  1672.             Cluster(TheCluster).Velocity.x = Cluster(TheCluster).Velocity.x + Cluster(TheCluster).Acceleration.x
  1673.             Cluster(TheCluster).Velocity.y = Cluster(TheCluster).Velocity.y + Cluster(TheCluster).Acceleration.y
  1674.             Cluster(TheCluster).Velocity.z = Cluster(TheCluster).Velocity.z + Cluster(TheCluster).Acceleration.z
  1675.             dx = Cluster(TheCluster).Velocity.x
  1676.             dy = Cluster(TheCluster).Velocity.y
  1677.             dz = Cluster(TheCluster).Velocity.z
  1678.             If ((dx <> 0) Or (dy <> 0) Or (dz <> 0)) Then
  1679.                 Call TranslateCluster(TheCluster, dx, dy, dz)
  1680.             End If
  1681.             Dim wi As Integer
  1682.             Dim wj As Integer
  1683.             wi = 1 + Int((Cluster(TheCluster).Centroid.x) / BlockSize + UBound(WorldMesh, 1) / 2)
  1684.             wj = 1 + Int((Cluster(TheCluster).Centroid.y) / BlockSize + UBound(WorldMesh, 2) / 2)
  1685.             If (Cluster(TheCluster).Centroid.z <= WorldMesh(wi, wj)) Then
  1686.                 Cluster(TheCluster).Acceleration.x = 0
  1687.                 Cluster(TheCluster).Acceleration.y = 0
  1688.                 Cluster(TheCluster).Acceleration.z = 0
  1689.                 Cluster(TheCluster).Velocity.x = 0
  1690.                 Cluster(TheCluster).Velocity.y = 0
  1691.                 Cluster(TheCluster).Velocity.z = 0
  1692.                 Cluster(TheCluster).MotionType = -9
  1693.                 Cluster(TheCluster).DeathTimer = Timer + 2
  1694.                 k = Cluster(TheCluster).FirstGroup
  1695.                 Do
  1696.                     Group(k).Volume.x = BlockSize * 3
  1697.                     Group(k).Volume.y = BlockSize * 3
  1698.                     Group(k).Volume.z = BlockSize * 3
  1699.                     For u = Group(k).FirstVector To Group(k).LastVector
  1700.                         vec3Dvel(u).x = (Rnd - .5) * .8
  1701.                         vec3Dvel(u).y = (Rnd - .5) * .8
  1702.                         vec3Dvel(u).z = (Rnd - 0) * .8
  1703.                     Next
  1704.                     If (k = Cluster(TheCluster).LastGroup) Then Exit Do
  1705.                     k = Group(k).Pointer
  1706.                 Loop
  1707.             End If
  1708.  
  1709.         Case -2
  1710.             ' Freefall and stack.
  1711.             Cluster(TheCluster).Velocity.x = Cluster(TheCluster).Velocity.x + Cluster(TheCluster).Acceleration.x
  1712.             Cluster(TheCluster).Velocity.y = Cluster(TheCluster).Velocity.y + Cluster(TheCluster).Acceleration.y
  1713.             Cluster(TheCluster).Velocity.z = Cluster(TheCluster).Velocity.z + Cluster(TheCluster).Acceleration.z
  1714.             dx = Cluster(TheCluster).Velocity.x
  1715.             dy = Cluster(TheCluster).Velocity.y
  1716.             dz = Cluster(TheCluster).Velocity.z
  1717.             If ((dx <> 0) Or (dy <> 0) Or (dz <> 0)) Then
  1718.                 Call TranslateCluster(TheCluster, dx, dy, dz)
  1719.             End If
  1720.             wi = 1 + Int((Cluster(TheCluster).Centroid.x) / BlockSize + UBound(WorldMesh, 1) / 2)
  1721.             wj = 1 + Int((Cluster(TheCluster).Centroid.y) / BlockSize + UBound(WorldMesh, 2) / 2)
  1722.             If (Cluster(TheCluster).Centroid.z <= WorldMesh(wi, wj)) Then
  1723.                 Cluster(TheCluster).Acceleration.x = 0
  1724.                 Cluster(TheCluster).Acceleration.y = 0
  1725.                 Cluster(TheCluster).Acceleration.z = 0
  1726.                 Cluster(TheCluster).Velocity.x = 0
  1727.                 Cluster(TheCluster).Velocity.y = 0
  1728.                 Cluster(TheCluster).Velocity.z = 0
  1729.                 Cluster(TheCluster).MotionType = 0
  1730.                 WorldMesh(wi, wj) = WorldMesh(wi, wj) + BlockSize / 3
  1731.             End If
  1732.  
  1733.         Case -9
  1734.             If (Timer >= Cluster(TheCluster).DeathTimer) Then
  1735.                 Call RemoveCluster(TheCluster)
  1736.             End If
  1737.  
  1738.         Case Else
  1739.             ' Fixed path.
  1740.             ' Note: This chunk of code is subject to the midnight bug.
  1741.             t = Timer
  1742.             u = Int(t)
  1743.             v = t - u
  1744.             xx = v * FixedPath(Cluster(TheCluster).MotionType, u).x + (1 - v) * FixedPath(Cluster(TheCluster).MotionType, u - 1).x
  1745.             yy = v * FixedPath(Cluster(TheCluster).MotionType, u).y + (1 - v) * FixedPath(Cluster(TheCluster).MotionType, u - 1).y
  1746.             zz = v * FixedPath(Cluster(TheCluster).MotionType, u).z + (1 - v) * FixedPath(Cluster(TheCluster).MotionType, u - 1).z
  1747.  
  1748.             ' Choose frame based on derived velocity vector.
  1749.             If (Cluster(TheCluster).Framed = 1) Then
  1750.                 k = Cluster(TheCluster).FirstGroup
  1751.                 Do
  1752.                     If (Group(k).FrameLength <> 0) Then
  1753.                         x0 = Group(k).Centroid.x
  1754.                         y0 = Group(k).Centroid.y
  1755.                         'z0 = Group(k).Centroid.z
  1756.                         dx = xx - x0
  1757.                         dy = yy - y0
  1758.                         'dz = zz - z0
  1759.                         If ((dx > 0) And (dy > 0)) Then Group(k).ActiveFrame = 1 + Int(((48 / (2 * pi)) * (Atn(dy / dx))))
  1760.                         If ((dx < 0) And (dy > 0)) Then Group(k).ActiveFrame = 1 + 24 + Int(((48 / (2 * pi)) * (Atn(dy / dx))))
  1761.                         If ((dx < 0) And (dy < 0)) Then Group(k).ActiveFrame = 1 + 24 + Int(((48 / (2 * pi)) * (Atn(dy / dx))))
  1762.                         If ((dx > 0) And (dy < 0)) Then Group(k).ActiveFrame = 1 + 48 + Int(((48 / (2 * pi)) * (Atn(dy / dx))))
  1763.                     End If
  1764.                     If (k = Cluster(TheCluster).LastGroup) Then Exit Do
  1765.                     k = Group(k).Pointer
  1766.                 Loop
  1767.             End If
  1768.  
  1769.             Call PlaceCluster(TheCluster, xx, yy, zz)
  1770.  
  1771.     End Select
  1772.  
  1773. Sub PlaceCluster (TheCluster As Long, xc As Double, yc As Double, zc As Double)
  1774.     Dim As Long g
  1775.     Dim As Double x0, y0, z0
  1776.     x0 = Cluster(TheCluster).Centroid.x
  1777.     y0 = Cluster(TheCluster).Centroid.y
  1778.     z0 = Cluster(TheCluster).Centroid.z
  1779.     Cluster(TheCluster).Centroid.x = xc
  1780.     Cluster(TheCluster).Centroid.y = yc
  1781.     Cluster(TheCluster).Centroid.z = zc
  1782.     g = Cluster(TheCluster).FirstGroup
  1783.     Do
  1784.         Group(g).Centroid.x = Group(g).Centroid.x + xc - x0
  1785.         Group(g).Centroid.y = Group(g).Centroid.y + yc - y0
  1786.         Group(g).Centroid.z = Group(g).Centroid.z + zc - z0
  1787.         If (g = Cluster(TheCluster).LastGroup) Then Exit Do
  1788.         g = Group(g).Pointer
  1789.     Loop
  1790.  
  1791. Sub TranslateCluster (TheCluster As Long, dx As Double, dy As Double, dz As Double)
  1792.     Dim As Long g
  1793.     g = Cluster(TheCluster).FirstGroup
  1794.     Do
  1795.         Group(g).Centroid.x = Group(g).Centroid.x + dx
  1796.         Group(g).Centroid.y = Group(g).Centroid.y + dy
  1797.         Group(g).Centroid.z = Group(g).Centroid.z + dz
  1798.         If (g = Cluster(TheCluster).LastGroup) Then Exit Do
  1799.         g = Group(g).Pointer
  1800.     Loop
  1801.     Cluster(TheCluster).Centroid.x = Cluster(TheCluster).Centroid.x + dx
  1802.     Cluster(TheCluster).Centroid.y = Cluster(TheCluster).Centroid.y + dy
  1803.     Cluster(TheCluster).Centroid.z = Cluster(TheCluster).Centroid.z + dz
  1804.  
  1805. Sub EvolveVectors (TheGroup As Long)
  1806.     Dim As Long g
  1807.     Dim As Double xdim, ydim, zdim
  1808.     Dim As Double dx, dy, dz
  1809.     Dim As Double px, py, pz
  1810.  
  1811.     xdim = Group(TheGroup).Volume.x
  1812.     ydim = Group(TheGroup).Volume.y
  1813.     zdim = Group(TheGroup).Volume.z
  1814.  
  1815.     For g = Group(TheGroup).FirstVector To Group(TheGroup).LastVector
  1816.  
  1817.         ' Position update with periodic boundaries inside group volume.
  1818.         dx = vec3Dvel(g).x
  1819.         dy = vec3Dvel(g).y
  1820.         dz = vec3Dvel(g).z
  1821.         If (dx <> 0) Then
  1822.             px = vec3Dpos(g).x + dx
  1823.             If Abs(px) > xdim / 2 Then
  1824.                 If (px > xdim / 2) Then
  1825.                     px = -xdim / 2
  1826.                 Else
  1827.                     px = xdim / 2
  1828.                 End If
  1829.             End If
  1830.             vec3Dpos(g).x = px
  1831.         End If
  1832.         If (dy <> 0) Then
  1833.             py = vec3Dpos(g).y + dy
  1834.             If Abs(py) > ydim / 2 Then
  1835.                 If (py > ydim / 2) Then
  1836.                     py = -ydim / 2
  1837.                 Else
  1838.                     py = ydim / 2
  1839.                 End If
  1840.             End If
  1841.             vec3Dpos(g).y = py
  1842.         End If
  1843.         If (dz <> 0) Then
  1844.             pz = vec3Dpos(g).z + dz
  1845.             If Abs(pz) > zdim / 2 Then
  1846.                 If (pz > zdim / 2) Then
  1847.                     pz = -zdim / 2
  1848.                 Else
  1849.                     pz = zdim / 2
  1850.                 End If
  1851.             End If
  1852.             vec3Dpos(g).z = pz
  1853.         End If
  1854.     Next
  1855.  
  1856. Sub SetParticleVelocity (TheGroup As Long, vx As Double, vy As Double, vz As Double)
  1857.     Dim As Long j, m, n
  1858.     m = Group(TheGroup).FirstVector
  1859.     n = Group(TheGroup).LastVector
  1860.     For j = m To n
  1861.         vec3Dvel(j).x = vx
  1862.         vec3Dvel(j).y = vy
  1863.         vec3Dvel(j).z = vz
  1864.     Next
  1865.  
  1866. ' Sorting
  1867.  
  1868. Sub QuickSort (LowLimit As Long, HighLimit As Long)
  1869.     Dim As Long piv
  1870.     If (LowLimit < HighLimit) Then
  1871.         piv = Partition(LowLimit, HighLimit)
  1872.         Call QuickSort(LowLimit, piv - 1)
  1873.         Call QuickSort(piv + 1, HighLimit)
  1874.     End If
  1875.  
  1876. Function Partition (LowLimit As Long, HighLimit As Long)
  1877.     Dim As Long i, j
  1878.     Dim As Double pivot, tmp
  1879.     pivot = Group(SortedGroups(HighLimit)).Distance2
  1880.     i = LowLimit - 1
  1881.  
  1882.     For j = LowLimit To HighLimit - 1
  1883.         tmp = Group(SortedGroups(j)).Distance2 - pivot
  1884.         If (tmp >= 0) Then
  1885.             i = i + 1
  1886.             Swap SortedGroups(i), SortedGroups(j)
  1887.         End If
  1888.     Next
  1889.     Swap SortedGroups(i + 1), SortedGroups(HighLimit)
  1890.     Partition = i + 1
  1891.  
  1892. 'Sub BubbleSort
  1893. '    ' Antiquated but works fine.
  1894. '    Dim As Integer i, j
  1895. '    Dim As Double u, v
  1896. '    For j = SortedGroupsCount To 1 Step -1
  1897. '        For i = 2 To SortedGroupsCount
  1898. '            u = Group(SortedGroups(i - 1)).Distance2
  1899. '            v = Group(SortedGroups(i)).Distance2
  1900. '            If (u < v) Then
  1901. '                Swap SortedGroups(i - 1), SortedGroups(i)
  1902. '            End If
  1903. '        Next
  1904. '    Next
  1905. 'End Sub
  1906.  
  1907. ' Graphics
  1908.  
  1909. Sub PlotWorld
  1910.     Dim As Long g, k, p
  1911.     Dim j As Integer
  1912.     Dim lowlim, highlim As Long
  1913.     Dim x1 As Double
  1914.     Dim y1 As Double
  1915.     Dim x2 As Double
  1916.     Dim y2 As Double
  1917.     Dim clrtmp As _Unsigned Long
  1918.     Dim ThePlotMode As Integer
  1919.  
  1920.     NumClusterVisible = 0
  1921.     NumVectorVisible = 0
  1922.  
  1923.     SortedGroupsCount = 0
  1924.     k = 1
  1925.     Do
  1926.         If (Cluster(k).Visible = 1) Then
  1927.             NumClusterVisible = NumClusterVisible + 1
  1928.             g = Cluster(k).FirstGroup
  1929.             Do
  1930.                 If (Group(g).Visible = 1) Then
  1931.                     SortedGroupsCount = SortedGroupsCount + 1
  1932.                     SortedGroups(SortedGroupsCount) = g
  1933.                 End If
  1934.                 If (g = Cluster(k).LastGroup) Then Exit Do
  1935.                 g = Group(g).Pointer
  1936.             Loop
  1937.         End If
  1938.         k = Cluster(k).Pointer
  1939.         If (k = -999) Then Exit Do
  1940.     Loop
  1941.     NumGroupVisible = SortedGroupsCount
  1942.  
  1943.     Call QuickSort(1, SortedGroupsCount)
  1944.     'Call BubbleSort
  1945.  
  1946.     PlayerCamera.Shade = ShadeMix~&(PlayerCamera.Shade, _RGB32(_Red32(vec3Dcolor(Group(ClosestGroup).FirstVector)), _Green32(vec3Dcolor(Group(ClosestGroup).FirstVector)), _Blue32(vec3Dcolor(Group(ClosestGroup).FirstVector)), 200), .01)
  1947.     PlayerCamera.Shade = ShadeMix~&(PlayerCamera.Shade, _RGB32(0, 0, 0, 255), .01)
  1948.     Cls
  1949.     Line (0, 0)-(_Width, _Height), PlayerCamera.Shade, BF
  1950.  
  1951.     For j = 1 To SortedGroupsCount
  1952.         g = SortedGroups(j)
  1953.         ThePlotMode = Group(g).PlotMode
  1954.  
  1955.         If (ThePlotMode = -1) Then ' Wire cube
  1956.             Dim x3 As Double
  1957.             Dim y3 As Double
  1958.             Dim x4 As Double
  1959.             Dim y4 As Double
  1960.             p = Group(g).FirstVector
  1961.             clrtmp = vec2Dcolor(p)
  1962.             x1 = vec2D(p).u: y1 = vec2D(p).v: x2 = vec2D(p + 1).u: y2 = vec2D(p + 1).v: x3 = vec2D(p + 2).u: y3 = vec2D(p + 2).v: x4 = vec2D(p + 4).u: y4 = vec2D(p + 4).v
  1963.             Call CLine(x1, y1, x2, y2, clrtmp)
  1964.             Call CLine(x1, y1, x3, y3, clrtmp)
  1965.             Call CLine(x1, y1, x4, y4, clrtmp)
  1966.             x1 = vec2D(p + 3).u: y1 = vec2D(p + 3).v: x2 = vec2D(p + 1).u: y2 = vec2D(p + 1).v: x3 = vec2D(p + 2).u: y3 = vec2D(p + 2).v: x4 = vec2D(p + 7).u: y4 = vec2D(p + 7).v
  1967.             Call CLine(x1, y1, x2, y2, clrtmp)
  1968.             Call CLine(x1, y1, x3, y3, clrtmp)
  1969.             Call CLine(x1, y1, x4, y4, clrtmp)
  1970.             x1 = vec2D(p + 5).u: y1 = vec2D(p + 5).v: x2 = vec2D(p + 4).u: y2 = vec2D(p + 4).v: x3 = vec2D(p + 7).u: y3 = vec2D(p + 7).v: x4 = vec2D(p + 1).u: y4 = vec2D(p + 1).v
  1971.             Call CLine(x1, y1, x2, y2, clrtmp)
  1972.             Call CLine(x1, y1, x3, y3, clrtmp)
  1973.             Call CLine(x1, y1, x4, y4, clrtmp)
  1974.             x1 = vec2D(p + 6).u: y1 = vec2D(p + 6).v: x2 = vec2D(p + 4).u: y2 = vec2D(p + 4).v: x3 = vec2D(p + 7).u: y3 = vec2D(p + 7).v: x4 = vec2D(p + 2).u: y4 = vec2D(p + 2).v
  1975.             Call CLine(x1, y1, x2, y2, clrtmp)
  1976.             Call CLine(x1, y1, x3, y3, clrtmp)
  1977.             Call CLine(x1, y1, x4, y4, clrtmp)
  1978.         End If
  1979.  
  1980.         If Group(g).ActiveFrame = 0 Then
  1981.             lowlim = Group(g).FirstVector
  1982.             highlim = Group(g).LastVector - 1
  1983.         Else
  1984.             lowlim = Group(g).FirstVector + Group(g).FrameLength * (Group(g).ActiveFrame)
  1985.             highlim = Group(g).FirstVector + Group(g).FrameLength * (Group(g).ActiveFrame + 1) - 2
  1986.         End If
  1987.  
  1988.         For p = lowlim To highlim
  1989.             If (vec3Dvis(p) = 1) Then
  1990.                 NumVectorVisible = NumVectorVisible + 1
  1991.                 If (g = ClosestGroup) Then
  1992.                     clrtmp = Yellow
  1993.                 Else
  1994.                     clrtmp = vec2Dcolor(p)
  1995.                 End If
  1996.                 Select Case ThePlotMode
  1997.                     Case 0
  1998.                         x1 = vec2D(p).u
  1999.                         y1 = vec2D(p).v
  2000.                         Call BlockPoint(x1, y1, clrtmp)
  2001.                     Case 1
  2002.                         x1 = vec2D(p).u
  2003.                         y1 = vec2D(p).v
  2004.                         x2 = vec2D(p + 1).u
  2005.                         y2 = vec2D(p + 1).v
  2006.                         If (((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) < 225) Then
  2007.                             'Call cline(x1, y1, x2, y2, clrtmp)
  2008.                             Call LineSmooth(x1, y1, x2, y2, clrtmp)
  2009.                         Else
  2010.                             Call CCircle(x1, y1, 1, clrtmp)
  2011.                             '''
  2012.                             'If p = highlim Then Call CCircle(x2, y2, 1, clrtmp)
  2013.                             '''
  2014.                         End If
  2015.                     Case 2
  2016.                         x1 = vec2D(p).u
  2017.                         y1 = vec2D(p).v
  2018.                         Call CCircle(x1, y1, 1, clrtmp)
  2019.                 End Select
  2020.             End If
  2021.         Next
  2022.     Next
  2023.  
  2024.  
  2025. Sub DisplayHUD
  2026.     Dim a As String
  2027.     Call LineSmooth(0, 0, 25 * (xhat(1) * uhat(1) + xhat(2) * uhat(2) + xhat(3) * uhat(3)), 25 * (xhat(1) * vhat(1) + xhat(2) * vhat(2) + xhat(3) * vhat(3)), _RGB32(255, 0, 0, 150))
  2028.     Call LineSmooth(0, 0, 25 * (yhat(1) * uhat(1) + yhat(2) * uhat(2) + yhat(3) * uhat(3)), 25 * (yhat(1) * vhat(1) + yhat(2) * vhat(2) + yhat(3) * vhat(3)), _RGB32(0, 255, 0, 150))
  2029.     Call LineSmooth(0, 0, 25 * (zhat(1) * uhat(1) + zhat(2) * uhat(2) + zhat(3) * uhat(3)), 25 * (zhat(1) * vhat(1) + zhat(2) * vhat(2) + zhat(3) * vhat(3)), _RGB32(30, 144, 255, 150))
  2030.     Call TextCenter(" Closest ", (1) * 16, LimeGreen)
  2031.     a = " " + Group(ClosestGroup).Label + " "
  2032.     Color DarkKhaki
  2033.     _PrintString (_Width / 2 - (Len(a) / 2) * 8, 2 * 16), a
  2034.     Color LimeGreen
  2035.     _PrintString ((1) * 8, _Height - (4) * 16), "   Movement   "
  2036.     Color DarkKhaki
  2037.     _PrintString ((1) * 8, _Height - (3) * 16), "  W  &/or  " + Chr$(30) + "  "
  2038.     _PrintString ((1) * 8, _Height - (2) * 16), "A S D    " + Chr$(17) + " " + Chr$(31) + " " + Chr$(16)
  2039.     Color LimeGreen
  2040.     _PrintString (_Width - (13) * 8, _Height - (4) * 16), "Orientation "
  2041.     Color DarkKhaki
  2042.     _PrintString (_Width - (13) * 8, _Height - (3) * 16), " Keypad 1-9 "
  2043.     If ((nhat(3) <> 0) Or (uhat(3) <> 0)) Then Color Red Else Color Gray
  2044.     _PrintString (_Width - (13) * 8, _Height - (2) * 16), "  5=Level   "
  2045.     Color LimeGreen
  2046.     _PrintString ((1) * 8, (1) * 16), "- Report -"
  2047.     Color DarkKhaki
  2048.     _PrintString ((1) * 8, (2) * 16), "FPS: " + LTrim$(RTrim$(Str$(FPSReport))) + "/" + LTrim$(RTrim$(Str$(FPSTarget)))
  2049.     _PrintString ((1) * 8, (3) * 16), "Particles: " + LTrim$(RTrim$(Str$(NumVectorVisible)))
  2050.     '_PrintString ((1) * 8, (5) * 16), "Clusters: " + LTrim$(RTrim$(Str$(NumClusterVisible)))
  2051.     '_PrintString ((1) * 8, (4) * 16), "Groups: " + LTrim$(RTrim$(Str$(NumGroupVisible)))
  2052.     Color LimeGreen
  2053.     _PrintString ((1) * 8, (10) * 16), "Abilities"
  2054.     Color DarkKhaki
  2055.     _PrintString ((1) * 8, (11) * 16), "F = throw"
  2056.     _PrintString ((1) * 8, (12) * 16), "B = build"
  2057.     _PrintString ((1) * 8, (13) * 16), "N = scramble"
  2058.     _PrintString ((1) * 8, (14) * 16), "K = delete"
  2059.     _PrintString ((1) * 8, (15) * 16), "Z = zoom"
  2060.     Color LimeGreen
  2061.     Call TextCenter(" SPACE = Ascend ", _Height - (2) * 16, LimeGreen)
  2062.  
  2063. Sub TextCenter (TheText As String, TheHeight As Integer, TheShade As _Unsigned Long)
  2064.     Color TheShade
  2065.     _PrintString (_Width / 2 - (Len(TheText) / 2) * 8, TheHeight), TheText
  2066.  
  2067. Sub DisplayMiniMap
  2068.     Dim As Integer i, j, wi, wj
  2069.     Dim As Double dx, dy, u, v
  2070.     Dim As String a
  2071.     Dim As _Unsigned Long Shade
  2072.     wi = 1 + Int((PlayerCamera.Position.x) / BlockSize + UBound(WorldMesh, 1) / 2)
  2073.     wj = 1 + Int((PlayerCamera.Position.y) / BlockSize + UBound(WorldMesh, 2) / 2)
  2074.     u = _Width / 2 - UBound(WorldMesh, 1)
  2075.     v = _Height / 2 - UBound(WorldMesh, 2)
  2076.     For i = 1 To UBound(WorldMesh, 1)
  2077.         For j = 1 To UBound(WorldMesh, 2)
  2078.             Shade = TerrainHeightShade~&(WorldMesh(i, j))
  2079.             Call CPset(i + u, j + v, _RGB32(_Red32(Shade), _Green32(Shade), _Blue32(Shade), 150))
  2080.         Next
  2081.     Next
  2082.     Call CCircle(wi + u, wj + v, 2, Red)
  2083.     Call LineSmooth(wi + u, wj + v, wi + u - 5 * nhat(1) * Sqr((fovd / -192)), wj + v - 5 * nhat(2) * Sqr((fovd / -192)), White)
  2084.     Color DarkKhaki, PlayerCamera.Shade
  2085.     _PrintString (_Width - UBound(WorldMesh, 1), UBound(WorldMesh, 2)), "x:" + LTrim$(RTrim$(Str$(Int(PlayerCamera.Position.x)))) + " " + "y:" + LTrim$(RTrim$(Str$(Int(PlayerCamera.Position.y)))) + " " + "z:" + LTrim$(RTrim$(Str$(Int(PlayerCamera.Position.z))))
  2086.     dx = -nhat(1)
  2087.     dy = -nhat(2)
  2088.     If ((dx > 0) And (dy > 0)) Then a = LTrim$(RTrim$(Str$(1 + Int(((180 / pi) * (Atn(dy / dx))))))) + Chr$(248)
  2089.     If ((dx < 0) And (dy > 0)) Then a = LTrim$(RTrim$(Str$(1 + 180 + Int(((180 / pi) * (Atn(dy / dx))))))) + Chr$(248)
  2090.     If ((dx < 0) And (dy < 0)) Then a = LTrim$(RTrim$(Str$(1 + 180 + Int(((180 / pi) * (Atn(dy / dx))))))) + Chr$(248)
  2091.     If ((dx > 0) And (dy < 0)) Then a = LTrim$(RTrim$(Str$(1 + 360 + Int(((180 / pi) * (Atn(dy / dx))))))) + Chr$(248)
  2092.     _PrintString (_Width - Len(a) * 8, UBound(WorldMesh, 2) - 16), a
  2093.  
  2094. ' Interface
  2095.  
  2096. Sub KeyDownProcess
  2097.     Dim As Double modifier
  2098.     modifier = 0.05
  2099.  
  2100.     If (_KeyDown(32) <> 0) Then ' Space
  2101.         PlayerCamera.Velocity.z = 5
  2102.         PlayerCamera.Acceleration.z = -.5
  2103.     End If
  2104.     If ((_KeyDown(87) <> 0) Or (_KeyDown(119) <> 0) Or (_KeyDown(18432) <> 0)) Then ' W or w or upparrow
  2105.         Call StrafeCameraNhat(-1, -1, 0)
  2106.         If ((nhat(3) <> 0) Or (uhat(3) <> 0)) Then Call RegulateCamera
  2107.         If (ToggleAnimate = 1) Then
  2108.             PlayerCamera.Velocity.x = PlayerCamera.Velocity.x - modifier * nhat(1)
  2109.             PlayerCamera.Velocity.y = PlayerCamera.Velocity.y - modifier * nhat(2)
  2110.             'PlayerCamera.Velocity.z = PlayerCamera.Velocity.z - modifier * nhat(3)
  2111.         End If
  2112.     End If
  2113.     If ((_KeyDown(83) <> 0) Or (_KeyDown(115) <> 0) Or (_KeyDown(20480) <> 0)) Then ' S or s or downarrow
  2114.         Call StrafeCameraNhat(1, 1, 0)
  2115.         If ((nhat(3) <> 0) Or (uhat(3) <> 0)) Then Call RegulateCamera
  2116.         If (ToggleAnimate = 1) Then
  2117.             PlayerCamera.Velocity.x = PlayerCamera.Velocity.x + modifier * nhat(1)
  2118.             PlayerCamera.Velocity.y = PlayerCamera.Velocity.y + modifier * nhat(2)
  2119.             'PlayerCamera.Velocity.z = PlayerCamera.Velocity.z + modifier * nhat(3)
  2120.         End If
  2121.     End If
  2122.     If ((_KeyDown(65) <> 0) Or (_KeyDown(97) <> 0)) Then ' A or a
  2123.         If ((nhat(3) <> 0) Or (uhat(3) <> 0)) Then Call RegulateCamera
  2124.         Call StrafeCameraUhat(-1, -1, -1)
  2125.         If (ToggleAnimate = 1) Then
  2126.             PlayerCamera.Velocity.x = PlayerCamera.Velocity.x - modifier * uhat(1)
  2127.             PlayerCamera.Velocity.y = PlayerCamera.Velocity.y - modifier * uhat(2)
  2128.             'PlayerCamera.Velocity.z = PlayerCamera.Velocity.z - modifier * uhat(3)
  2129.         End If
  2130.     End If
  2131.     If ((_KeyDown(68) <> 0) Or (_KeyDown(100) <> 0)) Then ' D or d
  2132.         If ((nhat(3) <> 0) Or (uhat(3) <> 0)) Then Call RegulateCamera
  2133.         Call StrafeCameraUhat(1, 1, 1)
  2134.         If (ToggleAnimate = 1) Then
  2135.             PlayerCamera.Velocity.x = PlayerCamera.Velocity.x + modifier * uhat(1)
  2136.             PlayerCamera.Velocity.y = PlayerCamera.Velocity.y + modifier * uhat(2)
  2137.             'PlayerCamera.Velocity.z = PlayerCamera.Velocity.z + modifier * uhat(3)
  2138.         End If
  2139.     End If
  2140.     'If ((_KeyDown(81) <> 0) Or (_KeyDown(113) <> 0)) Then ' Q or q
  2141.     '    Call StrafeCameraVhat(1, 1, 1)
  2142.     '    If (ToggleAnimate = 1) Then
  2143.     '        PlayerCamera.Velocity.x = PlayerCamera.Velocity.x - modifier * vhat(1)
  2144.     '        PlayerCamera.Velocity.y = PlayerCamera.Velocity.y - modifier * vhat(2)
  2145.     '        PlayerCamera.Velocity.z = PlayerCamera.Velocity.z - modifier * vhat(3)
  2146.     '    End If
  2147.     'End If
  2148.     'If ((_KeyDown(69) <> 0) Or (_KeyDown(101) <> 0)) Then ' E or e
  2149.     '    Call StrafeCameraVhat(-1, -1, -1)
  2150.     '    If (ToggleAnimate = 1) Then
  2151.     '        PlayerCamera.Velocity.x = PlayerCamera.Velocity.x + modifier * vhat(1)
  2152.     '        PlayerCamera.Velocity.y = PlayerCamera.Velocity.y + modifier * vhat(2)
  2153.     '        PlayerCamera.Velocity.z = PlayerCamera.Velocity.z + modifier * vhat(3)
  2154.     '    End If
  2155.     'End If
  2156.     If ((_KeyDown(90) <> 0) Or (_KeyDown(122) <> 0)) Then ' Z or z.
  2157.         fovd = fovd - 5
  2158.         If (fovd < -600) Then
  2159.             fovd = -600
  2160.         Else
  2161.             farplane(4) = farplane(4) - 5
  2162.         End If
  2163.         Call CalculateClippingPlanes(.5 * _Width, .5 * _Height)
  2164.     End If
  2165.  
  2166.     modifier = 0.0333
  2167.     If (_KeyDown(19200) <> 0) Or (_KeyDown(52) <> 0) Then Call RotateUhat(-modifier, -modifier, -modifier): Call CalculateScreenVectors ' 4
  2168.     If (_KeyDown(19712) <> 0) Or (_KeyDown(54) <> 0) Then Call RotateUhat(modifier, modifier, modifier): Call CalculateScreenVectors ' 6
  2169.     If (_KeyDown(56) <> 0) Then Call RotateVhat(modifier, modifier, modifier): Call CalculateScreenVectors ' 8
  2170.     If (_KeyDown(50) <> 0) Then Call RotateVhat(-modifier, -modifier, -modifier): Call CalculateScreenVectors ' 2
  2171.     If (_KeyDown(55) <> 0) Then Call RotateUV(-modifier, -modifier, -modifier) ' 7
  2172.     If (_KeyDown(57) <> 0) Then Call RotateUV(modifier, modifier, modifier) ' 9
  2173.     If (_KeyDown(49) <> 0) Then Call RotateUhat(-modifier, -modifier, -modifier): Call CalculateScreenVectors: Call RotateUV(-modifier, -modifier, -modifier) ' 1
  2174.     If (_KeyDown(51) <> 0) Then Call RotateUhat(modifier, modifier, modifier): Call CalculateScreenVectors: Call RotateUV(modifier, modifier, modifier) ' 3
  2175.  
  2176.     'modifier = 0.0222
  2177.     'Do While _MouseInput
  2178.     '    If (_MouseMovementX > 0) Then Call RotateUhat(modifier, modifier, modifier): Call CalculateScreenVectors
  2179.     '    If (_MouseMovementX < 0) Then Call RotateUhat(-modifier, -modifier, -modifier): Call CalculateScreenVectors
  2180.     '    If (_MouseMovementY > 0) Then Call RotateVhat(modifier, modifier, modifier): Call CalculateScreenVectors
  2181.     '    If (_MouseMovementY < 0) Then Call RotateVhat(-modifier, -modifier, -modifier): Call CalculateScreenVectors
  2182.     'Loop
  2183.  
  2184. Sub KeyHitProcess
  2185.     Dim As Long g, p
  2186.     Dim As Double x0, y0, z0
  2187.     Dim As Integer kh
  2188.     kh = _KeyHit
  2189.     If (kh <> 0) Then
  2190.         Select Case kh
  2191.             Case 27 ' Quit
  2192.                 System
  2193.  
  2194.             Case 53 ' 5
  2195.                 Call RegulateCamera
  2196.  
  2197.             Case Asc("b"), Asc("B")
  2198.                 x0 = (PlayerCamera.Position.x - 40 * nhat(1))
  2199.                 y0 = (PlayerCamera.Position.y - 40 * nhat(2))
  2200.                 z0 = (PlayerCamera.Position.z - 40 * nhat(3))
  2201.                 x0 = x0 - x0 Mod BlockSize / 3
  2202.                 y0 = y0 - y0 Mod BlockSize / 3
  2203.                 z0 = z0 - z0 Mod BlockSize / 3
  2204.                 g = LatestGroupIdentity&(1)
  2205.                 g = NewCube&(g, "Custom block", 100, x0, y0, z0, BlockSize / 3, BlockSize / 3, BlockSize / 3, Lime, Purple, Teal, -2, 0)
  2206.                 g = NewWireCube&(g, "Custom block", x0, y0, z0, BlockSize / 3, BlockSize / 3, BlockSize / 3, Lime, -2)
  2207.                 Cluster(ClusterIdTicker).Acceleration.x = 0
  2208.                 Cluster(ClusterIdTicker).Acceleration.y = 0
  2209.                 Cluster(ClusterIdTicker).Acceleration.z = -.15
  2210.                 Call ClusterPinch(g)
  2211.  
  2212.             Case Asc("f"), Asc("F")
  2213.                 x0 = (PlayerCamera.Position.x - 40 * nhat(1))
  2214.                 y0 = (PlayerCamera.Position.y - 40 * nhat(2))
  2215.                 z0 = (PlayerCamera.Position.z - 40 * nhat(3))
  2216.                 g = LatestGroupIdentity&(1)
  2217.                 g = NewCube&(g, "Potion", 150, x0, y0, z0, 10, 10, 10, Red, Purple, Teal, -1, 0)
  2218.                 g = NewCube&(g, "Potion", 50, x0, y0, z0 + 10, 2, 2, 10, Blue, Purple, Teal, -1, 0)
  2219.                 Cluster(ClusterIdTicker).Acceleration.x = 0
  2220.                 Cluster(ClusterIdTicker).Acceleration.y = 0
  2221.                 Cluster(ClusterIdTicker).Acceleration.z = -.15
  2222.                 Cluster(ClusterIdTicker).Velocity.x = -5 * nhat(1)
  2223.                 Cluster(ClusterIdTicker).Velocity.y = -5 * nhat(2)
  2224.                 Cluster(ClusterIdTicker).Velocity.z = -5 * nhat(3)
  2225.                 Call ClusterPinch(g)
  2226.  
  2227.             Case Asc("n"), Asc("N")
  2228.                 For p = Group(ClosestGroup).FirstVector To Group(ClosestGroup).LastVector
  2229.                     vec3Dvel(p).x = (Rnd - .5) * .20
  2230.                     vec3Dvel(p).y = (Rnd - .5) * .20
  2231.                     vec3Dvel(p).z = (Rnd - .5) * .20
  2232.                 Next
  2233.  
  2234.             Case Asc("k"), Asc("K")
  2235.                 Call RemoveGroup(ClosestGroup)
  2236.  
  2237.             Case Asc("t"), Asc("T")
  2238.                 ToggleAnimate = -ToggleAnimate
  2239.         End Select
  2240.     End If
  2241.     _KeyClear
  2242.  
  2243. ' Plotting and color tools.
  2244.  
  2245. Sub CLine (x0 As Double, y0 As Double, x1 As Double, y1 As Double, shade As _Unsigned Long)
  2246.     Line (_Width / 2 + x0, -y0 + _Height / 2)-(_Width / 2 + x1, -y1 + _Height / 2), shade
  2247.  
  2248. Sub CPset (x0, y0, shade As _Unsigned Long)
  2249.     PSet (_Width / 2 + x0, -y0 + _Height / 2), shade
  2250.  
  2251. Sub CCircle (x0 As Double, y0 As Double, rad As Double, shade As _Unsigned Long)
  2252.     Circle (_Width / 2 + x0, -y0 + _Height / 2), rad, shade
  2253.  
  2254. Sub BlockPoint (x0 As Double, y0 As Double, shade As _Unsigned Long)
  2255.     Line (_Width / 2 + x0 - 3, -y0 + _Height / 2 - 3)-(_Width / 2 + x0 + 3, -y0 + _Height / 2 + 3), _RGB32(_Red32(shade), _Green32(shade), _Blue32(shade), 200), BF
  2256.  
  2257. Function ShadeMix~& (shade0 As _Unsigned Long, shade1 As _Unsigned Long, weight As Double)
  2258.     ShadeMix~& = _RGB32((1 - weight) * _Red32(shade0) + weight * _Red32(shade1), (1 - weight) * _Green32(shade0) + weight * _Green32(shade1), (1 - weight) * _Blue32(shade0) + weight * _Blue32(shade1))
  2259.  
  2260. Sub LineSmooth (x0, y0, x1, y1, c As _Unsigned Long)
  2261.     ' source: https://en.wikipedia.org/w/index.php?title=Xiaolin_Wu%27s_line_algorithm&oldid=852445548
  2262.     ' translated: FellippeHeitor @ qb64.org
  2263.     ' updated slightly for this project
  2264.  
  2265.     Dim plX As Integer, plY As Integer, plI
  2266.  
  2267.     Dim steep As _Byte
  2268.     steep = Abs(y1 - y0) > Abs(x1 - x0)
  2269.  
  2270.     If steep Then
  2271.         Swap x0, y0
  2272.         Swap x1, y1
  2273.     End If
  2274.  
  2275.     If x0 > x1 Then
  2276.         Swap x0, x1
  2277.         Swap y0, y1
  2278.     End If
  2279.  
  2280.     Dim dx, dy, gradient
  2281.     dx = x1 - x0
  2282.     dy = y1 - y0
  2283.     gradient = dy / dx
  2284.  
  2285.     If dx = 0 Then
  2286.         gradient = 1
  2287.     End If
  2288.  
  2289.     'handle first endpoint
  2290.     Dim xend, yend, xgap, xpxl1, ypxl1
  2291.     xend = _Round(x0)
  2292.     yend = y0 + gradient * (xend - x0)
  2293.     xgap = (1 - ((x0 + .5) - Int(x0 + .5)))
  2294.     xpxl1 = xend 'this will be used in the main loop
  2295.     ypxl1 = Int(yend)
  2296.     If steep Then
  2297.         plX = ypxl1
  2298.         plY = xpxl1
  2299.         plI = (1 - (yend - Int(yend))) * xgap
  2300.         GoSub plot
  2301.  
  2302.         plX = ypxl1 + 1
  2303.         plY = xpxl1
  2304.         plI = (yend - Int(yend)) * xgap
  2305.         GoSub plot
  2306.     Else
  2307.         plX = xpxl1
  2308.         plY = ypxl1
  2309.         plI = (1 - (yend - Int(yend))) * xgap
  2310.         GoSub plot
  2311.  
  2312.         plX = xpxl1
  2313.         plY = ypxl1 + 1
  2314.         plI = (yend - Int(yend)) * xgap
  2315.         GoSub plot
  2316.     End If
  2317.  
  2318.     Dim intery
  2319.     intery = yend + gradient 'first y-intersection for the main loop
  2320.  
  2321.     'handle second endpoint
  2322.     Dim xpxl2, ypxl2
  2323.     xend = _Round(x1)
  2324.     yend = y1 + gradient * (xend - x1)
  2325.     xgap = ((x1 + .5) - Int(x1 + .5))
  2326.     xpxl2 = xend 'this will be used in the main loop
  2327.     ypxl2 = Int(yend)
  2328.     If steep Then
  2329.         plX = ypxl2
  2330.         plY = xpxl2
  2331.         plI = (1 - (yend - Int(yend))) * xgap
  2332.         GoSub plot
  2333.  
  2334.         plX = ypxl2 + 1
  2335.         plY = xpxl2
  2336.         plI = (yend - Int(yend)) * xgap
  2337.         GoSub plot
  2338.     Else
  2339.         plX = xpxl2
  2340.         plY = ypxl2
  2341.         plI = (1 - (yend - Int(yend))) * xgap
  2342.         GoSub plot
  2343.  
  2344.         plX = xpxl2
  2345.         plY = ypxl2 + 1
  2346.         plI = (yend - Int(yend)) * xgap
  2347.         GoSub plot
  2348.     End If
  2349.  
  2350.     'main loop
  2351.     Dim x
  2352.     If steep Then
  2353.         For x = xpxl1 + 1 To xpxl2 - 1
  2354.             plX = Int(intery)
  2355.             plY = x
  2356.             plI = (1 - (intery - Int(intery)))
  2357.             GoSub plot
  2358.  
  2359.             plX = Int(intery) + 1
  2360.             plY = x
  2361.             plI = (intery - Int(intery))
  2362.             GoSub plot
  2363.  
  2364.             intery = intery + gradient
  2365.         Next
  2366.     Else
  2367.         For x = xpxl1 + 1 To xpxl2 - 1
  2368.             plX = x
  2369.             plY = Int(intery)
  2370.             plI = (1 - (intery - Int(intery)))
  2371.             GoSub plot
  2372.  
  2373.             plX = x
  2374.             plY = Int(intery) + 1
  2375.             plI = (intery - Int(intery))
  2376.             GoSub plot
  2377.  
  2378.             intery = intery + gradient
  2379.         Next
  2380.     End If
  2381.  
  2382.     Exit Sub
  2383.  
  2384.     plot:
  2385.     ' Change to regular PSET for standard coordinate orientation.
  2386.     Call CPset(plX, plY, _RGB32(_Red32(c), _Green32(c), _Blue32(c), plI * _Alpha32(c)))
  2387.     Return
  2388.  
  2389. ' Camera transformation
  2390.  
  2391. Sub RotateUhat (dx As Double, dy As Double, dz As Double)
  2392.     uhat(1) = uhat(1) + nhat(1) * dx
  2393.     uhat(2) = uhat(2) + nhat(2) * dy
  2394.     uhat(3) = uhat(3) + nhat(3) * dz
  2395.  
  2396. Sub RotateVhat (dx As Double, dy As Double, dz As Double)
  2397.     vhat(1) = vhat(1) + nhat(1) * dx
  2398.     vhat(2) = vhat(2) + nhat(2) * dy
  2399.     vhat(3) = vhat(3) + nhat(3) * dz
  2400.  
  2401. Sub RotateUV (dx As Double, dy As Double, dz As Double)
  2402.     Dim As Double v1, v2, v3
  2403.     v1 = vhat(1)
  2404.     v2 = vhat(2)
  2405.     v3 = vhat(3)
  2406.     vhat(1) = v1 + uhat(1) * dx
  2407.     vhat(2) = v2 + uhat(2) * dy
  2408.     vhat(3) = v3 + uhat(3) * dz
  2409.     uhat(1) = uhat(1) - v1 * dx
  2410.     uhat(2) = uhat(2) - v2 * dy
  2411.     uhat(3) = uhat(3) - v3 * dz
  2412.  
  2413. Sub StrafeCameraUhat (dx As Double, dy As Double, dz As Double)
  2414.     PlayerCamera.Position.x = PlayerCamera.Position.x + uhat(1) * dx
  2415.     PlayerCamera.Position.y = PlayerCamera.Position.y + uhat(2) * dy
  2416.     PlayerCamera.Position.z = PlayerCamera.Position.z + uhat(3) * dz
  2417.  
  2418. Sub StrafeCameraVhat (dx As Double, dy As Double, dz As Double)
  2419.     PlayerCamera.Position.x = PlayerCamera.Position.x + vhat(1) * dx
  2420.     PlayerCamera.Position.y = PlayerCamera.Position.y + vhat(2) * dy
  2421.     PlayerCamera.Position.z = PlayerCamera.Position.z + vhat(3) * dz
  2422.  
  2423. Sub StrafeCameraNhat (dx As Double, dy As Double, dz As Double)
  2424.     PlayerCamera.Position.x = PlayerCamera.Position.x + nhat(1) * dx
  2425.     PlayerCamera.Position.y = PlayerCamera.Position.y + nhat(2) * dy
  2426.     PlayerCamera.Position.z = PlayerCamera.Position.z + nhat(3) * dz
  2427.  
  2428. '''
  2429.  

EDIT: Attached screenshot of looking straight up, about to capture an eclipse. 
eclipse.png

13
QB64 Discussion / [fixed] possible editor bug
« on: November 06, 2021, 09:37:38 am »
its not 2022 yet but i figured yall wanna know what i found whilst running windows 10, all-new qb64-everything as of last week. this problem arose maybe 3x recently, managed to capture it this time:

 
 

when i type (RND - .5) * whatever, the editor removes the .5 and throws the parentheses off.

14
Programs / A do-nothing zen garden
« on: March 19, 2021, 11:54:01 am »
Click the mouse to create heat, life, and waves. Right click to destroy.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 800, 32)
  2.  
  3. DIM SHARED GridWidth
  4. DIM SHARED GridHeight
  5. DIM SHARED CellWidth
  6. DIM SHARED CellHeight
  7. GridWidth = _WIDTH / 8
  8. GridHeight = _HEIGHT / 8
  9. CellWidth = _WIDTH / GridWidth
  10. CellHeight = _HEIGHT / GridHeight
  11.  
  12. TYPE Vector
  13.     x AS DOUBLE
  14.     y AS DOUBLE
  15.     z AS DOUBLE
  16.  
  17. DIM SHARED MainGrid(GridWidth, GridHeight) AS Vector
  18. DIM SHARED AuxiGrid(GridWidth, GridHeight) AS Vector
  19. DIM SHARED GridVel(GridWidth, GridHeight) AS DOUBLE
  20.  
  21. DIM SelectedCelli
  22. DIM SelectedCellj
  23.  
  24.         SelectedCelli = INT(_MOUSEX / CellWidth)
  25.         SelectedCellj = INT(_MOUSEY / CellHeight)
  26.         IF _MOUSEBUTTON(1) THEN
  27.             MainGrid(SelectedCelli, SelectedCellj).x = 8
  28.             MainGrid(SelectedCelli, SelectedCellj).y = 1
  29.             MainGrid(SelectedCelli, SelectedCellj).z = 6
  30.             GridVel(SelectedCelli, SelectedCellj) = 0
  31.         END IF
  32.         IF _MOUSEBUTTON(2) THEN
  33.             MainGrid(SelectedCelli, SelectedCellj).x = 0
  34.             MainGrid(SelectedCelli, SelectedCellj).y = 0
  35.             MainGrid(SelectedCelli, SelectedCellj).z = 0
  36.             GridVel(SelectedCelli, SelectedCellj) = 0
  37.         END IF
  38.     LOOP
  39.  
  40.     CALL UpdateGrid
  41.     CLS
  42.     CALL PlotGrid
  43.     _DISPLAY
  44.     _LIMIT 30
  45.  
  46.  
  47. SUB UpdateGrid
  48.     DIM i AS INTEGER
  49.     DIM j AS INTEGER
  50.     DIM t AS DOUBLE
  51.     DIM AS Vector a1, a2, a3, a4, a5, a6, a7, a8, a9
  52.     FOR i = 1 TO GridWidth
  53.         FOR j = 1 TO GridHeight
  54.             AuxiGrid(i, j).x = MainGrid(i, j).x
  55.             AuxiGrid(i, j).y = MainGrid(i, j).y
  56.             AuxiGrid(i, j).z = MainGrid(i, j).z
  57.         NEXT
  58.     NEXT
  59.     FOR i = 1 TO GridWidth - 2
  60.         FOR j = 1 TO GridHeight - 2
  61.             a1 = AuxiGrid(i - 1, j + 1)
  62.             a2 = AuxiGrid(i, j + 1)
  63.             a3 = AuxiGrid(i + 1, j + 1)
  64.             a4 = AuxiGrid(i - 1, j)
  65.             a5 = AuxiGrid(i, j)
  66.             a6 = AuxiGrid(i + 1, j)
  67.             a7 = AuxiGrid(i - 1, j - 1)
  68.             a8 = AuxiGrid(i, j - 1)
  69.             a9 = AuxiGrid(i + 1, j - 1)
  70.  
  71.  
  72.             ' Diffusion
  73.             MainGrid(i, j).x = (1 / 5) * (a2.x + a4.x + a6.x + a8.x + a5.x)
  74.  
  75.             ' Game of life
  76.             t = a1.y + a2.y + a3.y + a4.y + a6.y + a7.y + a8.y + a9.y
  77.             IF (a5.y = 1) THEN
  78.                 SELECT CASE t
  79.                     CASE IS < 2
  80.                         MainGrid(i, j).y = 0
  81.                     CASE 2
  82.                         MainGrid(i, j).y = 1
  83.                     CASE 3
  84.                         MainGrid(i, j).y = 1
  85.                     CASE IS > 3
  86.                         MainGrid(i, j).y = 0
  87.                 END SELECT
  88.             ELSE
  89.                 IF (t = 3) THEN
  90.                     MainGrid(i, j).y = 1
  91.                 END IF
  92.             END IF
  93.  
  94.             ' Wave propagation
  95.             DIM alpha
  96.             DIM wp1, wp2
  97.             alpha = .25
  98.             wp1 = alpha * (a6.z + a4.z) + 2 * (1 - alpha) * a5.z - GridVel(i, j)
  99.             wp2 = alpha * (a2.z + a8.z) + 2 * (1 - alpha) * a5.z - GridVel(i, j)
  100.             MainGrid(i, j).z = (0.98) * (1 / 2) * (wp1 + wp2)
  101.             GridVel(i, j) = AuxiGrid(i, j).z
  102.         NEXT
  103.     NEXT
  104.  
  105. SUB PlotGrid
  106.     DIM i AS INTEGER
  107.     DIM j AS INTEGER
  108.     FOR i = 0 TO GridWidth
  109.         FOR j = 0 TO GridHeight
  110.             LINE (i * CellWidth, j * CellHeight)-(i * CellWidth + CellWidth, j * CellHeight + CellHeight), _RGB32(255 * MainGrid(i, j).x, 25 + 230 * MainGrid(i, j).y, 255 * ABS(MainGrid(i, j).z)), BF
  111.             LINE (i * CellWidth, j * CellHeight)-(i * CellWidth + CellWidth, j * CellHeight + CellHeight), _RGB32(100, 100, 100), B
  112.         NEXT
  113.     NEXT

15
QB64 Discussion / Alright, this is weird on my machine...
« on: February 10, 2021, 02:50:59 pm »
I get two different answers at the bottom of this code. Someone else tells me they get the same answer twice. Can I get some community testing? Or someone otherwise set me straight please.

Code: QB64: [Select]
  1. z = 9223372036854775807 ' This is the biggest allowed number of this type.
  2. '                         (Only here for reference.)
  3.  
  4. a = 2 ^ 55 - 1 '          This number should be odd.
  5. b = 36028797018963967 '   The number above should equal this one.
  6.  

Pages: [1] 2 3 ... 5