#![no_main] #![no_std] use core::{ fmt::Write, iter::repeat, ops::{Deref, DerefMut}, }; use heapless::{String, Vec}; use system::with_stdout; use uefi::prelude::*; const WIDTH: usize = 30; const HEIGHT: usize = 30; type Matrix = Vec, HEIGHT>; #[derive(Debug, Clone)] struct Life { matrix: Matrix, } impl Deref for Life { type Target = Matrix; fn deref(&self) -> &Self::Target { &self.matrix } } impl Default for Life { fn default() -> Self { let mut matrix: Vec, HEIGHT> = Vec::default(); for _ in 0..HEIGHT { matrix.push(repeat(false).take(WIDTH).collect()).unwrap(); } Life { matrix } } } impl DerefMut for Life { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.matrix } } impl Life { fn with_starter(starter: &[(usize, usize)]) -> Self { let mut life = Self::default(); for (i, j) in starter.iter() { life[*i][*j] = true; } life } fn play(self) -> Life { const OFFSETS: &[(i64, i64)] = &[ (-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1), ]; let mut future = Life::default(); self.iter().enumerate().for_each(|(row, line)| { line.iter().enumerate().for_each(|(column, alive)| { let neighbors = OFFSETS .iter() .filter(|offset| { let neighbor = ((row as i64) + offset.0, (column as i64) + offset.1); let i = neighbor.0; let j = neighbor.1; i >= 0 && j >= 0 && (i as usize) < HEIGHT && (j as usize) < WIDTH && self[i as usize][j as usize] }) .count(); future[row][column] = (*alive && (neighbors == 2 || neighbors == 3)) || (!*alive && neighbors == 3); }) }); future } /// Buffers output into one string per frame since println does not buffer output in uefi-rs. fn render(&self) -> Frame { let mut frame = Frame::default(); for l in self.iter() { for cell in l.iter() { if *cell { frame.push('X').unwrap() } else { frame.push(' ').unwrap() } } frame.push('\n').unwrap() } frame } } type FrameBuffer = String<{ (WIDTH * HEIGHT) + HEIGHT }>; #[derive(Default)] struct Frame { buffer: FrameBuffer, } impl Deref for Frame { type Target = FrameBuffer; fn deref(&self) -> &Self::Target { &self.buffer } } impl DerefMut for Frame { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } const BREEDER: &[(usize, usize)] = &[(15, 16), (16, 15), (16, 16), (17, 16), (17, 17)]; const RENDER_DELAY: usize = 100_000; #[entry] fn main() -> Status { uefi::helpers::init().unwrap(); let mut life = Life::with_starter(&BREEDER); for _ in repeat(()) { life = life.play(); let frame = life.render(); with_stdout(|stdout| { stdout.reset(true).unwrap(); stdout.write_str(&frame).unwrap() }); // Stall the loop a bit so it is easier to watch boot::stall(RENDER_DELAY); } Status::SUCCESS }