Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Table fields updating on their own [solved]

edited August 16 in Questions Posts: 2

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

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)
self.name = _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(self.name)
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.name] = c
end


Species = class()
function Species:init(_name, _param, _parentSpecies)
self.name = _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.name] = s
return s.name
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 v.name
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! :)

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.

Comments

  • dave1707dave1707 Mod
    Posts: 9,584

    @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.

  • dave1707dave1707 Mod
    Posts: 9,584

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

  • Posts: 2
    @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 :)
Sign In or Register to comment.