1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
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;
|