Forum Thread
by member
  Posts  
Random Terrain Generation (Forums : Coding & Scripting : Random Terrain Generation) Locked
Thread Options
Mar 17 2013, 8:46pm Anchor

Now I have another problem. If you could take a look at my generation and tell me what I did wrong or if you see any flaws, basically I want it to generate a chunk which is 128 layers high and each layer needs 80 blocks. For some reason when I use this code some layers randomly have a weird number of blocks. Also I need frequency to be more effective, for instance copper has a frequency of 3 yet it seems to appear quite abundantly in layers but I think that is because I only have about 4 blocks put in right now.

code:
package dhg.client.chunk;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import dhg.client.block.Block;
import dhg.client.block.BlockGrass;

public class ChunkGenerator
{
  public static Map<Integer, List<Block>> generateChunk()
  {
    Map<Integer, List<Block>> layers = new HashMap<Integer, List<Block>>();
    List<Block> layerBlocks;
    Random r = new Random();
   
    for (int i = 0; i < 128; i++)
    {
      layerBlocks = new ArrayList<Block>();
        for (int j = 0; j < Block.getAllBlocks().size(); j++)
        {
          Block temp = Block.getBlockByID(j);
          if (temp.getLayerSpawn() <= i &amp;&amp; temp.getLayerSpawn() <= 128)
          {
            int blocksLeft = 80 / Block.getAllBlocks().size();
            int frequency = r.nextInt(temp.getFrequency() * 2) * blocksLeft;
            for (int g = 0; g < frequency; g++)
            {
              if (layerBlocks.size() < 80)
              {
                layerBlocks.add(temp);
                Collections.shuffle(layerBlocks);
              }
            }
          }
        }
      layers.put(i, layerBlocks);
    }
    return (layers);
  }
}
 

Edited by: ExoNaut

Mar 21 2013, 4:28pm Anchor

Hi ExoNaut,

so you want 128 layers each with 80 block, randomly picked from a block-pool (Block.getAllBlocks()) with a frequency of how much they should appear?
Currently you don't add 80 blocks to each of your layers, the real number is set by the product of Block.getAllBlocks().size() and a random value:

java code:
for (int i = 0; i < 128; i++) // the 128 layers
     {
         for (int j = 0; j < Block.getAllBlocks().size(); j++) // an undefined number
         {
             for (int g = 0; g < frequency; g++) // also an undefined and random number
             {

Instead of Block.getAllBlocks().size() use 80, the value how much blocks you really want to add.
Also if you mean with the frequency-value how often the blocks should be picked, you need to process it in relation to the frequency of all blocks.
For example:

java code:
int iMaxRel = /* TOTAL AMOUNT (Frequ1+Frequ2+Frequ3+...) */
int iCurRel = 0;

int iRand = r.nextInt() % iMaxRel;

int iSelected;
for(iSelected = 0; iSelected < Block.getAllBlocks().size(); iSelected++)
{
    iCurRel += Block.getBlockByID(iSelected).getFrequency();
    if(iRand < iCurRel) break;
}

layerBlocks.add(Block.getBlockByID(iSelected));

It's not the best and it still can be optimized with a different data structure.

Hope it helps.
Best regards
- Martin

Edited by: MausGames

Mar 21 2013, 9:16pm Anchor
MausGames wrote:Hi ExoNaut,

so you want 128 layers each with 80 block, randomly picked from a block-pool (Block.getAllBlocks()) with a frequency of how much they should appear?
Currently you don't add 80 blocks to each of your layers, the real number is set by the product of Block.getAllBlocks().size() and a random value:

java code:
for (int i = 0; i < 128; i++) // the 128 layers
     {
         for (int j = 0; j < Block.getAllBlocks().size(); j++) // an undefined number
         {
             for (int g = 0; g < frequency; g++) // also an undefined and random number
             {

Instead of Block.getAllBlocks().size() use 80, the value how much blocks you really want to add.
Also if you mean with the frequency-value how often the blocks should be picked, you need to process it in relation to the frequency of all blocks.
For example:

java code:
int iMaxRel = /* TOTAL AMOUNT (Frequ1+Frequ2+Frequ3+...) */
int iCurRel = 0;

int iRand = r.nextInt() % iMaxRel;

int iSelected;
for(iSelected = 0; iSelected < Block.getAllBlocks().size(); iSelected++)
{
    iCurRel += Block.getBlockByID(iSelected).getFrequency();
    if(iRand < iCurRel) break;
}

layerBlocks.add(Block.getBlockByID(iSelected));

It's not the best and it still can be optimized with a different data structure.

Hope it helps.
Best regards
- Martin


Alright thanks, the only question I have is how do I used that last bit of code (the frequency) to actually add that many blocks to the layerBlocks?

Mar 22 2013, 7:28am Anchor

Something like this:

java code:
public class ChunkGenerator
{
    public static Map<Integer, List<Block>> generateChunk()
    {
        Map<Integer, List<Block>> layers = new HashMap<Integer, List<Block>>();
        List<Block> layerBlocks;

        Random r = new Random();

        // get max frequency
        int iMaxRel = 0;
        for(int i = 0; i < Block.getAllBlocks().size(); i++)
            iMaxRel += Block.getBlockByID(i).getFrequency();
     
        // traverse layers
        for(int i = 0; i < 128; i++)
        {
            layerBlocks = new ArrayList<Block>();

            // traverse blocks
            for(int j = 0; j < 80; j++)
            {
                int iCurRel = 0;
                int iRand = r.nextInt() % iMaxRel; // random number from 0 to iMaxRel-1

                // select block by frequency
                int iSelected;
                for(iSelected = 0; iSelected < Block.getAllBlocks().size(); iSelected++)
                {
                    iCurRel += Block.getBlockByID(iSelected).getFrequency();
                    if(iRand < iCurRel) break;
                }

                // add selected block
                layerBlocks.add(Block.getBlockByID(iSelected));
            }
            layers.put(i, layerBlocks);
        }
        return (layers);
    }
 }

Best regards
- Martin

Edited by: MausGames

Mar 22 2013, 5:59pm Anchor

Thank you very much

Now the problem seems to be that even though dirt is at a frequency of 1, and stone at 25 dirt appears more often than stone.

Mar 23 2013, 7:19am Anchor

Debug it step by step, monitor the variables, try to understand what's happening and find strange behaviors.

Reply to Thread
click to sign in and post

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.