Brief description
Cell Lab is a simulation game for Android. It is developed by Petter Säterskog.
What is being said about Cell Lab
Some selected, possibly illuminating reviews:
"Awesome Game I love the concept and the art. My only gripe with the game is the lack of detail into each of the cell types. There would be a big benefit in having a localized database with more info and some examples; bonus points if this can be accessed from within the game. As of this review, I have yet to beat all the challenges, but I am having a good time trying. Looking forward to a sequel!" – Internet user priestofmyownchurch
"Amazing!!!! I love this app so much! Especially since i'm taking microbiology right now, and it's extremely nice to see some key concepts come to life! I really appreciate it! And that it's not your ordinary smarty pants game that only uses smarty pants-ness to allure people but is actually just a regular arcade game. This game is by no means ordinary, and i love it. I agree with the other reviews though that there's always room for improvement--more detailed and diverse cell types would be highly appreciated, although i understand how that could be hard achieve especially in a mobile app. But if you /do/ come to steam, I, among the many other science geeks, would be willing to pay (a reasonable price) for the added features and cell types. <3 Keep up the amazing work!" – Internet user Andrea Cleofas
"Absolutely Amazing; I love it! I am lucky to have found this game! It is a wet dream for anybody majoring in any biological science. The game allows you to engineer genomes to achieve a goal, or for your own experiments for fun. It may take a little time to learn the game's way of engineering genomes, but once fluidity amongst the controls is achieved, their are seemingly endless possibilities! The game is rather realistic in its portrayal of the diversity of physical and behavioural attributes of different cells. The game is well done!" – Internet user Victor Chopp
"Worst App ever I can't beat the 1st tutorial" – Internet user Ramona Thumstedter
"Poop This app is poop." – Internet user Unicorn Girl 101 Cutie Queen
"Im sorry... I dont understand what to do. The tutorials need work." – Internet user Yo Momma
"Evolution IS NIT REALL!!! This game is bad. It tries so hard to disprove Christians but the bible says god made everything!!" – Internet user Colby Velaer
Play Store listing
Cell Lab simulates few-celled organisms. It contains 45 challenges where the player is presented with an environment and has to design an organism that will survive in it. Solving challenges unlocks additional genes that can give cells new properties.
The encoding of the cells behaviour has been made as intuitive as possible without losing generality but it nevertheless takes a bit of effort to understand. Going through the provided tutorials carefully is recommended.
Cell Lab also contains an experimental mode where the user can set the parameters of the environment and put designed organisms in it to see how they multiply (or die). It is also possible to seed this environment with random genomes and once a viable genome has been seeded one can see how it slowly evolves through tiny mutations to an organism well adapted to the environment it is in.
It is then possible to change the environment to see how they re-adapt, fast forward the simulation, and finally to save and share it.
This simulation is not biologically realistic, all cells in Cell Lab only has one function, to swim, to eat, to collect sunlight, to float, etc . This is not how cells work in nature where one cell can do many things at once. This accuracy has been traded off to be able to make an interesting game. The cells have also been made to multiply very fast, this also for the enjoyment of the user.
What is realistic is the evolution taking place in this game. How species adapt to their environment and compete with each other to sometimes attain an equilibrium and sometimes extinction.
Features:
• 4 tutorials
• 45 challenges
• 16 types of cells with different functions
• 20 cell-modes per genome to program
• 22+ parameters in each cell mode
• Environment editor with 27 parameters
• Simulates and renders up to 1000 cells at decent frame rates
• Arbitrary number of cells and petri dish size in advanced mode
• Beautifully animated vector graphics that lets you zoom to atomic scales
• Save, load and share both environments and genomes
• Simulation fast-forward and slow-motion
• No advertisements or in-game payments
This app needs three permissions:
• Internet access. This is required to send bug reports and other anonymous usage data.
• Network state. This is required to make sure bug reports and usage data are only sent over wifi to avoid using mobile data.
• External Storage. This app needs to be able to read and write external storage so that the user can send and receive samples as email attachments.
A PC version of Cell Lab is being developed. The goal is for it to run on GNU/Linux, Windows and Mac. Please refer to the forum for discussions, I'll try to keep an eye there. Suggestions and ideas are welcome! It is easier to take suggestions into account before the game is finished.
Entry 11
(2022-01-29)
I've been curious to see if some parts of cell lab could be sped up by being written in native code.
The cell light absorption calculation is a prime candidate because it is rather resource intensive but also very indepenent of the rest of the code.
I rewrote it in rust and initial tests showed that it was 2-3 times faster.
Doing regular performance tests is important to make sure I do not introduce any new bottlenecks.
I do not have a good infrastructure for performance testing so I decided to work a bit on this. I have earlier changed the challenges to be run as lua scripts, but have always intended for Cell Lab to have a "head-less" mode where it can run a lua script without any graphics.
This headless mode is perfect for benchmarks as well so I decided to finally implement it. Cell Lab can now be run from a terminal with the flag "cell_lab -s script.lua" and it will start without a window and run the contents of the scipt.
I made a benchmarking script:
1 -- This script runs a benchmark of the Cell Lab simulation.
2 -- This can be used to compare different Cell Lab versions and different computer setups.
3
4 function benchmark(name, n)
5 exp = lab.load("petri_dishes/local/examples/"..name..".substrate");
6 start = os.clock()
7 for i = 0, n
8 do
9 exp.substrate.update(exp.substrate.max_dt)
10 end
11 finish = os.clock()
12 print (" * "..n.." iterations for "..name.." finished in " .. finish-start .. "s. "..exp.substrate.cell_count().." cells at end.");
13 end
14
15 print("Running benchmarks:")
16 benchmark("swimmers", 500)
17 benchmark("swimmers", 1000)
18 benchmark("swimmers", 2000)
19 benchmark("algae", 500)
20 benchmark("algae", 1000)
21 benchmark("algae", 2000)
The output looks like this in the old Java version:
$cell_lab -s benchmark.lua
Running benchmarks:
* 500 iterations for swimmers finished in 2.382s. 2055 cells at end.
* 1000 iterations for swimmers finished in 3.422s. 1963 cells at end.
* 2000 iterations for swimmers finished in 6.776s. 1960 cells at end.
* 500 iterations for algae finished in 8.044s. 3813 cells at end.
* 1000 iterations for algae finished in 16.822s. 3889 cells at end.
* 2000 iterations for algae finished in 34.487s. 3828 cells at end.
After moving the light absorption calculations to native code the output looks like this:
$cell_lab -s benchmark.lua
Running benchmarks:
* 500 iterations for swimmers finished in 1.869s. 2055 cells at end.
* 1000 iterations for swimmers finished in 3.184s. 1963 cells at end.
* 2000 iterations for swimmers finished in 6.201s. 1960 cells at end.
* 500 iterations for algae finished in 7.574s. 3817 cells at end.
* 1000 iterations for algae finished in 16.664s. 3897 cells at end.
* 2000 iterations for algae finished in 30.296s. 3893 cells at end.
The algae experiment is very light absorption intensive, with many cells stacked on top of each other, and here we see a slight speed increase.
As you can note, the numbers of cells is now different. The reason for this is that floating point calculations now give slightly different results, within the precision of single precision floating point numbers.
The Cell Lab simulaiton is inherently chaotic, so any microscopic change quickly becomes macroscopic.
Entry 10
(2022-01-14)
I've been thinking a bit about the workflow that I think players will use and decided that all genomes should be associated with a substrate (e.g. a petri dish). This is opposed to the system in the Android version where these are saved, exported and imported separately.
Each substrate is explicitly associated with a set of genomes (in addition to whatever is on the petri dish), and I call this altogether an "Experiment".
This change makes life easier for me, we do not need to be able to upload, describe, rate, and search for both genomes and substrates, only experiments.
It is also nice because often a genome is associated with a certain environment, and will not work optimally (or at all) on other substrates so we would always need to refer to or describe a substrate when uploading a single genome.
One could in principle skip saving individual genomes altogether and always share them live on petri dishes.
However, that system becomes annoying if you want to import a genome from one substrate to another, as the import dialog would have to be able to pick a certain cell from the petri dish (Which do you want? Maybe need to see it run to pick?).
When implementing this change, I also decided to change the genome editor so that we can edit several genomes at a time. I believe this will also make life a lot easier when designing e.g. ecosystems. I made the different genoems have their separate undo histories, as they are edited completely independently.
The load experiment menu now shows the associated genomes:
The genome editor allows us to select the genome to edit from a dropdown menu:
The genome editor has a dialog that allows the importing of genomes from other experiments:
I've also done some boring stuff that needed to be done, like adding a dialog for saving experiments in a folder of choice:
Entry 9
(2021-04-25)
I've experimented a bit with UV-protection. It turned out to be surprisingly difficult to make something interesting. Protection with melanin is very costly, especially for swimming organisms so a very high penalty for no protection is needed.
Otherwise, organisms with short generations without UV-protection are more fit.
Therefore, I set cells to die as soon as their nucleus is exposed to any UV light. Floating UV-protected photosynthetic organisms work quite fine. They are quite stable because there is also not much light left for photosynthesis below them that other species could use.
UV-protected swimmers (credit to Leandro Pires for the design) do work, however they need very much food and high salinity. So much so that oportunistic species that live in the UV-shade quickly ruin the ecosystem. See the screenshot below:
I'm leaning towards removing the UV light code since the mechanic was quite frustrating to work with and it didn't result in very interesting ecosystems. As can be seen in these screenshots, I've also added a water surface. Density and viscocity are 0 above it, resulting in organisms floating on the surface.
Entry 8
(2021-02-16)
I've changed the light mechanics to be more dynamic. Photocytes now cast shadows that affect the amount of light the downstream photocytes receive.
I've added a new property to the photocytes, they can now have one of three different pigments. Chlorophyll a, chlorophyll b, or melanin.
The former two have slightly different absorption spectra and which one is optimal for a certain cell depends on the spectrum of sunlight incident on it.
The light that was not absorbed remains in the shadow of the cell, and is thus different for the different pigments. The optimal configuration then seems to be to first absorb mostly red light using a layer of cells with
chlorophyll a, and then a layer below of cells with chlorophyll b absorbing what remains of the blue light. There is not enough light for further cells below this. See the screenshot below:
The calculation is pretty exact, it takes into account partially occluded cells and keeps track of double, triple, ..., shadows. The graphics just show all types of shadows in the same color though. This is for
speed, but also to make it look less cluttered. I will improve the graphics a bit, make it look overall lighter when the sun is shining to compensate for the shadows. I will also do some investigation if this is slowing down
the simulation a lot. I think it should be fine since not that many photocytes can survive since light is now limited. However, if someone were to artificially keep hundreds of layers of photocytes alive with some other energy source, it might
impact performance negatively.
I'm considering adding a setting for UV light similar to the radiation setting that will induce mutations. These could then be stopped using melanin. If the light is strong enough, then organisms will be forced to protect themselves
or else they will mutate so rapidly they die. I think this might result in e.g. some interesting looking swimmers since all sides exposed to light (which is now dynamic) would need protection.
Entry 7
(2021-02-2)
I have been working on both the backend, and a game menu. The menu has a section with a repository of Petri dishes.
This is also where new petri dishes are created (top button on the left).
Note that this is all very proof-of-concepty, the design is pretty ugly, and also buggy. E.g. the create new experiment button should look differently from the saved Petri dishes.
These are saved here from within the editor, and can afterwards be opened here again.
Clicking the publish button results in the Petri dish being sent to the backend. The backend checks the storage quota of the user and if it fits it stores some metadata in an sqlite database, and the actual Petri dish is stored in a separate file.
Leaving this menu and instead going to the "Published experiments" menu, we can then search for this "publication". Here we see first the empty search field, then we search for "star". This results in only one hit which
we select in the hit list. We click "download" and wait for the "open" button to be enabled, and finally we open the download in the editor.
It seems to work fine, I need to put some work into free-text search and ordering by different fields.
There is also some synchronization needed that was skipped in getting this working, but which will be necessary to make it reliable.
The user can later save the experiment again from the editor, with a new name, and open it in the repository.
The downloaded version is always saved to disk locally but this isn't shown to the user in the petri dish repository, it is just for caching downloads. The cache is easy to find and can be emptied for saving disk space though.
Entry 6
(2021-01-24)
I have added tools so cells can be moved with the mouse, boosted, or removed. The icons can be seen below, I'm not great at designing them but these
will have to do for now. I've connected this to scripting so challenges can specify what tools are allowed.
I have also spent quite some time looking at how to design the backend. I have zero experience here, but it seems rather straightforward. It think I should
use some third party database, instead of just saving the state to a file once in a while. I want something that is robust against losing power at any moment
(i.e. will not be corrupt if the server suddenly restarts). It should also cache stuff in memory that is accessed often, and features like indexing would be nice. I've decided
to go for an sqlite database, connected to the backend through jdbc. That way it can easily be replaced by another sql database if needed in the future to for example move the database to
a different server from where the backend is running if it becomes overloaded.
I've started reading a bit about sql because of this, seems like a mess but I'm not sure what else to use :P.
Entry 5
(2020-12-22)
I've continued work on the interface for settings that depend on the cell state, e.g. signal substances.
The plot is now a bit nicer and it now affects the genome being edited.
This still needs some work but I will leave this for now since it is more or less functional. My plan is to prototype everything quickly to get everything working.
After that I will (hopefully) go back and make things look a bit neater.
Big changes are still happening to the design and the code behind so I will just break stuff if I make them look nice right away.
I have also spent some time on getting the tutorials working. They will like the challenges be run as a Lua script. Here is an example tutorial:
1 -- microscope training 1
2
3 local step = 1
4
5 instructions = {
6 [[Welcome to the Microscope training!
7 Here we will here teach you how to use the robotic microscope installed in our lab.
8 Select the "Cell inserter" marked with an orange frame]],
9 [[Great job!
10 Now you have selected the cell inserter and can add cells in the substrate by clicking on it.
11 Click in the orange rectangle to insert a cell there.]]
12 }
13
14 function reset()
15 lab.load_built_in_substrate("tut1.substrate")
16 step = 0
17 next_step()
18 lab.set_description( instructions[step] )
19 gui.highlight( gui.views.top.buttons.tools.add )
20 end
21
22 function start()
23 lab.set_left_panel_mode( lab.left_panel_modes.tutorial ) -- do not show substrate editor in challenge
24 genome_editor.set_allowed_cell_types( {genetics.cell_types.photocyte} )
25 lab.set_allowed_tools( {lab.tools.add, lab.tools.remove, lab.tools.move} )
26 reset()
27 end
28
29 function next_step()
30 step = step + 1
31 lab.set_description( instructions[step] )
32 lab.set_status( "Step " .. tostring(step) .. " of " .. tostring(# instructions) )
33 if step > # instructions
34 then
35 challenge.finish()
36 end
37 end
38
39 function button_press(button)
40 if step == 1 and button == gui.views.top.buttons.tools.add
41 then
42 gui.clear_highlights()
43 -- add code for highlighting in substrate
44 next_step()
45 end
46 end
This looks like this in the first and second step:
I think this "highlighting" can lower the threshold a bit for new users and it allows me to use icons without text to a higher degree, resulting in a neater interface.
I might later opt for an arrow instead of the frame like here because it looks a bit weird with half of it outside the screen.
The next step will be to allow for drawing in the substrate. Drawing there will be made a bit more powerful, probably with a few primitives like lines and triangles.
The Lua scripts don't run as fast as the Java code so I will probably let the Lua script create the primitives once, and then the Java code keeps drawing them until removed.
This can then be used for challenges with some spatial rules, for example a race with a start and a finish line.
Entry 4
(2020-12-16)
I've been working a bit on a view for editing the cell properties that can depend on cell signals and such. It needs some tweaking of the layout but the functionality is at least there now.
Genome editor undo/redo-buttons (quite ugly) have been added as well, though they are not implemented fully yet.
I also spent some time experimenting with evolution, specifically the sprinkling of random cells. Random swimmers that reproduce show up very rarely compared to the earliest CL versions even
though it is faster now so I've investigated a bit what the reason for this is.
It seems to be due to many factors, we have many more modes now, making it harder to form short cycles. There are also more settings now, and some may be very detrimental. E.g. a swim force of 0
kills the swimmer. Low adhesin strength, very long adhesin, very high nutrient priority, etc.., are all detrimental. The first four of these are new so the chance that all these values are reasonable for all
cells is now very low. This is unavoidable and it isn't really expected that a completely random genome might work if the genomes are complex. It is fun though, so I might tune things. E.g. making
all probability distributions more centered around "normal" values really helps. At some point it cannot be called random any more though..
Entry 3
(2020-12-6)
I've started to work on scripting. This will be used to implement challenges instead of littering the Cell Lab code with special checks and changes for every new type of challenge.
It wasn't too bad before, but this will have the added benefit that players can themselves make challenges that go beyond just counting the total number of cells or so.
Long term I think this will allow for much more interesting challenges while keeping Cell Lab code clean.
For a first release I will focus on making challenges and tutorials using scripts. But in the future they may be more like mods, allowing to run simulations and output stats to files or
changing the behavior of cells to some degree.
I've settled on the scripting language Lua and the Java library LuaJ.
I haven't used Lua before but it seems like an industry standard for scipting in games and the actual scripts will be very simple anyways.
I've now implemented enough functionality for the challenge Macrophages 3. The Lua code for it is below, hopefully it is rather self-explanatory. It is subject to change, let me know on the forum if you have suggestions :).
1 -- Challenge Macrophages 3
2
3 local goal_cell_count = 100
4 local cell_budget = 10
5 local placed_cell_count = 0
6
7 function start()
8 lab.set_title( challenge.get_name() )
9 lab.set_description( "Can you make use of the light incident on this Petri dish to get 100 cells?" )
10 lab.set_left_panel_mode( lab.left_panel_modes.challenge ) -- do not show substrate editor in challenge
11 genome_editor.set_allowed_cell_types( {genetics.cell_types.phagocyte, genetics.cell_types.flagellocyte} )
12 reset()
13 end
14
15 function reset()
16 lab.load_built_in_substrate("algae1.substrate")
17 placed_cell_count = 0
18 end
19
20 function step()
21 local n = substrate.cell_count()
22 local status = "Inserted cells: " .. tostring(placed_cell_count) .. " (0 - " .. tostring(cell_budget) .. ")"
23 status = status .. "\nTotal cells: " .. tostring(n) .. " (" .. tostring(goal_cell_count) .. " - ∞)"
24 lab.set_status(status)
25 if n >= goal_cell_count
26 then
27 challenge.finish()
28 end
29 end
30
31 function place_organism(organism)
32 if # organism + placed_cell_count <= cell_budget
33 then
34 placed_cell_count = placed_cell_count + # organism
35 return true
36 else
37 if placed_cell_count == cell_budget
38 then
39 lab.notify_cursor("No cells left.")
40 else
41 lab.notify_cursor("Only " .. tostring(cell_budget - placed_cell_count) .. " cells left.")
42 end
43 return false
44 end
45 end
46
Entry 2
(2020-?)
I've started some work on the genome editor. It will see a lot of changes compared to the Android version:
- Much requested numeric input. Text input is challenging to implement with so many features like end, ctrl-a, ctrl-c, and many more obscure that are platform dependent. I will implement a limited subset of these.
- Settings split in tabs.
- Cell previews in dropdowns (this was now trivial since the GUI is all OpenGL).
- Undo/redo buttons.
- Family tree view has been added which makes navigation in the genome a lot easier.
Many buttons are not implemented yet so genome editing is not working fully at the moment but here are some pictures of the genome editor so far:
Entry 1
(2020-?)
Some basic framework has been set up and the graphics and simulation is reproduced the same way as the Android version.
I settled on using LWJGL for graphics and implementing the GUI myself to avoid being limited by some library I do not fully understand.
This turned out to be a big issue on Android whith many time-consuming bugs with the GUI.
I made some basic classes for buttons and such and added some settings for the substrate editor to try it out.
I also added some new plots that show the substrate statistics over time.