Skip to content

Several iterations of Conway's Game Of Life with Ballerina programming language.

License

Notifications You must be signed in to change notification settings

janihur/bal-game-of-life

Repository files navigation

bal-game-of-life

Several iterations of Conway's Game Of Life with Ballerina programming language.

All versions apply the following rules:

  1. Any live cell with two or three live neighbours survives.
  2. Any dead cell with three live neighbours becomes a live cell.
  3. All other live cells die in the next generation. Similarly, all other dead cells stay dead.

The coordinate system is programmer-friendly with origo ({x:0, y:0}) in top-left corner and increasing into right and down:

―――――――――――――――――――――――
| 0,0 | 0,1 | 0,2 | ...
―――――――――――――――――――
| 1,0 | 1,1 | ...
―――――――――――――
| 2,0 | ...
―――――――
| ...

Error handling is kept simple with panics in all error scenarios (checkpanic keyword).

Versions A (version-a?.bal) are bare implementations and versions B (version-b?.bal) have features creeped in.

Note that there is no checks that the combination of the command line arguments or the values of the arguments are sensible.

These are my first implementations of this game ever.

Used Ballerina version:

$ bal version
Ballerina 2201.1.0 (Swan Lake Update 1)
Language specification 2022R2
Update Tool 1.3.9

Version A1

  1. The seed is hardcoded (initialization of the module global grid variable).
  2. Uses two fixed size grids (two dimensional boolean arrays).
  3. The grid is a global state.
  4. First finds out all neighbour cells and then checks in a separate step which of those are alive.

All neighbour cell coordinates are hardcoded with the following algorithm:

  1. Top row: left hand cell (#1)
  2. Top row: right hand cell (#2)
  3. Top row: all middle cells (#3)
  4. Bottom row: left hand cell (#4)
  5. Bottom row: right hand cell (#5)
  6. Bottom row: all middle cells (#6)
  7. All middle rows: left hand cell (#7)
  8. All middle rows: right hand cell (#8)
  9. All middle rows: all middle cells (#9)
―――――――――――――――――
| 1 | 3 | 3 | 2 |
―――――――――――――――――
| 7 | 9 | 9 | 8 |
―――――――――――――――――
| 7 | 9 | 9 | 8 |
―――――――――――――――――
| 4 | 6 | 6 | 5 |
―――――――――――――――――

Run:

bal run version-a1.bal

Version A2

Changes compared to version A1:

  • Removed emptyGrid initialization variable as [[DEAD]] is effectively the same. One could also use [[]] because the implicit default value for boolean is false but I prefer [[DEAD]] because it is more explict.
  • Simplified main loop.
  • Count the number of alive neighbours in one step.

Run:

bal run version-a2.bal

Version A3

Changes compared to version A2:

  • Instead of hard coding neighbour cell coordinates are (mostly) calculated.
  • Global grid variable removed. After that there is no more global state thus all functions except main() (because io:readln() is not isolated) could be isolated.
  • Implementation of function numberOfLiveCells() couldn't use reduce() because there is a pending specification issue with anonymous functions and isolation.
  • Added function comments. Ballerina has a built-in documentation framework. It doesn't work with a single file programs but the Ballerina Flavored Markup could still be used.

Run:

bal run version-a3.bal

Version A4

Changes compared to version A3:

  • Using a set of alive cells instead of two dimensional array of all cells. However Ballerina doesn't have set data structure and map only supports string keys. Hence the set (aliveCells variable) has been implemented with Ballerina's very powerful table data structure.
  • Implemented numberOfLiveCells() as reduce() in main(). Now the function name no more documents the purpose of the function but the name of the result variable numberOfLiveNeighbours does. As a bonus this also works around the specification issue with anonymous functions and isolation.
  • Generates the neighbour cell coordinates with a query expression that is Ballerina's realization of a list comprehension.

Run:

bal run version-a4.bal

Version B1

Changes compared to version A4:

  • Grid size increased to 9x9 and default seed changed.
  • Added an option to start with a random seed. Every first generation cell has 30% chance to be alive.
  • Added an option to load the first generation from a file. Note that the grid size have to be 9x9. You can load files created with --saveprefix option.
  • Added an option to save generations to files.
  • Added player.sh to show the generation files.

Run:

# start with hard-coded seed
bal run version-b1.bal
# start with a random seed
bal run version-b1.bal -- --random
# save all generations also to files with a prefix
bal run version-b1.bal -- --random --saveprefix=$(date +%Y%m%d-%H%M%S)-9x9-
# load the first generation from a file
bal run version-b1.bal -- --load=<FILENAME>

Show saved generation files:

./player.sh <FILES>

Version B2

For now this is the final version.

Changes compared to version B1:

  • Example generations added to gen/ directory. See them with player.sh.
  • Stops automatically when
    • all cells are dead
    • two consecutive generations are identical (the cells have stabilized)
    • the generation has already appeared earlier in the history (the generation cycle)
  • Variable grid size:
    • if --load option is used the grid size is read from the file
    • --size option sets the grid size
    • defaults to 9x9
  • Reports the number of alive cells.

Run:

# start with a custom grid size
bal run version-b2.bal -- -- size 12

See Version B1 for other run options.

About

Several iterations of Conway's Game Of Life with Ballerina programming language.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published