private static Tuple<int, int>[] Link12_Extra(Tuple<int, int>[] initial, LinkItem[] items1, LinkItem[] items2, DistributeDistances distances, ItemLinker_ExtraArgs extraArgs)
        {
            Random rand = StaticRandom.GetRandomForThread();

            int wholePercent = extraArgs.Percent.ToInt_Floor();

            List<int> addOrder = new List<int>();

            if (extraArgs.BySize)
            {
                double totalSize = items2.Sum(o => o.Size);
                double maxSize = extraArgs.Percent * totalSize;
                double usedSize = 0;

                if (extraArgs.EvenlyDistribute)
                {
                    #region by size, evenly distribute

                    // Add some complete passes if over 100% percent
                    for (int cntr = 0; cntr < wholePercent; cntr++)
                    {
                        addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length));
                    }

                    usedSize = wholePercent * totalSize;

                    #endregion
                }

                #region by size, distribute the rest

                //NOTE: Building this list by size so that larger items have a higher chance of being chosen
                var bySize = items2.
                    Select((o, i) => Tuple.Create(i, o.Size / totalSize)).
                    OrderByDescending(o => o.Item2).
                    ToArray();

                // Keep selecting items unti the extra size is consumed (or if no more can be added)
                while (true)
                {
                    bool foundOne = false;

                    for (int cntr = 0; cntr < 1000; cntr++)     // this is an infinite loop detector
                    {
                        int attemptIndex = UtilityCore.GetIndexIntoList(rand.NextDouble(), bySize);     // get the index into the list that the rand percent represents
                        attemptIndex = bySize[attemptIndex].Item1;      // get the index into items2

                        if (items2[attemptIndex].Size + usedSize <= maxSize)
                        {
                            foundOne = true;
                            usedSize += items2[attemptIndex].Size;
                            addOrder.Add(attemptIndex);
                            break;
                        }
                    }

                    if (!foundOne)
                    {
                        // No more will fit
                        break;
                    }
                }

                #endregion
            }
            else
            {
                if (extraArgs.EvenlyDistribute)
                {
                    #region ignore size, evenly distribute

                    // Add some complete passes if over 100% percent
                    for (int cntr = 0; cntr < wholePercent; cntr++)
                    {
                        addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length));
                    }

                    // Add some items based on the portion of percent that is less than 100%
                    int remainder = (items2.Length * (extraArgs.Percent - wholePercent)).
                        ToInt_Round();

                    addOrder.AddRange(UtilityCore.RandomRange(0, items2.Length, remainder));

                    #endregion
                }
                else
                {
                    #region ignore size, randomly distribute

                    int totalCount = (items2.Length * extraArgs.Percent).
                        ToInt_Round();

                    //NOTE: UtilityCore.RandomRange stops when the list is exhausted, and makes sure not to have dupes.  That's not what is wanted
                    //here.  Just randomly pick X times
                    addOrder.AddRange(Enumerable.Range(0, totalCount).Select(o => rand.Next(items2.Length)));

                    #endregion
                }
            }

            return AddLinks(items1, items2, distances, addOrder, initial);
        }
        /// <summary>
        /// This adds 2s to 1s one at a time (specified by distances2to1_AddOrder)
        /// </summary>
        private static Tuple<int, int>[] AddLinks(LinkItem[] items1, LinkItem[] items2, DistributeDistances distances, IEnumerable<int> distances2to1_AddOrder, Tuple<int, int>[] initial = null)
        {
            // Store the inital link burdens
            BrainBurden[] links = Enumerable.Range(0, items1.Length).
                Select(o => new BrainBurden(o, items1, items2)).
                ToArray();

            if (initial != null)
            {
                #region Store initial

                foreach (var set in initial.ToLookup(o => o.Item1))
                {
                    foreach (int item2Index in set.Select(o => o.Item2))
                    {
                        links[set.Key].AddIOLink(item2Index);
                    }
                }

                #endregion
            }

            foreach (var distanceIO in distances2to1_AddOrder.Select(o => distances.Distances2to1[o]))
            {
                int ioIndex = distanceIO.Index2;
                int closestBrainIndex = distanceIO.DistancesTo1[0].Item1;

                AddIOLink(links, ioIndex, items2[ioIndex].Size, closestBrainIndex, distances.ResistancesItem1[closestBrainIndex]);
            }

            // Build the return
            List<Tuple<int, int>> retVal = new List<Tuple<int, int>>();
            foreach (BrainBurden burden in links)
            {
                retVal.AddRange(burden.IOLinks.Select(o => Tuple.Create(burden.Index, o)));
            }

            return retVal.ToArray();
        }
        private static Tuple<int, int>[] Link12_Distribute(LinkItem[] items1, LinkItem[] items2, DistributeDistances distances)
        {
            IEnumerable<int> addOrder = Enumerable.Range(0, distances.Distances2to1.Length);

            return AddLinks(items1, items2, distances, addOrder);
        }