1

I am trying to generate a Settlers of Catan game board and am stuck trying to create an efficient implementation of hex numbers.

The goal is to randomly generate a set of numbers from 2-12 (with only one instance of 2 and 12, and two instances of all numbers in between), ensuring that the values 6 and 8 they are not hexagonally (?) adjacent to one another. 6 & 8 are special because they are the numbers you are most likely to roll so the game does not want these next to one another as players get disproportionately higher resources of that kind. A 7 means you have to discard resources.

The expected result: https://i.stack.imgur.com/bAoqB.jpg

Right now I have a working brute force implementation that is very slow and I am hoping to optimize it, but I am not sure how. The implementation is in VBA, which has constrained the data structures I can use.

In pseudo code I am doing something like this:

For Each of the 19 hexes
    Loop Until we have a valid number
        Generate a random number between 1 and 12
        Check
            Have we already placed too many of that number?
            Is the number equal to 6 or 8?
                Is the number being placed on a hex next to another hex with 6 or 8 placed on it?
        If valid
            Place
        If invalid
            Regenerate random number

It's very manual and subject to the random generator function, which means it can be anywhere from being really short to being really really long (compounded over 19 hexes).

Note: How my numbers are being placed seems important. I start at the outside of the gameboard (see here https://i.stack.imgur.com/bAoqB.jpg) on the gray hex with number 6, and then move counter clockwise around the board inward. This means that my next hex is 2 light green, 4 light orange...continuing around to 9 dark green and then coming inwards to 4 light orange.

This pattern limits the number of comparisons I need to make.

tsurantino
  • 1,027
  • 13
  • 27
  • 1
    You might want to mention what is special about 6, 7, and 8. `ensuring that they are not hexagonally (?) adjacent to one another` begs explanation: what `they`? My stab: (pseudo-randomly) choose tiles for numbers with placement restrictions first, the fill up. Fill an array with the numbers/positions to assign; choose a valid index and assign the value at that index; if the index was not the last, assign the last value to the index just used; repeat with shorter array. – greybeard Oct 24 '14 at 08:49
  • 6 & 8 are special because they are the numbers you are most likely to roll so the game does not want these next to one another as players get disproportionately higher resources of that kind. A 7 means you have to discard resources. I understand your implementation but there is a lot of fluidity in where the 6 and 8 (the numbers which would be restricted by your approach) could go if they were unrestricted. Thank you for your answer though. – tsurantino Oct 24 '14 at 08:51
  • Could it be "very slow" because it's running forever? If the last hex to be placed is a 6 or an 8 and it can't go in the last tile... – David Eisenstat Oct 24 '14 at 13:19

2 Answers2

3

There are several optimizations you can do - first of all you know exactly how many numbers are present prom each tile - you have 2,3,3,4,4,5,5,6,6,8,8,9,9,10,10,11,11,12. So start off with this set of numbers - you will eliminate the check if the number has been generated too many times. now you can do a random shuffle of this set of numbers and check if it is "valid". This will still result in too many negative checks I think but it should perform better than your current approach.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • @greybeard not exactly. We need not sort anything. We need just any valid sequence and there is a not so bad chance to hit one(the ratio valid/invalid sequences is not too small but I am lazy to compute it precisely :) ) – Ivaylo Strandjev Oct 24 '14 at 08:55
0

Place the 8 first, calculate which of the remaining tiles you'd be happy to place the 6 on (i.e. non-adjacent), then choose on at random for the 6. Then place the rest.

Dave
  • 7,460
  • 3
  • 26
  • 39