| Age | Commit message (Collapse) | Author |
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Since NPM only uses README.md (and no normal README file), the existing
documentation is now living in the README.md.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
This patch changes the behavior of the calculation loop of a board
(nextState) to keep track of the changes that happened during the round
(number of cells that died or were born in a given team).
These stats may be accessed by called the getStats() method on a World
instance, which returns a !Stats object:
const world = Life2.World(...);
// ...
const stats = world.getStats();
displayStats(stats);
Close: https://github.com/nc0fr/life2/issues/8
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Doesn't work still!
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The new simulator is a simple Web application composed of a single HTML
document. A controler script is available in
//life2/simulator/site/simulator.js to manage the game displayed on the
page.
The board will be represented in a <canvas> element, using the Canvas
Web API.
Close: https://github.com/nc0fr/life2/issues/6
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The simulator will now be based upon the open-source packages created
for Life2, namely @life2/game (for implementing the game logic behind
the scenes), and @life2/format (to share board states with the team).
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
(A spec might come later)
The Life2 Text Format (L2TF) is a ASCII-based file format that allows
the sharing of a Life2 board easily. The format is designed to be easy
to parse by both machines and humans, as it is pretty natural,
reprensenting a grid as a set of lines.
As said in the beginning, the format is currently only defined in the
index.js file, however a specification will be done later (probably
during the week), for now, this is enough.
Currently, the format is composed of the following:
CELL KIND CHARACTER UINT8 REPR
EMPTY . 0
TEAM_A a 1
TEAM_B b 2
BARRIER # 3
A grid is supposedly a set of lines composed of the aforementionned
characters, for illustration, a Boad like the following:
const board = [[3, 3, 3, 3, 3, 3, 3, 3, 3],
[3, 0, 1, 0, 0, 0, 0, 2, 3],
[3, 0, 1, 0, 1, 2, 2, 2, 3],
[3, 0, 0, 1, 1, 2, 1, 1, 3],
[3, 0, 0, 0, 2, 2, 2, 0, 3],
[3, 3, 3, 3, 3, 3, 3, 3, 3]]; // 9x6
will be represented in the following file:
(file: //.../board.l2tf)
#########\n
#.a....b#\n
#.a.abbb#\n
#..aabaa#\n
#...bbb.#\n
#########\n
The current implementation, in JavaScript, exposes only three elements:
two functions and a string-based C-like enumeration.
The API is really simple, only being based on the parse() and
stringify() methods. JavaScript experts may recognize a similar pattern
as the standard JSON API available.
A typical user flow of the system may be:
import * as Life2 from '@life2/game';
import * as L2TF from '@life2/format';
const game = new Life2.World(...);
// ... init game
// Save the current board state in a file to share it with others
const curr = game.board.getGrid();
const text = L2TF.stringify(curr);
shareFile(new File(text));
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The World class is a Facade pattern which manages the main logic of the
Life2 simulation game: iterating over the board given a set of rules.
The World class mainly represents a single simulation.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
RulesManager is a utility class that has the responsability of storing
and managing a set of rules. Rules are identified by their name,
meaning that there cannot be two rules with the same names. However, no
check is done on the function content:
const func = (cell, _) => cell;
const rule1 = new Rule("foo", "", func);
const rule2 = new Rule("bar", "", func);
const rule3 = new Rule("foo", "", func);
const manager = new RulesManager();
manager.add(rule1); // OK
manager.add(rule2); // OK because "foo" != "bar"
manager.add(rule3); // Error("Rule 'foo' is already registered')
Also, the manager internally use a JavaScript Map object, meaning the
order returned when getting all registered rules is not promised to be
the same has the order of registration. This also means that the
performance and time complexity of the object is dependant on the
JavaScript engine (the ECMA Script specification only imposes a
datastructure where operations have a complexity better than O(n)).
I believe it is a non-issue as the manager should not keep a lot of
rules anyway.
The reason for the existance of the RulesManager class is to simplify
the facade that is the World class.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The rule.js file was imported the Cell type from index.js instead of
cell.js, creating a cyclic import graph as index.js itself imports the
rule.js file. While not illegal in the Node.js ecosystem, it is still
an issue that could crash some static analysis tools, and a bad pattern
to avoid in general.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
This patch removes the logic of computing the next state of a board to
the Board class. Instead, this will be the responsability of the World
class.
The rational behind this change is that it will simplifies the reasoning
about the Board as only being a geometrical data structure, leaving
the class to a single responsability. On the other hand, the World
class, which is already the manager of the game loop, will see its logic
simplified by being able to directly compute the next state, instead of
relying on its dependency on a Board.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The Board class is an abstraction over any 2D shaped board to allow the
use of any two dimensional shapes as a grid for the Life2 simulation.
This patch creates and exposes two types: the Board class, and a Grid
typedef.
The Board class is expected to be inherited by more concrete shaped
boards, such as classic "Rectangular" boards, or more complex "Triangle"
ones. Boards act as their own abstraction over their shape, with the
only requirement of implementing the small Board API defined by the
inherited class.
The Grid type serves as a encoded representation of the Board shape
using JavaScript Arrays and our defined Life2.Cell enumeration:
import {Cell} from "@life2/game";
/**
* @typedef {!Array<!Array<!Cell>>}
*/
let Grid;
The Grid structure can be though as a protocol.
The two combined can be represented as the following:
BOARD CODE
########## const grid = [[3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
###a.b.### [3, 3, 3, 1, 0, 2, 0, 3, 3, 3],
#.aab..ba# -> [3, 0, 1, 1, 2, 0, 0, 2, 1, 3],
###bb..### [3, 3, 3, 2, 2, 0, 0, 3, 3, 3],
########## [3, 3, 3, 3, 3, 3, 3, 3, 3, 3]];
Assuming:
* . = 0 = Cell.EMPTY
* a = 1 = Cell.TEAM_A
* b = 2 = Cell.TEAM_B
* # = 3 = Cell.BARRIER
The Grid representation could be obtained by calling the getGrid()
method, which can then be used by some user interface:
1. The simulator interface (our @life2/simulator)
2. A text format to share the grid state offline (our @life2/l2sf).
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Barrier cells are cells that never change and are not affected by rules
(hardcoded behavior in the Rule class). Barriers can be used by boards
to shape their board, e.g.
// `#` for barriers, `.` for empty, `a` for team A, and `b` for
// team B.
const board = [ "####################",
"####...######...####",
"###aa....##..b...###",
"##a....a...bb.....##",
"###....aabbbb....###",
"#####...a.bb...#####",
"########a...########",
"#########..#########",
"####################" ]; // 20x9 heart shaped
As illustrated, boards stay list of strings, but thanks to the barrier,
they can adopt specific shapes. A regular array shaped board unifies
the API between downstream users and our internal states.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Rules a simple mathematical fuctions that determine the next state of
the cells they are applied to. By their nature, rules either return a
new state, or do not apply.
Our implementation of rules allow modularity, where a rules either
return a state (Cell type) to notice a change, or nothing (the null
object) to notice no change.
The merit of such an implementation is that the last choice is
ultimately done by the board, which increases the flexibility of
downstream users.
For instance, a standard implementation of the game could determine the
final new state of a cell by reducing all the rules output on the given
cell and choosing the most occuring one:
const cell = ...;
const neighbors = board.getNeighbors(cell);
const states = rules.map(r => r.execute(cell, neighbords))
.filter(s => s != null);
const empty = states.filter(s => s === Cell.EMPTY)
.length;
const teamA = states.filter(s => s === Cell.TEAM_A)
.length;
const teamB = states.filter(s => s === Cell.TEAM_B)
.length;
const newState = Math.max(empty, teamA, teamB);
boad.changeCell(cell, newState);
Note that this is some fake code, the final API may not look like this.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
A cell is the smallest unit in the Life2 simulation game. It carries
information about its aliveness (whether or not it is filled), and the
team it is part of (TEAM_A or TEAM_B).
The cell type is currently implemented as an enumeration of integers,
merging the two states in one value. I believe integers are the fastest
type JavaScript runtimes can manipulate, especially at this small scale
(unsigned 8-bit integers). Given these properties, I believe using
integers will avoid huge performance and memory consumption in the
browser when dealing with boards of larger sizes (or even pseudo
infinite sizes...).
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The //life2/game directory hosts a JavaScript implementation of the
Life2 game, which will be distributed via the NPM package manager at
@life2/game.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
I have reserved the @life2 scope on the NPM registry to allow publishing
our packages, which is required for the game to work.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The previous command was not finding the files to format, making
Clang-Format always fail in CI even tho everything was correct.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
This patch adds the remaining names in AUTHORS for copyright reasons.
Close: https://github.com/nc0fr/life2/issues/3
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
GoogleJS ESlint configuration was actually named "closure" and not
GoogleJS, as Closure is the public name for JSCompiler.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
This patch adds a GitHub Actions workflows that ensures the JavaScript
source are following our JS Style Guide (Google's one).
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Dependabot is an automatic utility which periodically checks for updates
in our dependencies and open issues or merge requests to ask to update
them. This can be useful to avoid security issues in the long run.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The L2SF file format is a string representation format of a Life2 Board
at a given state. This is useful to create files that can be shared
publicly, or the make "checkpoints" of a simulation.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
This patch provides the logic behind the Life2 simulator: a classic Game
of Life with two teams.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
This patch provides a few settings to make VSCode follows the linting
tools used in the project.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
ESLint is a popular linting framework and static analyzer in the
JavaScript Ecosystem. Our configuration follows the Google JavaScript
Style Guide, as seen in issues.
Closes: https://github.com/nc0fr/life2/issues/4
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Clang-Format is a powerful code formatting tool for languages with a
C-like syntax, including JavaScript.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
|
|
Signed-off-by: Kaawan <121562747+Kaawan-d20@users.noreply.github.com>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
The World class is the entrypoint of the simulation program, where all
cells lives and states are calculated.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
|
|
Le projet de simulation (`//life2/simulator`) est une machine d'exécution
conçue pour faire tourner notre version customisable du jeu de la vie
en supportant plusieurs équipes.
Ce patch existe pour créer le projet et le configurer pour permettre
le développement.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Ce patch partage la présentation PDF de l'Unité d'Enseignment dans le
dossier "docs/".
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
GitHub Actions est un système de CI/CD gratuit proposé par GitHub
permettant la vérification d'un ensemble de règles et d'analyses
statiques sur un programme.
La mise en place de GitHub Actions permettra de faciliter la
collaboration et le déployement des outils (notamment le simulateur).
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Simulator est une application orientée Web complexe permettant
l'exécution et l'étude d'automates cellulaires dans le style du jeu de
la vie.
Grâce à des fonctionnalités d'étude en temps réel, le système pourra
permettre la gestion (ajout, suppression, ...) de règles durant
l'exécution, ainsi que la modification des états de cellules (assigner
des "équipes", bloquer une cellule sur un état perpetuelle, ...).
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Un Workspae NPM permet d'utiliser l'écosystème de module de NPM au sein
d'un monorepo.
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|
|
Signed-off-by: Nicolas Paul <n@nc0.fr>
|