Skip to main content

sac/life/
render.rs

1use super::*;
2
3impl LifeField {
4    /// Renders the field as a vector of ratatui Lines using Braille characters.
5    ///
6    /// Each Braille character represents a 2x4 block of cells, allowing for
7    /// compact display of the life field.
8    ///
9    /// # Arguments
10    /// * `char_width` - Width in characters (each char is 2 cells wide)
11    /// * `char_height` - Height in characters (each char is 4 cells tall)
12    ///
13    /// # Returns
14    /// Vector of Lines representing the rendered field
15    pub fn render_lines(&self, char_width: usize, char_height: usize) -> Vec<Line<'static>> {
16        let mut lines = Vec::with_capacity(char_height);
17        for char_y in 0..char_height {
18            let mut text = String::with_capacity(char_width);
19            for char_x in 0..char_width {
20                let dot_x = char_x * 2;
21                let dot_y = char_y * 4;
22                text.push(self.braille_char(dot_x, dot_y));
23            }
24            lines.push(Line::from(Span::raw(text)));
25        }
26        lines
27    }
28
29    /// Generates a Braille character representing a 2x4 cell block.
30    ///
31    /// Braille dots are mapped to cell positions:
32    /// - Dots 1-4 map to left column (top to bottom)
33    /// - Dots 5-8 map to right column (top to bottom)
34    ///
35    /// # Arguments
36    /// * `dot_x` - X coordinate of the left cell in the block
37    /// * `dot_y` - Y coordinate of the top cell in the block
38    ///
39    /// # Returns
40    /// A Braille Unicode character (U+2800 to U+28FF)
41    pub fn braille_char(&self, dot_x: usize, dot_y: usize) -> char {
42        let mut bits = 0u32;
43        for local_y in 0..4 {
44            for local_x in 0..2 {
45                let x = dot_x + local_x;
46                let y = dot_y + local_y;
47                if x < self.width && y < self.height && self.cells[self.index(x, y)] {
48                    bits |= match (local_x, local_y) {
49                        (0, 0) => 0x01,
50                        (0, 1) => 0x02,
51                        (0, 2) => 0x04,
52                        (0, 3) => 0x40,
53                        (1, 0) => 0x08,
54                        (1, 1) => 0x10,
55                        (1, 2) => 0x20,
56                        (1, 3) => 0x80,
57                        _ => 0,
58                    };
59                }
60            }
61        }
62        char::from_u32(0x2800 + bits).unwrap_or(' ')
63    }
64}