home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmos2002.zip / DEMO / SRC / beeswarm.mod < prev    next >
Text File  |  1997-06-10  |  8KB  |  246 lines

  1. MODULE BeeSwarm;
  2.  
  3.         (********************************************************)
  4.         (*                                                      *)
  5.         (*              Graphics demo, just for fun             *)
  6.         (*                                                      *)
  7.         (*  Programmer:         P. Moylan                       *)
  8.         (*  Last edited:        10 June 1997                    *)
  9.         (*  Status:             Working                         *)
  10.         (*                                                      *)
  11.         (*      Adapted from a Pascal program given to me       *)
  12.         (*      by Frank Compagner.                             *)
  13.         (*                                                      *)
  14.         (********************************************************)
  15.  
  16. FROM Graphics IMPORT
  17.     (* type *)  ColourType,
  18.     (* proc *)  GetScreenShape, SetMode, PlotDot;
  19.  
  20. FROM IO IMPORT
  21.     (* proc *)  KeyPressed;
  22.  
  23. FROM Random IMPORT
  24.     (* proc *)  RANDOM;
  25.  
  26. FROM MATHLIB IMPORT
  27.     (* proc *)  Sqrt;
  28.  
  29. FROM Timer IMPORT
  30.     (* proc *)  Sleep;
  31.  
  32. (************************************************************************)
  33.  
  34. CONST
  35.     (* Video mode.  Chose any graphics mode. *)
  36.  
  37.     VideoMode = 16;
  38.  
  39.     (* Size of the swarm. *)
  40.  
  41.     MaxBeeNumber = 50;
  42.  
  43.     (* SpeedScale controls how fast the swarm moves, and the scaling    *)
  44.     (* factor LeaderAdvantage defines how much faster the leader moves. *)
  45.     (* Attraction controls how tightly the swarm tends to cluster.      *)
  46.  
  47.     SpeedScale = 0.01;
  48.     LeaderAdvantage = 2.0;
  49.     Attraction = 8.0;
  50.  
  51.     (* Width of the border region on the screen outside which the       *)
  52.     (* leader will not go.                                              *)
  53.  
  54.     Border = 20;
  55.  
  56. TYPE
  57.     BeeNumber = [0..MaxBeeNumber];
  58.     BeeState = RECORD
  59.                    x, y: REAL;
  60.                    sx, sy: REAL;
  61.                END (*RECORD*);
  62.  
  63. VAR
  64.     (* Present and past state of all the bees. *)
  65.  
  66.     OldBee, Bee: ARRAY BeeNumber OF BeeState;
  67.  
  68.     (* Screen size and max colour.  CharHeight is not used, but is      *)
  69.     (* obtained as a side-effect of getting the other parameters.       *)
  70.  
  71.     Xmax, Ymax, CharHeight: CARDINAL;
  72.     MaxColour: ColourType;
  73.  
  74.     (* Maximum speed of all bees except the leader.  (We allow the      *)
  75.     (* leader to go faster.)  This is a variable because it depends     *)
  76.     (* on screen resolution.                                            *)
  77.  
  78.     SpeedLimit: REAL;
  79.  
  80.     SwarmColour: ColourType;
  81.  
  82. (************************************************************************)
  83.  
  84. PROCEDURE Initialise;
  85.  
  86.     (* Fills the Bee array with some suitable random numbers. *)
  87.  
  88.     VAR i: BeeNumber;
  89.  
  90.     BEGIN
  91.         FOR i := 0 TO MAX(BeeNumber) DO
  92.             WITH Bee[i] DO
  93.                 x := FLOAT(Xmax-2*Border)*RANDOM() + FLOAT(Border);
  94.                 y := FLOAT(Ymax-2*Border)*RANDOM() + FLOAT(Border);
  95.                 sx := 2.0*RANDOM() - 1.0;
  96.                 sy := 2.0*RANDOM() - 1.0;
  97.             END (*WITH*);
  98.         END (*FOR*);
  99.     END Initialise;
  100.  
  101. (************************************************************************)
  102.  
  103. PROCEDURE Sat (VAR (*INOUT*) x, y: REAL;  limit: REAL);
  104.  
  105.     (* Limits the magnitude of the (x,y) vector. *)
  106.  
  107.     VAR d2, scale: REAL;
  108.  
  109.     BEGIN
  110.         d2 := x*x + y*y;
  111.         IF d2 > limit*limit THEN
  112.             scale := limit/VAL(REAL,Sqrt(VAL(LONGREAL,d2)));
  113.             x := scale*x;  y := scale*y;
  114.         END (*IF*);
  115.     END Sat;
  116.  
  117. (************************************************************************)
  118.  
  119. PROCEDURE Move;
  120.  
  121.     CONST CriticalRS = 5.0;     (* both of these parameters affect how  *)
  122.           K1 = 0.4;             (* tightly the swarm will cluster       *)
  123.  
  124.     VAR i: BeeNumber;  dx, dy, rsquared, scale: REAL;
  125.  
  126.     BEGIN
  127.         (* Remember the location of dots to be cleared. *)
  128.  
  129.         OldBee := Bee;
  130.  
  131.         (* Update the velocity and position of the leader. *)
  132.  
  133.         WITH Bee[0] DO
  134.             sx := sx + RANDOM() - 0.5;
  135.             sy := sy + RANDOM() - 0.5;
  136.             Sat (sx, sy, LeaderAdvantage*SpeedLimit);
  137.             x := x + sx;  y := y + sy;
  138.             IF (TRUNC(x) < Border) OR (TRUNC(x) > Xmax-Border) THEN
  139.                 sx := -sx;  x := x + 2.0*sx;
  140.             END (*IF*);
  141.             IF (TRUNC(y) < Border) OR (TRUNC(y) > Ymax-Border) THEN
  142.                 sy := -sy;  y := y + 2.0*sy;
  143.             END (*IF*);
  144.         END (*  WITH Bee[0] *);
  145.  
  146.         (* Update the velocity and position of the followers.  The      *)
  147.         (* crucial observation is that the velocity of a bee depends on *)
  148.         (* its distance from the leader (plus a random adjustment).     *)
  149.  
  150.         FOR i := 1 TO MAX(BeeNumber) DO
  151.             WITH Bee[i] DO
  152.  
  153.                 (* Now trying a slightly different law, where each bee  *)
  154.                 (* tries to follow the one in front as well as the      *)
  155.                 (* leader.                                              *)
  156.  
  157.                 dx := K1*(Bee[0].x - x) + (1.0-K1)*(Bee[i-1].x - x);
  158.                 dy := K1*(Bee[0].y - y) + (1.0-K1)*(Bee[i-1].y - y);
  159.                 rsquared := dx*dx + dy*dy;
  160.                 IF rsquared > CriticalRS THEN
  161.                     scale := Attraction*SpeedLimit/rsquared;
  162.                 ELSE
  163.                     scale := Attraction*SpeedLimit
  164.                                 *rsquared/(CriticalRS*CriticalRS);
  165.                 END (*IF*);
  166.                 sx := sx + scale*dx + 2.0*(RANDOM() - 0.5);
  167.                 sy := sy + scale*dy + 2.0*(RANDOM() - 0.5);
  168.                 Sat (sx, sy, SpeedLimit);
  169.                 x := x + sx;  y := y + sy;
  170.                 IF (x < 0.0) OR (TRUNC(x) > Xmax) THEN
  171.                     sx := -sx;  x := x + 2.0*sx;
  172.                 END (*IF*);
  173.                 IF (y < 0.0) OR (TRUNC(y) > Ymax) THEN
  174.                     sy := -sy;  y := y + 2.0*sy;
  175.                 END (*IF*);
  176.             END (* WITH Bee[i] *);
  177.         END (*FOR*);
  178.     END Move;
  179.  
  180. (************************************************************************)
  181.  
  182. PROCEDURE Display;
  183.  
  184.     CONST SwarmColour = 10;  LeaderColour = 12;
  185.  
  186.     VAR b: BeeNumber;
  187.  
  188.     BEGIN
  189.         (* A pause, so that we don't update too fast. *)
  190.  
  191.         (*Sleep (20);*)
  192.  
  193.         (* Clear out the old positions displayed. *)
  194.  
  195. (*
  196.         FOR b := 0 TO MAX(BeeNumber) DO
  197.             WITH OldBee[b] DO
  198.                 PlotDot (TRUNC(x), TRUNC(y), 0);
  199.             END (*WITH*);
  200.         END (*FOR*);
  201. *)
  202.         WITH OldBee[0] DO
  203.             PlotDot (TRUNC(x), TRUNC(y), 0);
  204.         END (*WITH*);
  205.  
  206.         (* Plot the followers. *)
  207.  
  208.         FOR b := 1 TO MAX(BeeNumber) DO
  209.             WITH OldBee[b] DO
  210.                 PlotDot (TRUNC(x), TRUNC(y), 0);
  211.             END (*WITH*);
  212.             WITH Bee[b] DO
  213.                 PlotDot (TRUNC(x), TRUNC(y), SwarmColour);
  214.             END (*WITH*);
  215.         END (*FOR*);
  216.  
  217.         (* Plot the leader. *)
  218.  
  219.         WITH Bee[0] DO
  220.             PlotDot (TRUNC(x), TRUNC(y), LeaderColour);
  221.         END (*WITH*);
  222.         (*
  223.         IF SwarmColour < MaxColour THEN
  224.             INC (SwarmColour);
  225.         ELSE
  226.             SwarmColour := 1;
  227.         END (*IF*);
  228.         *)
  229.     END Display;
  230.  
  231. (************************************************************************)
  232. (*                              MAIN PROGRAM                            *)
  233. (************************************************************************)
  234.  
  235. BEGIN
  236.     SetMode (VideoMode, TRUE);
  237.     GetScreenShape (Xmax, Ymax, MaxColour, CharHeight);
  238.     SwarmColour := 1;
  239.     SpeedLimit := SpeedScale*FLOAT(Xmax);
  240.     Initialise;
  241.     REPEAT
  242.         Move;  Display;
  243.     UNTIL KeyPressed();
  244. END BeeSwarm.
  245.  
  246.