ability to edit grid with cursor
1 files changed, 73 insertions(+), 9 deletions(-)

M src/main.rs
M src/main.rs +73 -9
@@ 11,6 11,9 @@ extern crate getopts;
 use ncurses::*;
 
 fn main() {
+    const BG_COLORS: i16 = 0;
+    const CURSOR_COLORS: i16 = 1;
+
     let init_ncurses = || {
         initscr();
         cbreak();

          
@@ 18,6 21,9 @@ fn main() {
         nodelay(stdscr, true);
         keypad(stdscr, true);
         curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);
+        start_color();
+        init_pair(BG_COLORS, COLOR_WHITE, COLOR_BLACK);
+        init_pair(CURSOR_COLORS, COLOR_BLACK, COLOR_YELLOW);
     };
     let end_ncurses = || {
         echo();

          
@@ 159,36 165,54 @@ fn main() {
             *col = rand::random::<bool>();
         }
     }
-    let mut game = Game { cells: cells, dead: dead, alive: alive, border: border, window: newwin(rows as i32, cols as i32, maxy / 2 - rows as i32 / 2, maxx / 2 - cols as i32 / 2) };
+    let mut game = Game { cells: cells, dead: dead, alive: alive, border: border, color_pair: BG_COLORS, window: newwin(rows as i32, cols as i32, maxy / 2 - rows as i32 / 2, maxx / 2 - cols as i32 / 2) };
+    let mut cursor = Cursor { y: 0, x: 0, color_pair: CURSOR_COLORS };
 
     let mut paused = false;
     'game_loop: loop {
         let before_render = time::precise_time_s();
 
         game.render();
+        if paused {
+            cursor.render(&game);
+        }
         let mut game_window_beg = (0i32, 0i32);
         getbegyx(game.window, &mut game_window_beg.0, &mut game_window_beg.1);
         game_window_beg.0 += rows as i32;
         mv(game_window_beg.0, game_window_beg.1);
         clrtoeol();
         addstr(&format!(
-            "exit (q)    {paused} (p){next}",
+            "exit (q)  |  {paused} (p){pausedcontrols}",
             paused = if paused { "resume" } else { "pause" },
-            next = if paused { "  next (n)" } else { "" })
+            pausedcontrols = if paused { "    next (n)    change cell (space)    move cursor (arrow keys)" } else { "" })
         );
         refresh();
         wrefresh(game.window);
 
         loop {
-            match getch() as u8 as char {
-                'q' => break 'game_loop,
-                'p' => {
+            const QUIT: i32 = 'q' as i32;
+            const PAUSE: i32 = 'p' as i32;
+            const NEXT: i32 = 'n' as i32;
+            match getch() {
+                QUIT => break 'game_loop,
+                PAUSE => {
                     paused = !paused;
                     nodelay(stdscr, !paused);
                     continue 'game_loop;
                 },
-                'n' => break,
-                _ => if paused { continue } else { break }
+                NEXT => break,
+                c @ _ => {
+                    let cursor_changed = cursor.process_input(c, &game.window, &mut game.cells);
+                    if paused {
+                        if cursor_changed {
+                            continue 'game_loop;
+                        } else {
+                            continue;
+                        }
+                    } else {
+                        break;
+                    }
+                }
             }
         }
 

          
@@ 212,7 236,8 @@ struct Game {
     dead: char,
     alive: char,
     border: Border,
-    window: WINDOW
+    window: WINDOW,
+    color_pair: i16
 }
 
 impl Game {

          
@@ 266,6 291,9 @@ impl Game {
     }
 
     fn render(&self) {
+        let color_pair = COLOR_PAIR(self.color_pair) as i32;
+        wattron(self.window, color_pair);
+
         for row in 0..self.cells.len() {
             for col in 0..self.cells[row].len() {
                 let cell_char = if self.cells[row][col] { self.alive } else { self.dead } as u64;

          
@@ 284,6 312,8 @@ impl Game {
             self.border.get_ncurses_char(BorderPart::BottomLeft),
             self.border.get_ncurses_char(BorderPart::BottomRight)
         );
+
+        wattroff(self.window, color_pair);
     }
 
 }

          
@@ 351,3 381,37 @@ impl Border {
     }
 
 }
+
+struct Cursor {
+    y: u16,
+    x: u16,
+    color_pair: i16
+}
+
+impl Cursor {
+
+    fn process_input(&mut self, ch: i32, window: &WINDOW, cells: &mut Vec<Vec<bool>>) -> bool {
+        let mut maxyx = (0i32, 0i32);
+        getmaxyx(*window, &mut maxyx.0, &mut maxyx.1);
+        let maxyx = maxyx;
+        const SELECT: i32 = ' ' as i32;
+        match ch {
+            KEY_LEFT if self.x as i32 - 1 >= 0 => self.x -= 1,
+            KEY_RIGHT if self.x as i32 + 1 < maxyx.1 => self.x += 1,
+            KEY_UP if self.y as i32 - 1 >= 0 => self.y -= 1,
+            KEY_DOWN if self.y as i32 + 1 < maxyx.0 => self.y += 1,
+            SELECT => cells[self.y as usize][self.x as usize] = !cells[self.y as usize][self.x as usize],
+            _ => return false
+        }
+        true
+    }
+
+    fn render(&self, game: &Game) {
+        let char_at_cursor = if game.cells[self.y as usize][self.x as usize] { game.alive } else { game.dead } as u64;
+        let color_pair = COLOR_PAIR(self.color_pair) as i32;
+        wattron(game.window, color_pair);
+        mvwaddch(game.window, self.y as i32, self.x as i32, char_at_cursor);
+        wattroff(game.window, color_pair);
+    }
+
+}