Skip to content

kazinad/game_of_life

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rust newbie learning project: game_of_life

This is a console based implementation of Conway's Game of Life cellular automation algorithm. This project intends to demonstrate most basic features of the Rust language.

Known issues

  • The current implementation uses console screen to display the evolving cell grid, and one cell represented by a single character on the console screen. On most systems the default console size is 80x40 characters, which is too small for the implemented cell automation algorithm. For this reason, please increase your console size to say 383x114 or bigger for a much enjoyable result.

Features

  • Each cell in a cell grid is represented by a single bit. The bits are grouped into Rust's usize scalar data type, so on a 64 bit system a single cell group stores 64 cells in a single usize value. All cells of a cell grid are stored in an array of cell groups cells: Vec<usize>. This dense representation of cell grid cells is eight times smaller than the cell <-> byte representation, i.e. scales better on larger cell grid sizes.
  • A cell has three properties in a cell grid: x and y positions and the alive/dead value. The alive/dead value is represented as a single bit in the cells vector, but its x and y coordinates are computed by the position of the bit within the bit array. This is done by the Indexer index and pos methods.
  • Computing cell grid generations is a pure function, which means, we need the nth generation of the cell grid to compute the (n+1)th generation. This is represented in Universe current and next CellGrid values. Simply swapping the two values avoids frequent large memory reallocations.
  • Computing next generation of the cell grid uses all the cpu cores available on the running system. Rust does not allow multiple threads to write the same memory, i.e. it denies to have different threads holding mutable references to the same cells vector. For this reason we have to create slices of the cells vector. The cell vector slices are represented by the CellVectorSlice which maps distinct regions of the original cells vector to different threads. There is no need to use additional thread synchronization methods, so those do not block each other and can run on full speed.
  • Displaying the current generation is also parallel to computing the next generation. This possible because Rust allows to have multiple immutable references to the same value.
  • Computing cell grid generations and displaying the current one are implemented in separate modules, so the current console display method is easy to replace.
  • The original algorithm settles to a relatively static combination of cells after a while. To avoid this, cells are added at random positions if the number of living cells gets stable within 10 generations.

Releases

No releases published

Packages

No packages published

Languages