From d7a9df805b6184349015cc72cf50b38a47576ee7 Mon Sep 17 00:00:00 2001 From: Svornost <11434-svornost@users.noreply.gitgud.io> Date: Tue, 20 Oct 2020 14:14:32 -0700 Subject: [PATCH] Restructure create_node_rec to skip *any* previously-created nodes, including for the current slave or those in its own descendant lines. This makes it a bit faster and totally tolerant of inheritance cycles (which will throw later on anyway, with a better error message). --- src/js/ibcJS.js | 72 +++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/src/js/ibcJS.js b/src/js/ibcJS.js index 58e02d5dbcc..654765c6b8e 100644 --- a/src/js/ibcJS.js +++ b/src/js/ibcJS.js @@ -1,7 +1,7 @@ /** @typedef IBCRelative * An very simple object that represents a entity in a family tree. * Represents a group of common properties shared by SlaveState, InfantState, and PlayerState, - * as well as fetus and genepool objects. + * as well as genepool objects. * @type {object} * @property {number} ID * @property {number} mother @@ -292,45 +292,47 @@ globalThis.ibc = (() => { * @param {IBCRelative} s */ let create_node_rec = s => { - // Certain parents (e.g. 0, societal elite) are not considered to be related, despite - // having the same ID; convert them to null - let m = or_null(s.mother); - let f = or_null(s.father); - - // Ensure that parent nodes are created - [m, f].forEach(p => { - if (p !== null && !(p in nodes)) { // Not created, we have to do something - if (p === -1) { - create_node_rec(V.PC); - } else { - // Search for a slave state, genePool entry, or missingTable entry - let gp = find_gp(p); - if (gp !== null) { - // If we find one, we might have ancestry information: recurse - create_node_rec(gp); + if (!(s.ID in nodes)) { + nodes[s.ID] = new IBCNode(s.ID); + + // Certain parents (e.g. 0, societal elite) are not considered to be related, despite + // having the same ID; convert them to null + const m = or_null(s.mother); + const f = or_null(s.father); + + // Ensure that parent nodes are created + [m, f].forEach(p => { + if (p !== null && !(p in nodes)) { // Not created, we have to do something + if (p === -1) { + create_node_rec(V.PC); } else { - // Otherwise, just create a plain node - nodes[p] = new IBCNode(p); + // Search for a slave state, genePool entry, or missingTable entry + let gp = find_gp(p); + if (gp !== null) { + // If we find one, we might have ancestry information: recurse + create_node_rec(gp); + } else { + // Otherwise, just create a plain node + nodes[p] = new IBCNode(p); + } } } - } - }); + }); - if (!(s.ID in nodes)) // Create this node if necessary - nodes[s.ID] = new IBCNode(s.ID); - // We created its parents earlier, so set them to the actual nodes - nodes[s.ID].mother = (m === null) ? m : nodes[m]; - nodes[s.ID].father = (f === null) ? f : nodes[f]; - - // Try to use a cached CoI for performance - let sg = find_gp(s.ID); - if (!ignore_coeffs && sg !== null && "inbreedingCoeff" in sg && sg.inbreedingCoeff !== -1) { - nodes[s.ID]._coeff = sg.inbreedingCoeff; + // Set parents to the actual nodes + nodes[s.ID].mother = (m === null) ? m : nodes[m]; + nodes[s.ID].father = (f === null) ? f : nodes[f]; + + // Try to use a cached CoI for performance + let sg = find_gp(s.ID); + if (!ignore_coeffs && sg !== null && "inbreedingCoeff" in sg && sg.inbreedingCoeff !== -1) { + nodes[s.ID]._coeff = sg.inbreedingCoeff; + } } }; // Populate the nodes - slaves.forEach(s=> create_node_rec(s)); + slaves.forEach(s => create_node_rec(s)); // Populate NodeCodes make_nc(nodes); @@ -442,13 +444,13 @@ globalThis.ibc = (() => { all_slave_like.push(oldMaster); // Gather the genetics of all current fetuses - /** @type {IBCRelative[]} */ + /** @type {FC.FetusGenetics[]} */ let all_fetuses = V.slaves.filter(s => s.preg > 0).map(s => s.womb.map(i => i.genetics)).reduce((res, cur) => res.concat(cur), []); /** Recursively find all of the given ID's children, born and unborn * @param {number} id * @param {Set<number>} cur_slaves - * @param {Set<IBCRelative>} cur_fetuses + * @param {Set<FC.FetusGenetics>} cur_fetuses * @param {Set<number>} cur_fetus_parents */ let find_children_rec = (id, cur_slaves, cur_fetuses, cur_fetus_parents) => { @@ -476,7 +478,7 @@ globalThis.ibc = (() => { /** @type {Set<number>} */ let needed_slave_ids = new Set(); // Since each fetus has a unique record, a set still suffices - /** @type {Set<IBCRelative>} */ + /** @type {Set<FC.FetusGenetics>} */ let needed_fetuses = new Set(); /** @type {Set<number>} */ let needed_parent_ids = new Set(); -- GitLab