Creating a more consistant, randomly generated, world space for a text-based RPG
<p>Currently, I can create a randomized world within a 2-D array. However, I feel it is too random. Here is the class I'm currently working with:</p>

<p><code>from random import randint, choice, randrange</code></p>

<pre><code>class WorldSpace(object):
    def __init__(self, row, col, world_array):
        self.row = row  # Number of lists to be created.
        self.col = col  # Number of indexes inside of each row.
        self.world_array = world_array
</code></pre>

<p>The <code>WorldSpace</code> method that creates the world:</p>

<pre><code>@classmethod
def generate(cls, autogen):
    print 'Starting world generation...'
    print
    if autogen is True:
        row_amt = 75
        col_amt = 75

    else:
        row_amt = input('Please specify row length of world array.: ')
        col_amt = input('Please specify column length of world array.: ')
        if (row_amt or col_amt) == 0:
            print 'Invalid world values!'
            cls.generateWorld(False)

    world_array = [[' ']*col_amt for _ in xrange(row_amt)]
    print 'Created world...'

    return cls(row_amt, col_amt, world_array)
</code></pre>

<p>A method that modifies the world -- currently only creates <code>forests</code> though in my full segment of code, a series of oceans and mountains are formed as well:</p>

<pre><code>def modify_world(self, autogen):
    if autogen is True:
        # Forests:
        count = randint(6, 10)
        while count &gt; 0:
            a = randint(1, (self.row / randint(2, 6)))
            b = randint(1, (self.col / randint(2, 6)))
            row_val = randint(5, self.row)
            count_val = randint(5, 15)
            self.genLine_WObj(a, b, row_val, 't', count_val)
            count -=1

    print('\n'.join([''.join(['{:1}'.format(item) for item in row])
      for row in self.world_array]))
    inp = input('')
    if inp != '':
        return
</code></pre>

<p>And the method that actually creates the <code>forest</code> tiles:</p>

<pre><code>def genLine_WObj(self, a, b, row_val, char, count):
    # 'genLine_WObj' - Generate Line(like) world object.
    # Used to place lines of certain characters with psuedo-randomized
    # width and length onto the world array.
    while count != 0:
        row_col_dict = {row_val: (a, b)}
        for row in row_col_dict.keys():
            startPos, endPos = row_col_dict[row]

            for i in range(startPos, endPos):
                self.world_array[row][i] = char

        b += choice([0, 1])
        a += choice([0, 0, 0, 0, 1])

        row_val -= 1
        count -= 1
</code></pre>

<p>Now to actually run the program:</p>

<pre><code>world = WorldSpace.generate(True)
world.modify_world(True)
</code></pre>

<p>However, while the works ~20-30% of the time, sometimes it will generate small forests, or small pairs of <code>t</code> characters, when it should be creating forests all around the map.  How can I improve my code to make the randomized generation more consistent? </p>

<p>Fixed:</p>

<ol>
<li>Sometimes your <code>a</code> is bigger than your <code>b</code> and forest is not generated.</li>
<li>All your forests tend to be at the left side of map.</li>
</ol>

<p>Inline comments are added for changed lines.</p>

<pre><code>def modify_world(self, autogen):
    if autogen is True:
        # Forests:
        count = randint(6, 10)
        while count &gt; 0:
            a = randrange(self.col)           # begin of forest
            width = self.col / randint(2, 6)  # initial width of forest
            b = int(a + width)                # end of forest
            row_val = randint(5, self.row)
            count_val = randint(5, 15)
            self.genLine_WObj(a, b, row_val, 't', count_val)
            count -=1

    print('\n'.join([''.join(['{:1}'.format(item) for item in row])
      for row in self.world_array]))
    inp = input('')
    if inp != '':
        return


def genLine_WObj(self, a, b, row_val, char, count):
    # 'genLine_WObj' - Generate Line(like) world object.
    # Used to place lines of certain characters with psuedo-randomized
    # width and length onto the world array.
    while count != 0:
        row_col_dict = {row_val: (a, b)}
        for row in row_col_dict.keys():
            startPos, endPos = row_col_dict[row]

            for i in range(startPos, min(self.col, endPos)):  # added min
                self.world_array[row][i] = char

        b += choice([0, 1])
        a += choice([0, 0, 0, 0, 1])

        row_val -= 1
        count -= 1
</code></pre>

<p>And I would change <code>width</code> of forest to something mapsize-independent. E. g.:</p>

<pre><code>width = randint(2, 15)
</code></pre>

<p>But that depends on your goals.</p>

python arrays python-2.7 oop