]> git.lizzy.rs Git - rs2048.git/blob - src/display.rs
Fix inner field area
[rs2048.git] / src / display.rs
1 use super::game::{Board, Pos};
2 use crossterm::{cursor, queue, style::*};
3
4 enum Mode {
5     Roof_,
6     Data_,
7     Floor,
8     Empty,
9     Base_,
10 }
11
12 const FIELD_HEIGHT: usize = 3;
13 const FIELD_WIDTH: usize = 8;
14
15 fn write_line(stdout: &mut std::io::Stdout, vec: &[u32], mode: Mode) -> crossterm::Result<()> {
16     let mut vec = vec;
17     let len = vec.len();
18
19     queue!(
20         stdout,
21         Print(match mode {
22             Mode::Roof_ => "┏",
23             Mode::Data_ => "┃",
24             Mode::Floor => "┠",
25             Mode::Empty => "┃",
26             Mode::Base_ => "┗",
27         })
28     )?;
29
30     for i in 0..len {
31         let &n = vec.last().unwrap();
32         vec = &vec[0..vec.len() - 1];
33
34         match mode {
35             Mode::Data_ | Mode::Empty => queue!(stdout, Print(" "))?,
36             _ => {}
37         }
38
39         match mode {
40             Mode::Data_ | Mode::Empty if n != 0 => {
41                 let (r, g, b) = hsl::HSL {
42                     h: (n * 360 / 12) as f64,
43                     s: 1.0,
44                     l: 0.5,
45                 }
46                 .to_rgb();
47
48                 queue!(
49                     stdout,
50                     SetColors(Colors::new(Color::Black, Color::Rgb { r, g, b }))
51                 )?;
52             }
53             _ => {}
54         };
55
56         queue!(
57             stdout,
58             Print(match mode {
59                 Mode::Roof_ | Mode::Base_ => "━".repeat(FIELD_WIDTH),
60                 Mode::Floor => "─".repeat(FIELD_WIDTH),
61                 Mode::Data_ if n != 0 => format!("{:^w$}", 1 << n, w = FIELD_WIDTH - 2),
62                 Mode::Empty | Mode::Data_ => " ".repeat(FIELD_WIDTH - 2),
63             })
64         )?;
65
66         match mode {
67             Mode::Data_ | Mode::Empty => {
68                 queue!(stdout, SetAttribute(Attribute::Reset), Print(" "))?
69             }
70             _ => {}
71         }
72
73         if i != len - 1 {
74             queue!(
75                 stdout,
76                 Print(match mode {
77                     Mode::Roof_ => "┯",
78                     Mode::Data_ => "│",
79                     Mode::Floor => "┼",
80                     Mode::Empty => "│",
81                     Mode::Base_ => "┷",
82                 })
83             )?;
84         }
85     }
86
87     queue!(
88         stdout,
89         Print(match mode {
90             Mode::Roof_ => "┓",
91             Mode::Data_ => "┃",
92             Mode::Floor => "┨",
93             Mode::Empty => "┃",
94             Mode::Base_ => "┛",
95         }),
96         cursor::MoveToNextLine(1),
97     )?;
98
99     Ok(())
100 }
101
102 pub fn display_board(stdout: &mut std::io::Stdout, board: &Board) -> crossterm::Result<()> {
103     let dummy = vec![0; board.size.x as usize];
104
105     write_line(stdout, &dummy, Mode::Roof_)?;
106
107     for y in 0..board.size.y {
108         let vec = (0..board.size.x)
109             .rev()
110             .map(|x| board.get(Pos::new(x, y)).value())
111             .collect::<Vec<u32>>();
112
113         for i in 0..FIELD_HEIGHT {
114             write_line(
115                 stdout,
116                 &vec,
117                 if i == FIELD_HEIGHT / 2 {
118                     Mode::Data_
119                 } else {
120                     Mode::Empty
121                 },
122             )?;
123         }
124
125         if y != board.size.y - 1 {
126             write_line(stdout, &dummy, Mode::Floor)?;
127         }
128     }
129
130     write_line(stdout, &dummy, Mode::Base_)?;
131
132     Ok(())
133 }