Developer Guide: The Simulator
The Simulator component is a collection of classes that work together to represent the simulation state and provide various features like round simulation, history management, the algorithm API, saving and loading of simulation states, and more. Because most features depend on several different classes, we explain the system by going through its features instead of going through the classes.
The core of the simulator is the ParticleSystem
class.
The AmoebotSimulator
creates one instance of this class when the application starts and uses it to manage all simulation features until the application is stopped.
In most cases, the public methods and properties defined by this class should be the only way of modifying the simulation system.
Simulator Modes
At any time, the simulator is in one of two modes: The Initialization Mode or the Simulation Mode. While in Initialization Mode (in short Init Mode), it is possible to add particles to the system, remove or relocate existing particles and edit their parameters based on the currently selected algorithm. This can all be done manually by the user through the UI or automatically by an algorithm's generation method.
When the simulator is in Simulation Mode, particles cannot be added or removed anymore, and they can only be edited in the latest round. The system state evolves as the particle activations and movements are simulated, and previous system states can be reviewed due to the history feature.
Implementation
The ParticleSystem
provides several methods for changing between the modes:
The InitializationModeStarted(string selectedAlgo)
method is used to change from Simulation Mode to Init Mode.
The ongoing simulation is then stored in a temporary file using the Save/Load feature and the selected algorithm's default generation method is used to generate a system of particles as a starting point.
If InitializationModeAborted()
is called, the simulator switches back to Simulation Mode and reloads the previously stored simulation state.
The current initialization system is discarded in this case.
Finally, if InitializationModeFinished(string selectedAlgo)
is called, the current particle system is used to instantiate a new particle system in which all particles are initialized with the selected algorithm using the parameters stored in the initialization particles.
The system then resets the round counter to 0 and starts a new simulation in Simulation Mode.
In Init Mode, there are several simple methods like SetSelectedAlgorithm(string algoName)
and GenerateParticles(string methodName, object[] parameters)
that directly correspond to the available UI buttons and tools, allowing the user to easily modify the initialization system.
Simulation State
The main task of the simulator is to represent the state of the particle system, both during initialization and during the actual simulation. In both modes, the system uses two simple data structures to store instances of a class that represents an amoebot particle. The first data structure is a list that stores all particles in the system and the second is a map using grid coordinates as keys and particles as values. Expanded particles occupy two grid nodes, so they appear twice in the map.
Rounds
During Simulation Mode, the system keeps track of the round numbers using simple integer counters.
A simulation always starts in round 0 and the counter is incremented with each simulated round.
There are two properties storing the first (EarliestRound
) and the last (LatestRound
) simulated round, which define the range of valid round indices.
The current round is also represented by two properties, CurrentRound
and PreviousRound
.
Outside of a round simulation (i.e., to the outside of the system), they always have the same value.
The difference is that CurrentRound
is incremented at the start of a round simulation and PreviousRound
is incremented at the end, which is very convenient for some calculations during the simulation.
Particles
The rest of the system state is stored in the particle instances themselves.
There are two different classes, one for each mode: Particle
for the Simulation Mode and InitializationParticle
for Init Mode.
Both of them store the basic particle state information:
- The particle's global grid position, both for its head and its tail (which are equal for contracted particles)
- The current global expansion direction if the particle is expanded
- The particle's chirality,
true
meaning that it matches the global counter-clockwise rotation direction - The particle's compass direction, represented as the global direction that the particle believes to be East
In Init Mode, the chirality and compass direction of a particle can be set freely and its position and expansion state can be changed as well; this is not possible in Simulation Mode.
Internally, the system uses the OpenInitParticle
class to access the particle's data more freely.
The abstract InitializationParticle
class just serves as an interface for custom generation algorithms.
It is the simulator's responsibility to ensure that the particles' positions match the occupied positions in the system's map whenever it is not currently simulating a round.
The particle classes contain much more information than what is listed here. However, most of it is related to more specific features and thus, it is explained elsewhere.