/// <summary>
    /// Creates a random payload of blocks constrained by the block manager. Payloads are by default
    /// created to be a size of 20 when randomly created
    /// </summary>
    /// <returns></returns>
    public static IndividualDatastructure createRandomPayload(int payloadsize)
    {
        ///So now that we've added our open space, we attempt to insert random blocks
        int count = 0;

        IndividualDatastructure payload = new IndividualDatastructure();
        ///Here we need to init an open space. I want this to be at the centre of the 3D space
        int centre = IndividualManager.Instance.maxIndividualSize / 2;

        ///Calculating the offset of the centre
        double offset = BlockFunctions.calculateOffset(centre, centre, centre);

        payload.openSpaces.Add(offset);

        ///Here we grab the payload type that is tagged as such
        BlockType type = null;

        type = BlockManager.Instance.blockTypes[BlockFunctions.findBlockID("payload")];
        if (type == null)
        {
            throw new Exception("There was no block of type payload defined");
        }

        payloadsize = Math.Min(payloadsize, IndividualManager.Instance.startIndividualSize);
        ///While we have less blocks than desired, and less failed consecutive attempts than defined
        while (count < payloadsize && count < IndividualManager.Instance.startIndividualSize)///This number may need to be tweaked. I feel 200 consecutive failed attempts is enough though
        {
            if (BlockFunctions.insertBlockTypeAtRandom(payload, type))
            {
                count++;
            }
        }
        Debug.Log("Payload created with size of " + count);
        return(payload);
    }
예제 #2
0
    private static void alterPieces(Individual indiv)
    {
        ///For each pass defined by degree of mutation
        for (int i = 0; i < MutationManager.Instance.degreeToMutate; i++)
        {
            List <double> toDelete = new List <double>();
            Dictionary <double, Block> replaceAtWith = new Dictionary <double, Block>();

            ///for each block
            foreach (double b in indiv.hull.container.contents.Keys)
            {
                double rand = Randomizer.random.NextDouble();
                ///WE DO NOT ALTER THE PAYLOAD NOR IGNORED BLOCKS
                if (indiv.payload.container.contents.Keys.Contains(b))
                {
                    continue;
                }
                if (rand < MutationManager.Instance.doNothingProbability)
                {
                    continue;
                }
                rand = Randomizer.random.NextDouble();
                ///If we should alter it
                if (Randomizer.random.NextDouble() < MutationManager.Instance.alterOrDeleteProbability)
                {
                    ///RANDOMIZE BLOCK
                    Block newBlock = BlockFunctions.generateRandomBlock();
                    replaceAtWith.Add(b, newBlock);
                }
                ///or delete it
                else
                {
                    toDelete.Add(b);
                }
            }
            foreach (double b in toDelete)
            {
                indiv.hull.container.openSpaces.Add(b);
                indiv.hull.container.contents.Remove(b);
            }
            foreach (double b in replaceAtWith.Keys)
            {
                indiv.payload.container.contents[b] = replaceAtWith[b];
            }
        }
    }
    /// <summary>
    /// Creates a random payload of blocks constrained by the block manager. Payloads are by default
    /// created to be a size of 20 when randomly created
    /// </summary>
    /// <returns></returns>
    public static IndividualDatastructure createRandomHull(IndividualDatastructure hull, int hullSize)
    {
        int count = 0;

        ///Here i'm making sure that we don't fall into an infinite loop of trying to place blocks when it's not possible
        ///Normally this wouldn't be an issue, but because users can input their own blocks
        ///I need to safeguard against assholes.
        hullSize = Math.Min(hullSize, IndividualManager.Instance.startIndividualSize);
        ///While we have less blocks than desired, and less failed consecutive attempts than defined
        while (count < hullSize && count < IndividualManager.Instance.startIndividualSize)///This number may need to be tweaked. I feel 200 consecutive failed attempts is enough though
        {
            if (BlockFunctions.insertBlockAtRandom(hull))
            {
                count++;
            }
        }
        return(hull);
    }
예제 #4
0
    /// <summary>
    /// Pass in the structure which holds your blocks, as well as the type of block you would like added, and
    /// this will add that block at a random spot to your structure
    /// </summary>
    /// <param name="structure"></param>
    /// <param name="type"></param>
    /// <returns>The altered datastructure, null if failed</returns>
    internal static bool insertBlockTypeAtRandom(IndividualDatastructure structure, BlockType type)
    {
        double openSpace = BlockFunctions.randomOpenSpace(structure.openSpaces);
        ///This is our block
        facing   face   = Randomizer.RandomEnumValue <facing>();
        rotation rot    = Randomizer.RandomEnumValue <rotation>();
        Block    pBlock = new Block(type.UID, face, rot);

        ///If we've gotten to this point, then we can successfully place ourself into the individual

        /*
         * IVE BEEN GETTING AN ERROR WHERE WE TRY TO PLACE BLOCKS THAT ALREADY EXIST.
         * NO IDEA WHY THIS HAPPENS AND IT SHOULDN'T SO I'M SIMPLY PUTTING THIS CONDITIONAL HERE AS A JANK FIX
         */
        if (structure.contents.ContainsKey(openSpace))
        {
            return(false);
        }
        structure.contents.Add(openSpace, pBlock);


        ///Remove the open space from structure.openSpaces
        structure.openSpaces.Remove(openSpace);
        ///Add the possible neighbours of the placed block to our open neighbours list
        List <double> openConsiderations = BlockFunctions.addNeighboursToOpen(openSpace, structure.contents);

        ///Iterating over the open spots we are considering, and check to see if they are already filled or not.
        ///Then adding them to our open spaces list if they are not.

        foreach (double possible in openConsiderations)
        {
            if (structure.contents.ContainsKey(possible))
            {
                continue;
            }
            structure.openSpaces.Add(possible);
        }
        return(true);
    }
예제 #5
0
    private static void addPieces(Individual indiv)
    {
        List <double> insert = new List <double>();

        foreach (double b in indiv.hull.container.openSpaces)
        {
            ///We have already added enough blocks
            if (indiv.hull.container.contents.Count >= IndividualManager.Instance.maxIndividualSize)
            {
                continue;
            }
            if (Randomizer.random.NextDouble() < MutationManager.Instance.additionProbability)
            {
                insert.Add(b);
            }
        }
        ///Doing it this way because we cannot alter a structure while iterating through it
        foreach (double inserting in insert)
        {
            BlockFunctions.insertBlockAtRandom(indiv.hull.container);
        }
    }
    /// <summary>
    /// Places the blocks within this assortment into 3D space
    /// Uses the optimized block creation for deciding whether or not to render a block/ give it a collider
    /// This will also alter the individual by locating the centre of gravity,
    /// creating a block there with a mass of all the un-rendered blocks,
    /// then jointing the centre of gravity with all the rendered blocks.
    /// This also semi-optimizes the addition of the thrusters to the thruster
    /// index in the individual by performing that within the loop we are already doing.
    /// It does the same with the fuel amount.
    /// </summary>
    /// <param name="indiv"></param>
    /// </summary>
    public static GameObject instantiate(Individual passedIN)
    {
        ///Temporary variables for instantiating the Block structure as a unity 3-D object
        BlockManager     blockMan   = BlockManager.Instance;
        List <BlockType> blockTypes = blockMan.blockTypes;
        int     centre       = IndividualManager.Instance.maxIndividualSize / 2;
        float   centreWeight = 0;
        Vector3 COGPosition  = Vector3.zero;
        int     COGWeight    = 0;
        Dictionary <double, Block> contents = passedIN.hull.container.contents;

        GameObject parent = new GameObject();

        parent.transform.position = new Vector3(centre, centre, centre);

        ///Iterate through all our positions/weights to find the centre of gravity
        foreach (double index in contents.Keys)
        {
            int blockWeight = blockTypes[contents[index].type].weight;
            int blockType   = contents[index].type;
            int blockCost   = blockTypes[contents[index].type].weight;

            ///Adding our values to the individual values
            passedIN.weight += blockWeight;
            passedIN.cost   += blockCost;
            if (blockType == BlockFunctions.findBlockID("fuel"))
            {
                passedIN.fuelVolume++;
            }

            ///Create the 3D block
            GameObject created = BlockFunctions.createBlock(index, contents);


            ///Calculate the centre of gravity location
            COGPosition  += (created.transform.position * blockWeight);
            centreWeight += blockWeight;

            ///If creation was allowed, we;
            if (created.GetComponent <MeshRenderer>().enabled)
            {
                ///Additionally, I optimize setting the thruster index here because we are already iterating over each block anyway
                if (contents[index].type == BlockFunctions.findBlockID("thruster"))
                {
                    passedIN.thrusterIndex.Add(created);
                }
                else
                {
                    passedIN.exteriorIndex.Add(created);
                }
                created.transform.SetParent(parent.transform);
            }
            ///If we do not render physically;
            else
            {
                ///Increment the COGWeight
                COGWeight += blockTypes[contents[index].type].weight;
                ///And destroy the block for it
                UnityEngine.Object.Destroy(created);
            }
        }

        ///After doing the physics for each block
        ///make sure our weight is non-zero
        if (passedIN.weight <= 0)
        {
            passedIN.weight = 1;
        }


        ///This is our centre of gravity. Now I need to create a block there, and set it's weight;
        COGPosition = COGPosition / centreWeight;
        parent.transform.position = Vector3.zero;

        Rigidbody rigid = parent.AddComponent <Rigidbody>();

        rigid.centerOfMass = COGPosition;
        rigid.mass         = passedIN.weight;
        rigid.drag         = 0;


        return(parent);
    }