Initial commit.
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | /target | ||||||
|  | **/*.rs.bk | ||||||
|  | *~ | ||||||
							
								
								
									
										8
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | [package] | ||||||
|  | name = "pixelfoo" | ||||||
|  | version = "0.1.0" | ||||||
|  | authors = ["juergen <juergen@chaospott.de>"] | ||||||
|  | edition = "2018" | ||||||
|  |  | ||||||
|  | [dependencies] | ||||||
|  | rand = "0.6.0" | ||||||
							
								
								
									
										12
									
								
								README.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								README.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | bimood - color cycling mood lamp with two complementary colors | ||||||
|  |     parameter is the seconds for one cycle through the colors | ||||||
|  |  | ||||||
|  | predprey - grass-prey-predator simulation | ||||||
|  |     parameter is number of actions per 40ms frame | ||||||
|  |  | ||||||
|  | maze - draws a maze | ||||||
|  |     parameter is number of actions per 40ms frame | ||||||
|  |  | ||||||
|  | Compile with "cargo build --release". | ||||||
|  |  | ||||||
|  | The binary executables are in the "target/release" subdirectory. | ||||||
							
								
								
									
										141
									
								
								src/bin/bimood/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								src/bin/bimood/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | |||||||
|  | use std::env::args; | ||||||
|  | use std::io::stdout; | ||||||
|  | use std::io::Write; | ||||||
|  | use std::iter::repeat; | ||||||
|  | use std::thread::sleep; | ||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Debug)] | ||||||
|  | struct Color(u8, u8, u8); | ||||||
|  |  | ||||||
|  | impl Color { | ||||||
|  |     fn black() -> Color { | ||||||
|  |         Color(0, 0, 0) | ||||||
|  |     } | ||||||
|  |     fn white() -> Color { | ||||||
|  |         Color(255, 255, 255) | ||||||
|  |     } | ||||||
|  |     fn gray50() -> Color { | ||||||
|  |         Color(128, 128, 128) | ||||||
|  |     } | ||||||
|  |     fn red() -> Color { | ||||||
|  |         Color(255, 0, 0) | ||||||
|  |     } | ||||||
|  |     fn green() -> Color { | ||||||
|  |         Color(0, 255, 0) | ||||||
|  |     } | ||||||
|  |     fn blue() -> Color { | ||||||
|  |         Color(0, 0, 255) | ||||||
|  |     } | ||||||
|  |     fn yellow() -> Color { | ||||||
|  |         Color(255, 255, 0) | ||||||
|  |     } | ||||||
|  |     fn cyan() -> Color { | ||||||
|  |         Color(0, 255, 255) | ||||||
|  |     } | ||||||
|  |     fn magenta() -> Color { | ||||||
|  |         Color(255, 0, 255) | ||||||
|  |     } | ||||||
|  |     fn complement(&self) -> Color { | ||||||
|  |         Color(255 - self.0, 255 - self.1, 255 - self.2) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn interpolate_u8(b0: u8, b1: u8, a: f64) -> u8 { | ||||||
|  |     let b0 = b0 as f64; | ||||||
|  |     let b1 = b1 as f64; | ||||||
|  |     ((1.0 - a) * b0 + a * b1) as u8 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn interpolate(c0: Color, c1: Color, a: f64) -> Color { | ||||||
|  |     Color( | ||||||
|  |         interpolate_u8(c0.0, c1.0, a), | ||||||
|  |         interpolate_u8(c0.1, c1.1, a), | ||||||
|  |         interpolate_u8(c0.2, c1.2, a), | ||||||
|  |     ) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Frame = Vec<Vec<Color>>; | ||||||
|  |  | ||||||
|  | fn send<T: Write>(w: &mut T, f: &Frame) -> std::io::Result<()> { | ||||||
|  |     for l in f { | ||||||
|  |         for c in l { | ||||||
|  |             let Color(r, g, b) = c; | ||||||
|  |             let buf = &[*r, *g, *b]; | ||||||
|  |             w.write_all(buf)?; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     w.flush() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const DEFAULT_LOOP_TIME: usize = 120; | ||||||
|  |  | ||||||
|  | fn main() -> std::io::Result<()> { | ||||||
|  |     let args = args().collect::<Vec<_>>(); | ||||||
|  |     eprintln!("executing {}", args[0]); | ||||||
|  |  | ||||||
|  |     let x_size = args[1].parse::<usize>().unwrap(); | ||||||
|  |     let y_size = args[2].parse::<usize>().unwrap(); | ||||||
|  |     let loop_time = args[3].parse::<usize>().unwrap_or(DEFAULT_LOOP_TIME); | ||||||
|  |     eprintln!( | ||||||
|  |         "screen size {}x{}, loop time {:?}s", | ||||||
|  |         x_size, y_size, loop_time | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     let mut border = 0; | ||||||
|  |     while (x_size - 2 * border) * (y_size - 2 * border) > x_size * y_size / 2 { | ||||||
|  |         border += 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     let t_frame = 0.040; // s | ||||||
|  |     let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32); | ||||||
|  |  | ||||||
|  |     let mut previous_color = Color::blue(); | ||||||
|  |     let colors = vec![ | ||||||
|  |         Color::red(), | ||||||
|  |         Color::yellow(), | ||||||
|  |         Color::green(), | ||||||
|  |         Color::cyan(), | ||||||
|  |         Color::blue(), | ||||||
|  |         Color::magenta(), | ||||||
|  |     ]; | ||||||
|  |     let mut color_index = 0; | ||||||
|  |     let mut next_color = colors[color_index]; | ||||||
|  |  | ||||||
|  |     // time to interpolate from one color to the next | ||||||
|  |     let t_interpolate = (loop_time as f64) / (colors.len() as f64); // s | ||||||
|  |     let delta_a = t_frame / t_interpolate; | ||||||
|  |     let mut a = 0.0; | ||||||
|  |  | ||||||
|  |     eprint!("delta_a {}", delta_a); | ||||||
|  |     loop { | ||||||
|  |         let c0 = interpolate(previous_color, next_color, a); | ||||||
|  |         let c1 = c0.complement(); | ||||||
|  |         let mut frame = repeat(repeat(c0).take(x_size).collect::<Vec<_>>()) | ||||||
|  |             .take(y_size) | ||||||
|  |             .collect::<Vec<_>>(); | ||||||
|  |         for x in border..(x_size - border) { | ||||||
|  |             for y in border..(y_size - border) { | ||||||
|  |                 frame[y][x] = c1 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         a += delta_a; | ||||||
|  |         if a >= 1.0 { | ||||||
|  |             a = 0.0; | ||||||
|  |  | ||||||
|  |             color_index += 1; | ||||||
|  |             if color_index >= colors.len() { | ||||||
|  |                 color_index = 0; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             previous_color = next_color; | ||||||
|  |             next_color = colors[color_index]; | ||||||
|  |         } | ||||||
|  |         let mut buf = Vec::with_capacity(x_size * y_size * 3); | ||||||
|  |         send(&mut buf, &frame)?; | ||||||
|  |         stdout().write_all(&buf)?; | ||||||
|  |         stdout().flush()?; | ||||||
|  |         sleep(delay); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										225
									
								
								src/bin/maze/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										225
									
								
								src/bin/maze/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,225 @@ | |||||||
|  | use std::env::args; | ||||||
|  | use std::io::stdout; | ||||||
|  | use std::io::Write; | ||||||
|  | use std::thread::sleep; | ||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
|  | use rand::thread_rng; | ||||||
|  | use rand::Rng; | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Debug)] | ||||||
|  | struct Color(u8, u8, u8); | ||||||
|  |  | ||||||
|  | #[allow(unused)] | ||||||
|  | impl Color { | ||||||
|  |     fn black() -> Color { | ||||||
|  |         Color(0, 0, 0) | ||||||
|  |     } | ||||||
|  |     fn white() -> Color { | ||||||
|  |         Color(255, 255, 255) | ||||||
|  |     } | ||||||
|  |     fn gray50() -> Color { | ||||||
|  |         Color(128, 128, 128) | ||||||
|  |     } | ||||||
|  |     fn red() -> Color { | ||||||
|  |         Color(255, 0, 0) | ||||||
|  |     } | ||||||
|  |     fn green() -> Color { | ||||||
|  |         Color(0, 255, 0) | ||||||
|  |     } | ||||||
|  |     fn blue() -> Color { | ||||||
|  |         Color(0, 0, 255) | ||||||
|  |     } | ||||||
|  |     fn yellow() -> Color { | ||||||
|  |         Color(255, 255, 0) | ||||||
|  |     } | ||||||
|  |     fn cyan() -> Color { | ||||||
|  |         Color(0, 255, 255) | ||||||
|  |     } | ||||||
|  |     fn magenta() -> Color { | ||||||
|  |         Color(255, 0, 255) | ||||||
|  |     } | ||||||
|  |     fn complement(&self) -> Color { | ||||||
|  |         Color(255 - self.0, 255 - self.1, 255 - self.2) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||||||
|  | enum Square { | ||||||
|  |     Unknown, | ||||||
|  |     Corridor, | ||||||
|  |     Wall, | ||||||
|  |     Start, | ||||||
|  |     Finish, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct Board(Vec<Vec<Square>>); | ||||||
|  |  | ||||||
|  | fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> { | ||||||
|  |     for line in &board.0 { | ||||||
|  |         for square in line { | ||||||
|  |             let Color(r, g, b) = match square { | ||||||
|  |                 Square::Unknown => Color::black(), | ||||||
|  |                 Square::Corridor => Color::yellow(), | ||||||
|  |                 Square::Wall => Color::blue(), | ||||||
|  |                 Square::Start => Color::red(), | ||||||
|  |                 Square::Finish => Color::green(), | ||||||
|  |             }; | ||||||
|  |             let buf = &[r, g, b]; | ||||||
|  |             w.write_all(buf)?; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     w.flush() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Board { | ||||||
|  |     fn new(x_size: i32, y_size: i32, x_maze_size: i32, y_maze_size: i32) -> Board { | ||||||
|  |         Board( | ||||||
|  |             (0..y_size) | ||||||
|  |                 .map(move |y| { | ||||||
|  |                     (0..x_size) | ||||||
|  |                         .map(|x| { | ||||||
|  |                             if x < x_maze_size && y < y_maze_size { | ||||||
|  |                                 if x == 0 | ||||||
|  |                                     || x == x_maze_size - 1 | ||||||
|  |                                     || y == 0 | ||||||
|  |                                     || y == y_maze_size - 1 | ||||||
|  |                                     || (x % 2 == 0 && y % 2 == 0) | ||||||
|  |                                 { | ||||||
|  |                                     Square::Wall | ||||||
|  |                                 } else { | ||||||
|  |                                     Square::Unknown | ||||||
|  |                                 } | ||||||
|  |                             } else { | ||||||
|  |                                 Square::Unknown | ||||||
|  |                             } | ||||||
|  |                         }) | ||||||
|  |                         .collect::<Vec<_>>() | ||||||
|  |                 }) | ||||||
|  |                 .collect::<Vec<_>>(), | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  |     fn get(&self, pos: (i32, i32)) -> Square { | ||||||
|  |         let (x, y) = pos; | ||||||
|  |         self.0[y as usize][x as usize] | ||||||
|  |     } | ||||||
|  |     fn set(&mut self, pos: (i32, i32), sq: Square) { | ||||||
|  |         let (x, y) = pos; | ||||||
|  |         self.0[y as usize][x as usize] = sq; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | struct Move { | ||||||
|  |     from: (i32, i32), | ||||||
|  |     dir: (i32, i32), | ||||||
|  |     prio: i32, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn add_move(open: &mut Vec<Move>, arg: isize, from: (i32, i32), dir: (i32, i32)) { | ||||||
|  |     open.push(Move { from, dir, prio: 0 }); | ||||||
|  |     open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const DEFAULT_ARG: isize = 16; | ||||||
|  |  | ||||||
|  | fn main() -> std::io::Result<()> { | ||||||
|  |     let args = args().collect::<Vec<_>>(); | ||||||
|  |     eprintln!("executing {}", args[0]); | ||||||
|  |  | ||||||
|  |     let x_size = args[1].parse::<usize>().unwrap(); | ||||||
|  |     let y_size = args[2].parse::<usize>().unwrap(); | ||||||
|  |     let arg = args[3].parse::<isize>().unwrap_or(DEFAULT_ARG); | ||||||
|  |     eprintln!("screen size {}x{}, arg {}", x_size, y_size, arg); | ||||||
|  |  | ||||||
|  |     let mut rng = thread_rng(); | ||||||
|  |  | ||||||
|  |     let t_frame = 0.040; // s | ||||||
|  |     let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32); | ||||||
|  |     let mut t_wait = 0.0; // s | ||||||
|  |  | ||||||
|  |     let x_size = x_size as i32; | ||||||
|  |     let y_size = y_size as i32; | ||||||
|  |     let x_maze_size = (x_size - 1) / 2 * 2 + 1; | ||||||
|  |     let y_maze_size = (y_size - 1) / 2 * 2 + 1; | ||||||
|  |     let x_maze_mid = (x_maze_size - 1) / 4 * 2 + 1; | ||||||
|  |     let y_maze_mid = (y_maze_size - 1) / 4 * 2 + 1; | ||||||
|  |  | ||||||
|  |     let mut board = Board(Vec::new()); | ||||||
|  |     let mut open = Vec::new(); | ||||||
|  |     loop { | ||||||
|  |         if open.is_empty() { | ||||||
|  |             if t_wait > 0.0 { | ||||||
|  |                 t_wait -= t_frame; | ||||||
|  |             } else { | ||||||
|  |                 t_wait = 60.0; // s | ||||||
|  |                 board = Board::new(x_size, y_size, x_maze_size, y_maze_size); | ||||||
|  |  | ||||||
|  |                 // start in the middle | ||||||
|  |                 let mid = (x_maze_mid, y_maze_mid); | ||||||
|  |                 board.set(mid, Square::Corridor); | ||||||
|  |                 add_move(&mut open, arg, mid, (1, 0)); | ||||||
|  |                 add_move(&mut open, arg, mid, (0, 1)); | ||||||
|  |                 add_move(&mut open, arg, mid, (-1, 0)); | ||||||
|  |                 add_move(&mut open, arg, mid, (0, -1)); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             let work = arg.max(1); | ||||||
|  |             let mut count = 0; | ||||||
|  |             while !open.is_empty() && count < work { | ||||||
|  |                 let mut start = 0; | ||||||
|  |                 let mut limit = 0; | ||||||
|  |                 let mut prio = open[limit].prio; | ||||||
|  |                 loop { | ||||||
|  |                     limit += 1; | ||||||
|  |                     if limit >= open.len() { | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     if open[limit].prio > prio { | ||||||
|  |                         if rng.gen::<f64>() >= 0.4 { | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                         start = limit; | ||||||
|  |                         prio = open[limit].prio; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 let r = rng.gen_range(start, limit); | ||||||
|  |                 let Move { | ||||||
|  |                     from: (x0, y0), | ||||||
|  |                     dir: (dx, dy), | ||||||
|  |                     .. | ||||||
|  |                 } = open.remove(r); | ||||||
|  |  | ||||||
|  |                 let (x1, y1) = (x0 + dx, y0 + dy); | ||||||
|  |                 let (x2, y2) = (x1 + dx, y1 + dy); | ||||||
|  |                 if board.get((x1, y1)) == Square::Unknown { | ||||||
|  |                     board.set((x1, y1), Square::Corridor); | ||||||
|  |                     board.set((x2, y2), Square::Corridor); | ||||||
|  |  | ||||||
|  |                     for (dx, dy) in vec![(1, 0), (0, 1), (-1, 0), (0, -1)] { | ||||||
|  |                         let (x3, y3) = (x2 + dx, y2 + dy); | ||||||
|  |                         let (x4, y4) = (x3 + dx, y3 + dy); | ||||||
|  |                         if board.get((x3, y3)) == Square::Unknown { | ||||||
|  |                             if board.get((x4, y4)) == Square::Unknown { | ||||||
|  |                                 add_move(&mut open, arg, (x2, y2), (dx, dy)); | ||||||
|  |                             } else { | ||||||
|  |                                 board.set((x3, y3), Square::Wall); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     count += 1; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if open.is_empty() { | ||||||
|  |                 board.set((1, 1), Square::Start); | ||||||
|  |                 board.set((x_maze_size - 2, y_maze_size - 2), Square::Finish); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         let mut buf = Vec::with_capacity((x_size * y_size * 3) as usize); | ||||||
|  |         send(&mut buf, &board)?; | ||||||
|  |         stdout().write_all(&buf)?; | ||||||
|  |         stdout().flush()?; | ||||||
|  |         sleep(delay); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										166
									
								
								src/bin/predprey/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								src/bin/predprey/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,166 @@ | |||||||
|  | use std::env::args; | ||||||
|  | use std::io::stdout; | ||||||
|  | use std::io::Write; | ||||||
|  | use std::iter::repeat_with; | ||||||
|  | use std::thread::sleep; | ||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
|  | use rand::thread_rng; | ||||||
|  | use rand::Rng; | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Debug)] | ||||||
|  | struct Color(u8, u8, u8); | ||||||
|  |  | ||||||
|  | #[allow(unused)] | ||||||
|  | impl Color { | ||||||
|  |     fn black() -> Color { | ||||||
|  |         Color(0, 0, 0) | ||||||
|  |     } | ||||||
|  |     fn white() -> Color { | ||||||
|  |         Color(255, 255, 255) | ||||||
|  |     } | ||||||
|  |     fn gray50() -> Color { | ||||||
|  |         Color(128, 128, 128) | ||||||
|  |     } | ||||||
|  |     fn red() -> Color { | ||||||
|  |         Color(255, 0, 0) | ||||||
|  |     } | ||||||
|  |     fn green() -> Color { | ||||||
|  |         Color(0, 255, 0) | ||||||
|  |     } | ||||||
|  |     fn blue() -> Color { | ||||||
|  |         Color(0, 0, 255) | ||||||
|  |     } | ||||||
|  |     fn yellow() -> Color { | ||||||
|  |         Color(255, 255, 0) | ||||||
|  |     } | ||||||
|  |     fn cyan() -> Color { | ||||||
|  |         Color(0, 255, 255) | ||||||
|  |     } | ||||||
|  |     fn magenta() -> Color { | ||||||
|  |         Color(255, 0, 255) | ||||||
|  |     } | ||||||
|  |     fn complement(&self) -> Color { | ||||||
|  |         Color(255 - self.0, 255 - self.1, 255 - self.2) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||||||
|  | enum Square { | ||||||
|  |     Empty, | ||||||
|  |     Grass, | ||||||
|  |     Rabbit, | ||||||
|  |     Fox, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Board = Vec<Vec<Square>>; | ||||||
|  |  | ||||||
|  | fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> { | ||||||
|  |     for line in board { | ||||||
|  |         for square in line { | ||||||
|  |             let Color(r, g, b) = match square { | ||||||
|  |                 Square::Empty => Color::blue(), | ||||||
|  |                 Square::Grass => Color::green(), | ||||||
|  |                 Square::Rabbit => Color::yellow(), | ||||||
|  |                 Square::Fox => Color::red(), | ||||||
|  |             }; | ||||||
|  |             let buf = &[r, g, b]; | ||||||
|  |             w.write_all(buf)?; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     w.flush() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const DEFAULT_ARG: usize = 10; | ||||||
|  |  | ||||||
|  | fn grow(board: &Board, x: usize, y: usize, grow: Square, die: Square) -> Square { | ||||||
|  |     let x_size = board[0].len() as isize; | ||||||
|  |     let y_size = board.len() as isize; | ||||||
|  |     let x = x as isize; | ||||||
|  |     let y = y as isize; | ||||||
|  |     for (dx, dy) in vec![(1, 0), (0, 1), (-1, 0), (0, -1)] { | ||||||
|  |         let x1 = x + dx; | ||||||
|  |         let y1 = y + dy; | ||||||
|  |         if 0 <= x1 && x1 < x_size && 0 <= y1 && y1 < y_size { | ||||||
|  |             let neigh_sq = board[y1 as usize][x1 as usize]; | ||||||
|  |             if neigh_sq == grow { | ||||||
|  |                 return grow; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     die | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn main() -> std::io::Result<()> { | ||||||
|  |     let args = args().collect::<Vec<_>>(); | ||||||
|  |     eprintln!("executing {}", args[0]); | ||||||
|  |  | ||||||
|  |     let x_size = args[1].parse::<usize>().unwrap(); | ||||||
|  |     let y_size = args[2].parse::<usize>().unwrap(); | ||||||
|  |     let arg = args[3].parse::<usize>().unwrap_or(DEFAULT_ARG); | ||||||
|  |     eprintln!("screen size {}x{}, arg {}", x_size, y_size, arg); | ||||||
|  |  | ||||||
|  |     let mut rng = thread_rng(); | ||||||
|  |  | ||||||
|  |     let p_empty = 0.25; | ||||||
|  |     let p_grass = 0.25; | ||||||
|  |     let p_rabbit = 0.25; | ||||||
|  |     // p_fox = 0.05 | ||||||
|  |     let mut board = repeat_with(|| { | ||||||
|  |         repeat_with(|| { | ||||||
|  |             let p = rng.gen::<f64>(); | ||||||
|  |             if p < p_empty { | ||||||
|  |                 Square::Empty | ||||||
|  |             } else if p < p_empty + p_grass { | ||||||
|  |                 Square::Grass | ||||||
|  |             } else if p < p_empty + p_grass + p_rabbit { | ||||||
|  |                 Square::Rabbit | ||||||
|  |             } else { | ||||||
|  |                 Square::Fox | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .take(x_size) | ||||||
|  |         .collect::<Vec<_>>() | ||||||
|  |     }) | ||||||
|  |     .take(y_size) | ||||||
|  |     .collect::<Vec<_>>(); | ||||||
|  |  | ||||||
|  |     let t_frame = 0.040; // s | ||||||
|  |     let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32); | ||||||
|  |  | ||||||
|  |     let x_mid = (x_size - 1) as f64 / 2.0; | ||||||
|  |     let y_mid = (y_size - 1) as f64 / 2.0; | ||||||
|  |     let r = (x_size.min(y_size) - 1) as f64 / 2.5; | ||||||
|  |     loop { | ||||||
|  |         for _ in 0..arg { | ||||||
|  |             let x = rng.gen_range(0, x_size); | ||||||
|  |             let y = rng.gen_range(0, y_size); | ||||||
|  |             let sq = board[y][x]; | ||||||
|  |             let dx = (x as f64 - x_mid as f64) / r as f64; | ||||||
|  |             let dy = (y as f64 - y_mid as f64) / r as f64; | ||||||
|  |             let p0 = (dx * dx + dy * dy).min(1.0); | ||||||
|  |             let p_survive = match sq { | ||||||
|  |                 Square::Empty => 1.0, | ||||||
|  |                 Square::Grass => p0, | ||||||
|  |                 Square::Rabbit => p0, | ||||||
|  |                 Square::Fox => 0.8 * p0, | ||||||
|  |             }; | ||||||
|  |             let new_sq = if rng.gen::<f64>() < p_survive { | ||||||
|  |                 sq | ||||||
|  |             } else { | ||||||
|  |                 Square::Empty | ||||||
|  |             }; | ||||||
|  |             board[y][x] = match sq { | ||||||
|  |                 Square::Empty => grow(&board, x, y, Square::Grass, new_sq), | ||||||
|  |                 Square::Grass => grow(&board, x, y, Square::Rabbit, new_sq), | ||||||
|  |                 Square::Rabbit => grow(&board, x, y, Square::Fox, new_sq), | ||||||
|  |                 Square::Fox => new_sq, | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         let mut buf = Vec::with_capacity(x_size * y_size * 3); | ||||||
|  |         send(&mut buf, &board)?; | ||||||
|  |         stdout().write_all(&buf)?; | ||||||
|  |         stdout().flush()?; | ||||||
|  |         sleep(delay); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     #[test] | ||||||
|  |     fn it_works() { | ||||||
|  |         assert_eq!(2 + 2, 4); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Juergen Stuber
					Juergen Stuber