Table fields updating on their own [solved]

Hi everyone! Long time fan of Codea, first time poster :slight_smile:

I’m doing a small evolution sim project for fun and ran into something that looks like a mysterious bug (although I’m sure it’s just me being stupid). I’m not asking anyone to troubleshoot my code, but if you’ve encountered smth similar, any pointers as to what might be wrong would be most welcome.

The sim consists of 4 classes: Creature() for individual creature behavior, CreatureManager for managing entire population, Species() is just a description of the creature type (defined by its genome, which is simply a table of integers) and SpeciesManager() for managing the list of current species in the population. There are 2 global variables, CM = CreatureManager() and SM = SpeciesManager().

Here’s the relevant code:

Creature = class() function Creature:init(_name, _param, _pos, _parentSpecies) = _name -- creature name self.param = _param -- this is the genome (list of integers indexed by string, such as “speed”) -- which species the creature belongs to: self.species = SM:checkSpecies(self.param, true) or SM:createSpecies(self.param, _parentSpecies) end function Creature:reproduce() CM:spawnOffspring( end

CreatureManager = class() function CreatureManager:init() self.creatures = {} -- table with all creatures, indexed by their name self.counter = 0 -- total number of creatures since sim start end function CreatureManager:mutate(_param) -- returns new genome table after some mutation (not important) end function CreatureManager:spawnOffspring(_parentName) self.counter = self.counter + 1 parentParam = self.creatures[_parentName].param -- Genome of the parent offspringParam = self:mutate(parentParam) -- Genome of the offspring -- Spawn new creature at parent’s position and add it to the population c = Creature("Offspring "..self.counter, offspringParam, self.creatures[_parentName].pos, self.creatures[_parentName].species) self.creatures[] = c end
Species = class() function Species:init(_name, _param, _parentSpecies) = _name self.param = _param -- Reference genome of the species, same structure as in Creature() self.parentSpecies = _parentSpecies self.population = 1 end
SpeciesManager = class() function SpeciesManager:init() self.species = {} self.counter = 0 -- total number of species since sim start end -- creates new species and returns its name: function SpeciesManager:createSpecies(_param, _parentSpecies) self.counter = self.counter + 1 name = generateName(2).." ["..self.counter.."]" -- generate unique name s = Species(name, _param, _parentSpecies) self.species[] = s return end -- returns species name if such a species exist or nil -- if _updatePopulation is true, increases the population of the found species function SpeciesManager:checkSpecies(_param, _updateSpecies) for k, v in pairs(self.species) do -- differenceScore() just calculates how different two genomes are (not important) if differenceScore(_param, v.param) <= SPECIES_DEFINITION then if _updateSpecies then v:increasePopulation() end return end end return nil end SM = SpeciesManager() CM = CreatureManager()

It is important that there are no other references to SM.species or SM.species[x].param anywhere else in the code.

The idea is, as the sims runs the creatures reproduce with random mutations in their genome, and as the genome of the creature drifts far enough from any existing species, a new species is added to the SM.species table. And it runs as expected, with one exception. Sometimes as the sim progresses, the values in the param table of the already existing species change. It seems to happen after the new offspring has been spawned, and the new value somehow corresponds to the mutation of the offspring, but this change does not happen every time and does not happen at the time new offspring is spawned.

I’ve spent hours trying to troubleshoot this and starting to suspect there’s some issue with how Codea updates tables which I’m not aware of. Any ideas or pointers would be most appreciated! :slight_smile:

UPDATE: as usual, describing the problem helps by itself. It was indeed the case of me being stupid, not something wrong with Codea.

UPDATE 2: So the issue was me forgetting that a table identifier in Lua is only a reference to the table itself, so the ‘equals’ operator just copies that reference, but does nothing with the data. So, after
a[1] = 100 b = a b[1] = 200
a[1] is equal 200.

The solution is use custom function for table copy.

@konaire I doubt that it’s a problem with Codea, but working with tables can be tricky if you don’t understand parsing through them when updating/deleting entries. Just looking at someone else’s code, especially just parts of it, and trying to find an intermittent problem is next to impossible. The problem could be caused by code not shown. You might have to add more if/print statements to narrow down where and what is happening.

Anyways, welcome to the forum and don’t be a stranger.

@konaire Would you mind sharing your problem and your solution just in case someone else runs into a similar mystery.

@dave1707 You are of course correct, the issue was me forgetting what a Lua table is (I don’t use Lua often so it usually takes a while to refresh the memory every time I return to it). I’ll update the post with the solution :slight_smile: