with Ada.Characters.Latin_1, Ada.Strings.Fixed, Ada.Text_IO; package body ANSI_Terminal is package Latin renames Ada.Characters.Latin_1; package IO renames Ada.Text_IO; function Clear_Screen return String is begin -- ANSI control sequence Erase in Display -- Variant to clear entire screen return Latin.ESC & "[2J"; end Clear_Screen; function Reset_Cursor return String is begin -- ANSI control sequence Cursor Position -- Parameters to move cursor to top left corner return Latin.ESC & "[1;1H"; end Reset_Cursor; procedure Clear_Screen is begin IO.Put (Clear_Screen); end Clear_Screen; procedure Reset_Cursor is begin IO.Put (Reset_Cursor); end Reset_Cursor; function BG_Color_Code (Value : in Natural) return String is use Ada.Strings; use Ada.Strings.Fixed; begin -- ANSI sequence to change text background colour -- Total length is always 11 characters -- It doesn't have to be, but the consistency is important for rendering return Latin.ESC & "[48;5;" & Tail (Trim (Integer'Image (Value), Left), 3, '0') & "m"; end BG_Color_Code; function Lookup (Input : in March_Cell_Grid; X, Y : in Integer) return String is Average_Density : Natural := Integer (Quantity'Ceiling (Input (X, Y).Density / 4.0)); Bit_Index : Positive := Integer (Input (X, Y).Index) + 1; Choice : Natural; begin case Average_Density is when 1 .. 2 => Choice := 19; -- dark blue when 3 .. 4 => Choice := 20; -- slightly less dark blue when 5 .. 6 => Choice := 21; -- slightly dark blue when 7 .. 8 => Choice := 12; -- blue when 9 .. 10 => Choice := 14; -- cyan when 11 .. 12 => Choice := 10; -- green when 13 .. 14 => Choice := 11; -- yellow when 15 .. 16 => Choice := 3; -- dark yellow when 17 .. 18 => Choice := 9; -- red when 19 .. 20 => Choice := 1; -- dark red when others => Choice := 0; -- black end case; -- Total length should always be 12 characters return BG_Color_Code (Choice) & Liquid_Chars (Bit_Index); end Lookup; function Marching_Squares (Input : in Particle_Vector) return String is -- Having the grid be one bigger around the edges simplifies calculations Grid : March_Cell_Grid (0 .. 81, 0 .. 26); -- 80 cols * 25 rows * 12 chars/cell + 24 linefeeds + 4 char color reset = 24028 -- Oh yeah, baby, big strings Output : String (1 .. 24028); X, Y, S : Integer; begin for P of Input loop X := Integer (Plane.Re (P.Place) - 0.5); Y := Integer (Plane.Im (P.Place) / 2.0 - 0.5); if X >= 0 and X <= 80 and Y >= 0 and Y <= 25 then for J in Integer range 0 .. 1 loop for I in Integer range 0 .. 1 loop Grid (X + I, Y + J).Index := Grid (X + I, Y + J).Index or (2 ** (I + 2 * J)); Grid (X + I, Y + J).Density := Grid (X + I, Y + J).Density + P.Density; end loop; end loop; end if; end loop; for J in Integer range 1 .. 25 loop for I in Integer range 1 .. 80 loop S := (J - 1) * 961 + (I - 1) * 12 + 1; Output (S .. S + 11) := Lookup (Grid, I, J); end loop; Output (J * 961) := Latin.LF; end loop; Output (24025 .. 24028) := Latin.ESC & "[0m"; return Output; end Marching_Squares; end ANSI_Terminal;