Hexagon Generation

2

Answers

  • another approach:

    1. for all fields (in a random order!!!!!)

    check fields

    • if occupied ignore
    • empty: continue here:

    check neighbours change random color

    if neigbour color found, * set same color * move on with step 0. ELSE * if all neighbours are empty * choose random color (which must be a NEW color (not used yet)) * (if there's no new color, skip and goto 0)


    But then he fills all with one color He needs to stop and start new

    min. 5 fields per color, max. color = ?

  • 1, 29, 40, 46 249 to 252 296 to 299

  • Excuse, what do you mean by that?

  • edited March 2018

    the lines numbers that i added 1 = line 1

  • Chrisir i am having a little trouble understanding your code it fells a level above me. Can you explain it to me so that way i can understand it better.

    here's the code ▼

      // RESET 
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        TileColors[TE] = 1; // not OCEAN
      }
    
    
      // attempts
      for (int i = 1; i < 13; i++) {
    
        // new group of Type startingNewGroupType : loop over types of hexagon :
        // starting with 1 = NO ocean 
        for (int startingNewGroupType = 1; startingNewGroupType < 4; startingNewGroupType++) {
    
          int startingNewGroupWhere = int (random(AmountOfTiles));
    
          TileColors[startingNewGroupWhere] = startingNewGroupType;
    
          // going down and up
          int from =  -int(random(4, 12));
          int to   =   int(random(4, 12));  
          for (int i2 = from; i2 < to; i2++) {
            int newFieldIndex= startingNewGroupWhere + i2; 
            if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
              TileColors[newFieldIndex] = startingNewGroupType;
    
            // for each new field going left and right 
            from =  -int(random(4, 12));
            to   =   int(random(4, 12));  
            for (int i3 = from; i3 < to; i3++) {
              if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                TileColors[newFieldIndex + i3*29] = startingNewGroupType;
            }
          }
        }
        //
      }//for
    
      // 
    
      //add ocean
      int startingNewGroupType = 0;
    
      float xPrev=-10000;
      float yPrev=-10000;
    
      // attempts
      for (int i4 = 1; i4 < 12; i4++) {
    
        int startingNewGroupWhere = indexOfExistingOcean(); // find old ocean tile
    
        if ( startingNewGroupWhere==-1)
          startingNewGroupWhere= int (random(AmountOfTiles));
    
        TileColors[startingNewGroupWhere] = startingNewGroupType;
    
        if (random(100) > 90) {
    
          // random walker / river 
    
          int newFieldIndex = startingNewGroupWhere  -1; 
          int direction = int(random(4));
    
          // attempts
          for (int i = 1; i < 293; i++) {
    
            if (random(100)>60) 
              direction = int(random(4)); 
    
            switch (direction) {
            case 0: //north
              newFieldIndex = startingNewGroupWhere  -1; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 1: //east 
              newFieldIndex= startingNewGroupWhere + 29; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 2: //south 
              newFieldIndex= startingNewGroupWhere + 1; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 3: //west 
              newFieldIndex= startingNewGroupWhere - 29; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
            }
            startingNewGroupWhere=newFieldIndex;
          }
        }
    
        //---
    
        else
        {
          // Lake 
    
          // going down and up
          int from =  -int(random(4, 12));
          int to   =   int(random(4, 12));  
          for (int i2 = from; i2 < to; i2++) {
    
            int newFieldIndex= startingNewGroupWhere + i2;
    
            if (newFieldIndex >= 0 && 
              newFieldIndex < AmountOfTiles && 
              dist(xPrev, yPrev, XColmns[newFieldIndex], YColmns[newFieldIndex]) < 66 ) {
    
              TileColors[newFieldIndex] = startingNewGroupType;
    
              // for each new field going left and right 
              from =  -int(random(4, 12));
              to   =   int(random(4, 12));  
              for (int i3 = from; i3 < to; i3++) {
                if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                  TileColors[newFieldIndex + i3*29] = startingNewGroupType;
              }
            }
          }//for
    
          xPrev=XColmns[startingNewGroupWhere];
          yPrev=YColmns[startingNewGroupWhere];
        }//else 
        //
      }//for
    
      //
    } // setup end
    
    // ------------------------------------------------------------------------
    
    int indexOfExistingOcean() {
    
      //
      ArrayList<Integer> indices = new ArrayList(); 
    
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        if (TileColors[TE] == 0) { //  OCEAN
          //
          indices.add (TE); 
          //
        }//if
      }//for
    
      if (indices.size()==0) {
        return -1;
      } 
      int randomNumber = int(random(indices.size())); 
      return indices.get(randomNumber); 
    
  • Apologies, I don’t have the time....

  • edited March 2018

    okay, maybe later you can do it please.

  • No, I don't think so

  • Okay that's all right anyways.

  • Chrisir having trouble working out how to make it where when the mouse is pressed on a hexagon a ellipse called character would move into that hexagons x and y.

  • I see

    Do you have the center of the hexagon?

    Then use if(dist(mouseX,mouseY, centerX,centerY) <44) .... or some value for 44 being the radius

    Then store the data that this ellipse carries a character. Or just store the index of the hexagon and show the character using the data of the hexagon in the array with the character index

    Eg in function mousePressed you for loop i over the array and check if (dist( as above if true set indexCharacter to i

  • I see

    Do you have the center of the hexagon?

    Then use if(dist(mouseX,mouseY, centerX,centerY) <44) .... or some value for 44 being the radius

    Then store the data that this ellipse carries a character. Or just store the index of the hexagon and show the character using the data of the hexagon in the array with the character index

    Eg in function mousePressed you for loop i over the array and check if (dist( as above if true set indexCharacter to i

  • edited April 2018

    I'm having some trouble with the y value in hexagon for some reason it doesn't want to change when i press in the hexagons but the x works fine Any suggestions.

    Chrisir i think that the code you gave me was for a area of a circle if it was pressed in the area but is it possible to do it for the area of a hexagon for. here's the code

    float [] XColmns;
    float [] YColmns;
    
    float [] ColorR;
    float [] ColorG;
    float [] ColorB;
    
    int [] TileColors;
    int [] TileColorChance;
    
    int AmountOfTiles = 1131;
    int Seed = round(random(1000000000));
    float CharPosX, CharPosY;
    
    ////////////////////////////////////////////////////////////////////////////
    
    void setup() {
    
      size(975, 830);
    
      println("Seed:  "+Seed);
      randomSeed(Seed);
    
      XColmns = new float[AmountOfTiles];
      YColmns = new float[AmountOfTiles];
      ColorR = new float[AmountOfTiles];
      ColorG = new float[AmountOfTiles];
      ColorB = new float[AmountOfTiles];
      TileColors = new int[AmountOfTiles];
      TileColorChance = new int[AmountOfTiles];
    
    
      for (int c = 0; c < 39; c++) {
    
        if ((int)c%2==0) {   
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 30 + N * 27;
          }
        } else { 
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 43 + N * 27;
          }
        }
      }
    
      // RESET 
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        TileColors[TE] = 1; // not OCEAN
      }
    
    
      // attempts
      for (int i = 1; i < 13; i++) {
    
        // new group of Type startingNewGroupType : loop over types of hexagon :
        // starting with 1 = NO ocean 
        for (int startingNewGroupType = 1; startingNewGroupType < 4; startingNewGroupType++) {
    
          int startingNewGroupWhere = int (random(AmountOfTiles));
    
          TileColors[startingNewGroupWhere] = startingNewGroupType;
    
          // going down and up
          int from =  -int(random(4, 12));
          int to   =   int(random(4, 12));  
          for (int i2 = from; i2 < to; i2++) {
            int newFieldIndex= startingNewGroupWhere + i2; 
            if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
              TileColors[newFieldIndex] = startingNewGroupType;
    
            // for each new field going left and right 
            from =  -int(random(4, 12));
            to   =   int(random(4, 12));  
            for (int i3 = from; i3 < to; i3++) {
              if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                TileColors[newFieldIndex + i3*29] = startingNewGroupType;
            }
          }
        }
        //
      }//for
    
      // 
    
      //add ocean
      int startingNewGroupType = 0;
    
      float xPrev=-10000;
      float yPrev=-10000;
    
      // attempts
      for (int i4 = 1; i4 < 12; i4++) {
    
        int startingNewGroupWhere = indexOfExistingOcean(); // find old ocean tile
    
        if ( startingNewGroupWhere==-1)
          startingNewGroupWhere= int (random(AmountOfTiles));
    
        TileColors[startingNewGroupWhere] = startingNewGroupType;
    
        if (random(100) > 90) {
    
          // random walker / river 
    
          int newFieldIndex = startingNewGroupWhere  -1; 
          int direction = int(random(4));
    
          // attempts
          for (int i = 1; i < 293; i++) {
    
            if (random(100)>60) 
              direction = int(random(4)); 
    
            switch (direction) {
            case 0: //north
              newFieldIndex = startingNewGroupWhere  -1; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 1: //east 
              newFieldIndex= startingNewGroupWhere + 29; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 2: //south 
              newFieldIndex= startingNewGroupWhere + 1; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 3: //west 
              newFieldIndex= startingNewGroupWhere - 29; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
            }
            startingNewGroupWhere=newFieldIndex;
          }
        }
    
        //---
    
        else
        {
          // Lake 
    
          // going down and up
          int from =  -int(random(4, 12));
          int to   =   int(random(4, 12));  
          for (int i2 = from; i2 < to; i2++) {
    
            int newFieldIndex= startingNewGroupWhere + i2;
    
            if (newFieldIndex >= 0 && 
              newFieldIndex < AmountOfTiles && 
              dist(xPrev, yPrev, XColmns[newFieldIndex], YColmns[newFieldIndex]) < 66 ) {
    
              TileColors[newFieldIndex] = startingNewGroupType;
    
              // for each new field going left and right 
              from =  -int(random(4, 12));
              to   =   int(random(4, 12));  
              for (int i3 = from; i3 < to; i3++) {
                if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                  TileColors[newFieldIndex + i3*29] = startingNewGroupType;
              }
            }
          }//for
    
          xPrev=XColmns[startingNewGroupWhere];
          yPrev=YColmns[startingNewGroupWhere];
        }//else 
        //
      }//for
    
      ////////////////////////////////////////////////////////////////////////////
                                              // new code here
        CharPosX = XColmns[round(random(0, AmountOfTiles))];
        CharPosY = YColmns[round(random(0, AmountOfTiles))];
      ////////////////////////////////////////////////////////////////////////////
                                              //new code ends here 
       } // setup end
    
    // ------------------------------------------------------------------------
    
    int indexOfExistingOcean() {
    
      //
      ArrayList<Integer> indices = new ArrayList(); 
    
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        if (TileColors[TE] == 0) { //  OCEAN
          //
          indices.add (TE); 
          //
        }//if
      }//for
    
      if (indices.size()==0) {
        return -1;
      } 
      int randomNumber = int(random(indices.size())); 
      return indices.get(randomNumber); 
      //
    }//func 
    
    ////////////////////////////////////////////////////////////////////////////
    
    void draw() {
    
      background(226, 185, 108);
    
      //table
      fill(89, 60, 5);  
      // ellipse(-260, -330, 1500, 1500);
    
      //black board
      fill(0);
      stroke(108, 67, 4);
      strokeWeight(1);
      //rect(0, 0, width, height);
    
      for (int i = 0; i < AmountOfTiles; i++) {
        Hexagon(XColmns[i], YColmns[i], 14, TileColors[i]);
      }
    
      fill(255, 0, 25);
      ellipse(CharPosX, CharPosY, 10, 10);
    } // end of draw
    
    ////////////////////////////////////////////////////////////////////////////
    
    void Hexagon (float x, float y, float S, float ColorSelecter) { 
      noFill(); 
      //Ocean
      if (ColorSelecter == 0)         fill(16, 0, 165);
      //Grassland
      else if (ColorSelecter == 1)    fill(81, 175, 14);
      //Jungle
      else if (ColorSelecter == 2)    fill(27, 157, 2);
      //Pond
      else if (ColorSelecter == 3)    fill(1, 116, 147); 
      // Error 
      else                            println ("Error ColorSelecter "+ColorSelecter);
    
    ////////////////////////////////////////////////////////////////////////////
                                                 //new code here                                        
      if (mousePressed && dist(mouseX, mouseY, x+S/2, y+S/2) < S)    CharPosX = x;  CharPosY = y;
      ////////////////////////////////////////////////////////////////////////////
                                             //new code ends here                                                 
    
          noStroke();
          beginShape();
      for (int i=0; i<6; i++) {
        float angle = i * 2 * PI / 6;
        vertex(x + S*cos(angle), y + S*sin(angle));
      }
      endShape(CLOSE);
    
    }//function
    
  • Circle is very similar to an hexagon

    Just make the ...<value smaller in the if dist line

    Is your x,y the center or upper left corner of hexagon?

  • That could be a source of error

  • edited April 2018

    Yes i -1 the size in the dist(); and it was that i had no brackets which the second line of code that is run in that if statement was buggy. To fix it i just added brackets at the start and the end of the statement. Thanks for your suggestions it help a lot.

  • edited April 2018

    Does it work now?

    you should hit ctrl-t more often in processing

    what is your goal in this sketch? A game?

    distribute the initial colors

    to distribute the initial colors you could like start each color in different random spots in the map. Then in a second step fill the wholes (empty fields) by connecting it.

  • you had a missing closing bracket } here

      ////////////////////////////////////////////////////////////////////////////
      //new code here                                        
      if (mousePressed && dist(mouseX, mouseY, x+S/2, y+S/2) < S) {  
        CharPosX = x;  
        CharPosY = y;
      }  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here                                                 
    
  • Yah it works. no i was just trying to learn some different concepts since i'm sort of new to this stuff ;) . Yep that was the spot. Chrisir how would you make like a AI person that moved around but only in the center of different hexagons. For example it can move forward a tile back a tile or left to right one tile etc..

  • float [] XColmns;
    float [] YColmns;
    
    float [] ColorR;
    float [] ColorG;
    float [] ColorB;
    
    int [] TileColors;
    int [] TileColorChance;
    
    int AmountOfTiles = 1131;
    
    int AI_Walker_Position = int (AmountOfTiles / 2);   
    
    int Seed = round(random(1000000000));
    float CharPosX, CharPosY;
    
    ////////////////////////////////////////////////////////////////////////////
    
    void setup() {
    
      size(975, 830);
    
      println("Seed:  "+Seed);
      randomSeed(Seed);
    
      XColmns = new float[AmountOfTiles];
      YColmns = new float[AmountOfTiles];
      ColorR = new float[AmountOfTiles];
      ColorG = new float[AmountOfTiles];
      ColorB = new float[AmountOfTiles];
      TileColors = new int[AmountOfTiles];
      TileColorChance = new int[AmountOfTiles];
    
    
      for (int c = 0; c < 39; c++) {
    
        if ((int)c%2==0) {   
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 30 + N * 27;
          }
        } else { 
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 43 + N * 27;
          }
        }
      }
    
      // RESET 
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        TileColors[TE] = 1; // not OCEAN
      }
    
    
      // attempts
      for (int i = 1; i < 13; i++) {
    
        // new group of Type startingNewGroupType : loop over types of hexagon :
        // starting with 1 = NO ocean 
        for (int startingNewGroupType = 1; startingNewGroupType < 4; startingNewGroupType++) {
    
          int startingNewGroupWhere = int (random(AmountOfTiles));
    
          TileColors[startingNewGroupWhere] = startingNewGroupType;
    
          // going down and up
          int from =  -int(random(4, 12));
          int to   =   int(random(4, 12));  
          for (int i2 = from; i2 < to; i2++) {
            int newFieldIndex= startingNewGroupWhere + i2; 
            if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
              TileColors[newFieldIndex] = startingNewGroupType;
    
            // for each new field going left and right 
            from =  -int(random(4, 12));
            to   =   int(random(4, 12));  
            for (int i3 = from; i3 < to; i3++) {
              if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                TileColors[newFieldIndex + i3*29] = startingNewGroupType;
            }
          }
        }
        //
      }//for
    
      // 
    
      //add ocean
      int startingNewGroupType = 0;
    
      float xPrev=-10000;
      float yPrev=-10000;
    
      // attempts
      for (int i4 = 1; i4 < 12; i4++) {
    
        int startingNewGroupWhere = indexOfExistingOcean(); // find old ocean tile
    
        if ( startingNewGroupWhere==-1)
          startingNewGroupWhere= int (random(AmountOfTiles));
    
        TileColors[startingNewGroupWhere] = startingNewGroupType;
    
        if (random(100) > 90) {
    
          // random walker / river 
    
          int newFieldIndex = startingNewGroupWhere  -1; 
          int direction = int(random(4));
    
          // attempts
          for (int i = 1; i < 293; i++) {
    
            if (random(100)>60) 
              direction = int(random(4)); 
    
            switch (direction) {
            case 0: //north
              newFieldIndex = startingNewGroupWhere  -1; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 1: //east 
              newFieldIndex= startingNewGroupWhere + 29; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 2: //south 
              newFieldIndex= startingNewGroupWhere + 1; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
    
            case 3: //west 
              newFieldIndex= startingNewGroupWhere - 29; 
              if (newFieldIndex >= 0 && newFieldIndex < AmountOfTiles) 
                TileColors[newFieldIndex] = startingNewGroupType;
              break;
            }
            startingNewGroupWhere=newFieldIndex;
          }
        }
    
        //---
    
        else
        {
          // Lake 
    
          // going down and up
          int from =  -int(random(4, 12));
          int to   =   int(random(4, 12));  
          for (int i2 = from; i2 < to; i2++) {
    
            int newFieldIndex= startingNewGroupWhere + i2;
    
            if (newFieldIndex >= 0 && 
              newFieldIndex < AmountOfTiles && 
              dist(xPrev, yPrev, XColmns[newFieldIndex], YColmns[newFieldIndex]) < 66 ) {
    
              TileColors[newFieldIndex] = startingNewGroupType;
    
              // for each new field going left and right 
              from =  -int(random(4, 12));
              to   =   int(random(4, 12));  
              for (int i3 = from; i3 < to; i3++) {
                if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                  TileColors[newFieldIndex + i3*29] = startingNewGroupType;
              }
            }
          }//for
    
          xPrev=XColmns[startingNewGroupWhere];
          yPrev=YColmns[startingNewGroupWhere];
        }//else 
        //
      }//for
    
      ////////////////////////////////////////////////////////////////////////////
      // new code here
      CharPosX = XColmns[round(random(0, AmountOfTiles))];
      CharPosY = YColmns[round(random(0, AmountOfTiles))];
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here
    } // setup end
    
    // ------------------------------------------------------------------------
    
    int indexOfExistingOcean() {
    
      //
      ArrayList<Integer> indices = new ArrayList(); 
    
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        if (TileColors[TE] == 0) { //  OCEAN
          //
          indices.add (TE); 
          //
        }//if
      }//for
    
      if (indices.size()==0) {
        return -1;
      } 
      int randomNumber = int(random(indices.size())); 
      return indices.get(randomNumber); 
      //
    }//func 
    
    ////////////////////////////////////////////////////////////////////////////
    
    void draw() {
    
      background(226, 185, 108);
    
      //table
      fill(89, 60, 5);  
      // ellipse(-260, -330, 1500, 1500);
    
      //black board
      fill(0);
      stroke(108, 67, 4);
      strokeWeight(1);
      //rect(0, 0, width, height);
    
      for (int i = 0; i < AmountOfTiles; i++) {
        Hexagon(XColmns[i], YColmns[i], 14, TileColors[i]);
        if (i==AI_Walker_Position) {
          fill(255, 0, 255);
          ellipse(XColmns[i], YColmns[i], 10, 10);
        }//if
      }//for
    
      move_AI();
    
      fill(255, 0, 25);
      ellipse(CharPosX, CharPosY, 10, 10);
    } // end of draw
    
    ////////////////////////////////////////////////////////////////////////////
    
    void Hexagon (float x, float y, 
      float S, 
      float ColorSelecter) { 
    
    
      noFill(); 
      //Ocean
      if (ColorSelecter == 0)   
        fill(16, 0, 165);
      //Grassland
      else if (ColorSelecter == 1) 
        fill(81, 195, 14);
      //Jungle
      else if (ColorSelecter == 2) 
        fill(27, 157, 2);
      //Pond
      else if (ColorSelecter == 3)   
        fill(1, 116, 147); 
      // Error 
      else                          
      println ("Error ColorSelecter "
        +ColorSelecter);
    
      ////////////////////////////////////////////////////////////////////////////
      //new code here                                        
      if (mousePressed && dist(mouseX, mouseY, x+S/2, y+S/2) < S) {  
        CharPosX = x;  
        CharPosY = y;
      }
    
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here                                                 
    
      noStroke();
      beginShape();
      for (int i=0; i<6; i++) {
        float angle = i * 2 * PI / 6;
        vertex(x + S*cos(angle), y + S*sin(angle));
      }
      endShape(CLOSE);
    }//function
    
    void move_AI() {
    
      // for AI_Walker_Position
    
      int direction=0;
    
      if (random(100)>90) 
        direction = int(random(4));
      else return; 
    
      // print(direction);
    
      switch (direction) {
      case 0: //north
        AI_Walker_Position = AI_Walker_Position  - 1; 
        break;
    
      case 1: //east 
        AI_Walker_Position= AI_Walker_Position + 29; 
        break;
    
      case 2: //south 
        AI_Walker_Position = AI_Walker_Position + 1; 
        break;
    
      case 3: //west 
        AI_Walker_Position= AI_Walker_Position - 29; 
        break;
    
      default: 
        println("Error 322");
        break;
      }//switch 
    
      // check 
      if (AI_Walker_Position < 0) 
        AI_Walker_Position=AmountOfTiles; 
    
      if (AI_Walker_Position >= AmountOfTiles) 
        AI_Walker_Position=0;
    }
    //
    
  • edited April 2018

    Wow that's great i thought that you had to do some like the code below just didn't now how to do it.

      case 0: //north
        AI_Walker_Position = AI_Walker_Position  - 1; 
        break;
    
      case 1: //east 
        AI_Walker_Position= AI_Walker_Position + 29; 
        break;
    
      case 2: //south 
        AI_Walker_Position = AI_Walker_Position + 1; 
        break;
    
      case 3: //west 
        AI_Walker_Position= AI_Walker_Position - 29; 
        break;
    
  • Well, it's absolutely the same principle we use in lines 106 to 146 above which shows that you never really read or understood them...?

  • O yeah i didn't see that Wow. what does case do in the code is it like the condition.

  • edited April 2018

    case?

    see reference

    yeah condition like ==

    https://www.processing.org/reference/switch.html

  • edited April 2018

    Okay thanks. Wow Chrisir the case statement and the if statement condition are very similar now i know thanks a lot this is ground breaking stuff.

  • Chrisir how would you add the noise function for the hexagon generation. From what i understand it makes smoother generation.

  • are you talking of how to distribute the colors to our hexagons?

    it makes smoother generation.

    please understand that above we have a process with several steps:

    • reset

    • place colors except ocean/water

    • add water as rivers (going thin in one random direction) OR lakes (more into an area, into all directions)

    That's why the water looks totally different than the other colors.

    For noise()

    for noise() see reference and here:

    https://forum.processing.org/two/discussion/27719/looping-perlin-noise

    The problem I see is that one condition you have is that you want all hexagons of one color to be connected. So one color is always ONE area / patch and not several patches. Not to easy with noise().

  • edited April 2018

    Okay thanks, but is it easy to generate the base colors say ocean and grassland in noise then generate on top of the grassland random patches of trees in other code not noise.

  • Okay thanks i am going to try to do this now.

  • edited April 2018

    I think you need to define more clearly what you don't like about the current way the colors are distributed

    Does the hexagons of ONE color really be connected? So they are ONE patch and not divided into 3 patches or so?

  • What does that change Chrisir.

  • edited April 2018

    very philosophical. It would help us if you would answer this.

  • new version for color distribution

    float [] XColmns;
    float [] YColmns;
    
    float [] ColorR;
    float [] ColorG;
    float [] ColorB;
    
    int [] TileColors;
    //int [] TileColorChance;
    
    int AmountOfTiles = 1131;
    
    int AI_Walker_Position = int (AmountOfTiles / 2);   
    
    int Seed = round(random(1000000000));
    float CharPosX, CharPosY;
    
    int direction=0;
    
    ////////////////////////////////////////////////////////////////////////////
    
    void setup() {
    
      size(975, 830);
    
      println("Seed:  "+Seed);
      randomSeed(Seed);
    
      XColmns = new float[AmountOfTiles];
      YColmns = new float[AmountOfTiles];
      ColorR = new float[AmountOfTiles];
      ColorG = new float[AmountOfTiles];
      ColorB = new float[AmountOfTiles];
      TileColors = new int[AmountOfTiles];
      // TileColorChance = new int[AmountOfTiles];
    
    
      // make hexagon positions
      for (int c = 0; c < 39; c++) {
    
        if ((int)c%2==0) {   
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 30 + N * 27;
          }
        } else { 
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 43 + N * 27;
          }
        }
      }
    
      // -----------
    
      // RESET colors
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        TileColors[TE] = -1; // not defined
      }
    
      // -----------
    
      // add patches 
      patches();
    
      // -----------
    
      // fill gaps between patches
      // attempts
      for (int c2 = 0; c2 < 139; c2++) {
    
        IntList array1 = new IntList();
        for (int c3 = 0; c3 < AmountOfTiles; c3++) {
          array1.append(c3);
        }
        array1.shuffle(); 
    
        // fill gaps between patches 
        for (int c4 = 0; c4 < AmountOfTiles; c4++) {
          int c = array1.get(c4); 
          if (TileColors[c] == -1) {
            int type1 = getNeighbours(c);
            if (type1 != -1)
              TileColors[c] = type1;
          }//if
        }//for
      }//for
      // -----------
    
      // 
      // -----------
      // add ocean but then (maybe) you need to skip ocean above (starting for loop at 1)
      // addOcean(); 
    
      ////////////////////////////////////////////////////////////////////////////
      // new code here
      CharPosX = XColmns[round(random(0, AmountOfTiles))];
      CharPosY = YColmns[round(random(0, AmountOfTiles))];
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here
    } // setup end
    
    // ------------------------------------------------------------------------
    
    int getNeighbours(int index1) {
    
      if (index1-1 > 0 && TileColors[index1-1]  != -1 && !tooFar(index1, index1-1))
        return TileColors[index1-1] ;
    
      if (index1+1 < AmountOfTiles && TileColors[index1+1]  != -1&& !tooFar(index1, index1+1))
        return TileColors[index1+1] ;
    
    
      if (index1-29 > 0 &&  TileColors[index1-29]  != -1&& !tooFar(index1, index1-29))
        return TileColors[index1-29] ;
    
      if (index1+29 < AmountOfTiles &&  TileColors[index1+29]  != -1&& !tooFar(index1, index1+29))
        return TileColors[index1+29] ;
    
      int v=30;
      if (index1-v > 0 &&  TileColors[index1-v]  != -1&& !tooFar(index1, index1-v))
        return TileColors[index1-v] ;
    
      if (index1+v < AmountOfTiles &&  TileColors[index1+v]  != -1&& !tooFar(index1, index1+v))
        return TileColors[index1+v] ;
    
      // fail 
      return -1;
    }
    
    
    boolean tooFar(int ind1, int ind2) {
    
      return dist(XColmns[ind1], YColmns[ind1], 
        XColmns[ind2], YColmns[ind2]) >= 66;
    }
    
    void patches() {
    
      float xPrev=-10000;
      float yPrev=-10000;
    
      // attempts
      //for (int i = 1; i < 13; i++) {
    
      // new group of Type startingNewGroupType : loop over types of hexagon :
      // starting with 1 = NO ocean 
      for (int startingNewGroupType = 0; startingNewGroupType < 4; startingNewGroupType++) {
    
        // making a ***patch*** of color  
    
        int startingNewGroupWhere = int (random(AmountOfTiles));
    
        TileColors[startingNewGroupWhere] = startingNewGroupType;
    
        // going down and up from there 
        int from =  -int(random(4, 7));
        int to   =   int(random(4, 7));  
    
        for (int i2 = from; i2 < to; i2++) {
    
          int newFieldIndex= startingNewGroupWhere + i2; 
          if (newFieldIndex >= 0 && 
            newFieldIndex < AmountOfTiles && 
            dist(xPrev, yPrev, XColmns[newFieldIndex], YColmns[newFieldIndex]) < 66 ) { 
    
            TileColors[newFieldIndex] = startingNewGroupType;
    
            // for each new field going left and right 
            from =  -int(random(4, 7));
            to   =   int(random(4, 7));  
            for (int i3 = from; i3 < to; i3++) {
              if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                TileColors[newFieldIndex + i3*29] = startingNewGroupType;
            }//for
          }//if
    
          xPrev=XColmns[startingNewGroupWhere];
          yPrev=YColmns[startingNewGroupWhere];
        }//for
      }//for 
      //
      // }//for attempts
    }
    
    ////////////////////////////////////////////////////////////////////////////
    
    void draw() {
    
      background(226, 185, 108);
    
      //table
      fill(89, 60, 5);  
      // ellipse(-260, -330, 1500, 1500);
    
      //black board
      fill(0);
      stroke(108, 67, 4);
      strokeWeight(1);
      //rect(0, 0, width, height);
    
      for (int i = 0; i < AmountOfTiles; i++) {
        Hexagon(XColmns[i], YColmns[i], 14, TileColors[i]);
        if (i==AI_Walker_Position) {
          fill(255, 0, 255);
          ellipse(XColmns[i], YColmns[i], 10, 10);
        }//if
      }//for
    
      move_AI();
    
      fill(255, 0, 25);
      ellipse(CharPosX, CharPosY, 10, 10);
    } // end of draw
    
    ////////////////////////////////////////////////////////////////////////////
    
    void Hexagon (float x, float y, 
      float S, 
      float ColorSelecter) { 
    
      noFill(); 
      //Ocean
      if (ColorSelecter == 0)   
        fill(16, 0, 165);
      //Grassland
      else if (ColorSelecter == 1) 
        fill(81, 195, 14);
      //Jungle
      else if (ColorSelecter == 2) 
        fill(27, 157, 2);
      //Pond
      else if (ColorSelecter == 3)   
        fill(1, 116, 147); 
      // Error 
      else                         
      println ("Error ColorSelecter "
        +ColorSelecter);
    
      ////////////////////////////////////////////////////////////////////////////
      //new code here                                        
      if (mousePressed && dist(mouseX, mouseY, x+S/2, y+S/2) < S) {  
        CharPosX = x;  
        CharPosY = y;
      }
    
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here                                                 
    
      noStroke();
      beginShape();
      for (int i=0; i<6; i++) {
        float angle = i * 2 * PI / 6;
        vertex(x + S*cos(angle), y + S*sin(angle));
      }
      endShape(CLOSE);
    }//function
    
    void move_AI() {
    
      // for AI_Walker_Position
    
      int testDirection;
    
      if (random(100)>90) {
        int prevDirection = direction;
        testDirection = int(random(4));
    
        // to go back and forth is not allowed
    
        if (prevDirection ==  0 && testDirection == 2) 
          return;
        if (prevDirection ==  2 && testDirection == 0) 
          return;
    
        if (prevDirection ==  1 && testDirection == 3) 
          return;
    
        if (prevDirection ==  3 && testDirection == 1) 
          return;
      } else {
        return;
      }
    
      direction = testDirection; 
    
      switch (direction) {
      case 0: //north
        AI_Walker_Position = AI_Walker_Position  - 1; 
        break;
    
      case 1: //east 
        AI_Walker_Position= AI_Walker_Position + 29; 
        break;
    
      case 2: //south 
        AI_Walker_Position = AI_Walker_Position + 1; 
        break;
    
      case 3: //west 
        AI_Walker_Position= AI_Walker_Position - 29; 
        break;
    
      default: 
        println("Error 322");
        break;
      }//switch 
    
      // check 
      if (AI_Walker_Position < 0) 
        AI_Walker_Position=AmountOfTiles; 
    
      if (AI_Walker_Position >= AmountOfTiles) 
        AI_Walker_Position=0;
    }
    //
    
  • edited April 2018

    Sorry for late response life gets busy as you know. Wow that looks great though and i appreciate the comments it helps to understand the code. I agree on ocean code in setup the new code is better.

  • edited April 2018

    This is the 2D array i have been working on last night.

        //can change the size of the hexagons
        int divider = 10;
        int cols = round(width*5.6/divider);
        int rows = round(height*4.55/divider);
        int Colm;
    
        void setup() {
    
        size(900, 830);
    
        // Declare 2D HexArray 
        int[][] HexArray = new int[cols][rows];
    
        // Initialize 2D HexArray values
        for (int C = 0; C < cols; C++) {
          for (int R = 0; R < rows; R++) {
            HexArray[C][R] = int(random(100));
          }
        }
    
        // Draw Hexagons with color
        for (int C = 0; C < cols; C++) {
          for (int R = 0;  R < rows; R++) {
            stroke(HexArray[C][R]);
            fill(HexArray[C][R]);
            if ((int)C % 2 == 0) {
              Colm = 0;
            } else {
              Colm = divider-divider/10;
              }
    
            Hexagon(divider + C * (divider-divider/5) * 2, divider + Colm + R * (divider-divider/10) * 2, divider);
          }
        }
    
        }//end of void setup
    
        void Hexagon(float x, float y, float S) {
          noStroke();
          beginShape();
          for (int i=0; i<6; i++) {
            float angle = i * 2 * PI / 6;
            vertex(x + S*cos(angle), y + S*sin(angle));
          }
          endShape(CLOSE);
        }
    
  • I agree on ocean code in setup the new code is better.

    No, it’s just another version / outcome, not better. It depends from what you want.

    In this Version ocean is treated like forest just a normal patch.

    In the previous version, water was superimposed over all the other patches and therefore making a more complex pattern with rivers and lakes.

    Do you think you can answer my questions above?

  • I think you need to define more clearly what you don't like about the current way the colors are distributed

    Well i was just seeing if we could get smoother terrain generation because i was looking at examples of noise generation and then i saw this one here's the link to it studio.sketchpad.cc/sp/pad/view/ro.ALuTIcV$K3D/rev.28.

    Does the hexagons of ONE color really be connected? So they are ONE patch and not divided into 3 patches or so?

    Not to sure what you mean here but by one color do you mean having multiple colors inside a hexagon?

  • but by one color do you mean having multiple colors inside a hexagon?

    No, I mean if you have one patch of forest is it allowed to have another patch somewhere else, ***not connected to the first patch?

    Also is this part of a game or project you’re planning? What kind?

  • edited April 2018

    Now i understand yes it is allowed to have multiple patches in different places.

    Its kind of a game that i am trying to make. But i ran into some problems with the hexagon generation code.

    Sorry i should have been more clearer at the start with this. I was just trying to code as much as possible so that way i would could get more experience with coding because i am fairly new here. That's why i was asking if you could explain the code to me because it seems you are very experienced in this sort of thing and i want to learn and grow to get better at coding.

  • it is allowed to have multiple patches in different places.

    Ah, ok. I thought it would be not allowed to separate one color (different patches of it).

    That’s a huge difference, now we can just call patches several times

  • Yeah that's great.

  • MAYbe I will have a look

    Does your version with 2D array work?

  • edited April 2018

    slightly new version:

    • please note that the AI Walker is better (was better in the version before already)

    • the distribution of colors is improved, there was a bug in the neighbor finding

    • one example hexagon shows its neighbors now with a small red cross (to test the neighbor finding)

    Chrisir

    final color RED = color (255, 0, 0); // RED 
    
    final int[] vectorsForNeigbours = {
      -1, 1, -29, 29, -28, 30
    }; 
    
    float [] XColmns;
    float [] YColmns;
    
    float [] ColorR;
    float [] ColorG;
    float [] ColorB;
    
    int [] TileColors;
    //int [] TileColorChance;
    
    int AmountOfTiles = 1131;
    
    int AI_Walker_Position = int (AmountOfTiles / 2);   
    
    int Seed = round(random(1000000000));
    float CharPosX, CharPosY;
    
    int direction=0;
    
    int centerFieldIndexGlobal; 
    int [] listOfNeighbours = new int [6]; 
    ////////////////////////////////////////////////////////////////////////////
    
    void setup() {
    
      size(975, 830);
    
      //println("Seed:  "+Seed);
      randomSeed(Seed);
    
      XColmns = new float[AmountOfTiles];
      YColmns = new float[AmountOfTiles];
      ColorR = new float[AmountOfTiles];
      ColorG = new float[AmountOfTiles];
      ColorB = new float[AmountOfTiles];
      TileColors = new int[AmountOfTiles];
      // TileColorChance = new int[AmountOfTiles];
    
    
      // make hexagon positions
      for (int c = 0; c < 39; c++) {
    
        if ((int)c%2==0) {   
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 30 + N * 27;
          }
        } else { 
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 43 + N * 27;
          }
        }
      }
    
      // -----------
    
      // RESET colors
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        TileColors[TE] = -1; // not defined
      }
    
      // -----------
    
      // add patches 
      patches();
    
      // -----------
    
      // fill gaps between patches
      // 130 attempts
      for (int c2 = 0; c2 < 139; c2++) {
    
        IntList array1 = new IntList();
        for (int c3 = 0; c3 < AmountOfTiles; c3++) {
          array1.append(c3);
        }
        array1.shuffle(); 
    
        // fill gaps between patches 
        for (int c4 = 0; c4 < AmountOfTiles; c4++) {
          int c = array1.get(c4); 
          if (TileColors[c] == -1) {
            int type1 = getNeighbours(c);
            if (type1 != -1)
              TileColors[c] = type1;
          }//if
        }//for
      }//for
      // -----------
    
      // 
      // -----------
      // add ocean but then (maybe) you need to skip ocean above (starting for loop at 1)
      // addOcean(); 
    
      ////////////////////////////////////////////////////////////////////////////
      // new code here
      CharPosX = XColmns[round(random(0, AmountOfTiles))];
      CharPosY = YColmns[round(random(0, AmountOfTiles))];
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here
    } // setup end
    
    // ------------------------------------------------------------------------
    
    int getNeighbours(int index1) {
    
      //int i2=0;
    
      for (Integer i : vectorsForNeigbours) {
    
        int neighbourIndex = index1 + i;
    
        if (neighbourIndex >= 0 && 
          neighbourIndex < AmountOfTiles &&
          TileColors[neighbourIndex] != -1 && 
          !tooFar(index1, neighbourIndex)) {
          // return the found color of the neighbour
          return TileColors[neighbourIndex];
        }//if
        //i2++;
      }//for 
    
      // fail 
      return -1;
    }
    
    boolean tooFar(int ind1, int ind2) {
    
      return dist(XColmns[ind1], YColmns[ind1], 
        XColmns[ind2], YColmns[ind2]) >= 66;
    }
    
    void patches() {
    
      float xPrev=-10000;
      float yPrev=-10000;
    
      // attempts
      //for (int i = 1; i < 13; i++) {
    
      // new group of Type startingNewGroupType : loop over types of hexagon :
      // starting with 1 = NO ocean 
      for (int startingNewGroupType = 0; startingNewGroupType < 4; startingNewGroupType++) {
    
        // making a ***patch*** of color  
    
        int startingNewGroupWhere = int (random(AmountOfTiles));
    
        TileColors[startingNewGroupWhere] = startingNewGroupType;
    
        // going down and up from there 
        int from =  -int(random(4, 7));
        int to   =   int(random(4, 7));  
    
        for (int i2 = from; i2 < to; i2++) {
    
          int newFieldIndex= startingNewGroupWhere + i2; 
          if (newFieldIndex >= 0 && 
            newFieldIndex < AmountOfTiles && 
            dist(xPrev, yPrev, XColmns[newFieldIndex], YColmns[newFieldIndex]) < 66 ) { 
    
            TileColors[newFieldIndex] = startingNewGroupType;
    
            // for each new field going left and right 
            from =  -int(random(4, 7));
            to   =   int(random(4, 7));  
            for (int i3 = from; i3 < to; i3++) {
              if (newFieldIndex + i3*29 >= 0 && newFieldIndex + i3*29 < AmountOfTiles) 
                TileColors[newFieldIndex + i3*29] = startingNewGroupType;
            }//for
          }//if
    
          xPrev=XColmns[startingNewGroupWhere];
          yPrev=YColmns[startingNewGroupWhere];
        }//for
      }//for 
      //
      // }//for attempts
    }
    
    ////////////////////////////////////////////////////////////////////////////
    
    void draw() {
    
      background(226, 185, 108);
    
      //table
      fill(89, 60, 5);  
      // ellipse(-260, -330, 1500, 1500);
    
      //black board
      fill(0);
      stroke(108, 67, 4);
      strokeWeight(1);
      //rect(0, 0, width, height);
    
      for (int i = 0; i < AmountOfTiles; i++) {
        Hexagon(XColmns[i], YColmns[i], 14, TileColors[i], i);
        if (i==AI_Walker_Position) {
          fill(255, 0, 255);
          ellipse(XColmns[i], YColmns[i], 10, 10);
        }//if
      }//for
    
      move_AI();
      showNeighbour(AmountOfTiles/4); 
    
      for (int i = 0; i < AmountOfTiles; i++) {
        for (int i2=0; i2<6; i2++)  
          if (i==listOfNeighbours[i2]) 
            cross(XColmns[i], YColmns[i]);
      }
    
      // fill(255, 0, 25);
      fill(RED);
      ellipse(CharPosX, CharPosY, 10, 10);
    } // end of draw
    
    ////////////////////////////////////////////////////////////////////////////
    
    void showNeighbour(int centerFieldIndex) {
    
      centerFieldIndexGlobal=centerFieldIndex;
    
      int i2=0;
      for (Integer i : vectorsForNeigbours) {
        listOfNeighbours[i2]=centerFieldIndex+i;
        i2++;
      }
    
      //listOfNeighbours[0]=centerFieldIndex-1; 
      //listOfNeighbours[1]=centerFieldIndex+1;
    
      //listOfNeighbours[2]=centerFieldIndex-29;
      //listOfNeighbours[3]=centerFieldIndex+29;
    
      //listOfNeighbours[4]=centerFieldIndex-28;
      //listOfNeighbours[5]=centerFieldIndex+30;
    } 
    
    void Hexagon (float x, float y, 
      float S, 
      float ColorSelecter, 
      int index1) { 
    
      noFill(); 
      //Ocean
      if (ColorSelecter == 0)   
        fill(16, 0, 165);
      //Grassland
      else if (ColorSelecter == 1) 
        fill(81, 195, 14);
      //Jungle
      else if (ColorSelecter == 2) 
        fill(27, 157, 2);
      //Pond
      else if (ColorSelecter == 3)   
        fill(1, 116, 147); 
      // Error 
      else                         
      println ("Error ColorSelecter "
        +ColorSelecter);
    
      if (index1==centerFieldIndexGlobal)
        fill(RED); // fill(255); 
    
      ////////////////////////////////////////////////////////////////////////////
      //new code here                                        
      if (mousePressed && dist(mouseX, mouseY, x+S/2, y+S/2) < S) {  
        CharPosX = x;  
        CharPosY = y;
      }
    
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here                                                 
    
      noStroke();
      beginShape();
      for (int i=0; i<6; i++) {
        float angle = i * 2 * PI / 6;
        vertex(x + S*cos(angle), y + S*sin(angle));
      }
      endShape(CLOSE);
    }//function
    
    void cross(float x, float y) {
    
      final int radius = 5;
    
      stroke(RED); // RED 
    
      line(x-radius, y-radius, 
        x+radius, y+radius);
      line(x+radius, y-radius, 
        x-radius, y+radius);
    }//
    
    void move_AI() {
    
      // for AI_Walker_Position
    
      int testDirection;
    
      if (random(100)>90) {
        int prevDirection = direction;
        testDirection = int(random(4));
    
        // to go back and forth is not allowed
    
        if (prevDirection ==  0 && testDirection == 2) 
          return;
        if (prevDirection ==  2 && testDirection == 0) 
          return;
    
        if (prevDirection ==  1 && testDirection == 3) 
          return;
    
        if (prevDirection ==  3 && testDirection == 1) 
          return;
      } else {
        return;
      }
    
      direction = testDirection; 
    
      switch (direction) {
      case 0: //north
        AI_Walker_Position = AI_Walker_Position  - 1; 
        break;
    
      case 1: //east 
        AI_Walker_Position= AI_Walker_Position + 29; 
        break;
    
      case 2: //south 
        AI_Walker_Position = AI_Walker_Position + 1; 
        break;
    
      case 3: //west 
        AI_Walker_Position= AI_Walker_Position - 29; 
        break;
    
      default: 
        println("Error 322");
        break;
      }//switch 
    
      // check 
      if (AI_Walker_Position < 0) 
        AI_Walker_Position=AmountOfTiles; 
    
      if (AI_Walker_Position >= AmountOfTiles) 
        AI_Walker_Position=0;
    }
    //
    
  • edited April 2018

    this line at end of setup was wrong:

    ////////////////////////////////////////////////////////////////////////////
      // new code here
      CharPosX = XColmns[round(random(0, AmountOfTiles))];
      CharPosY = YColmns[round(random(0, AmountOfTiles))];
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here
    

    must be the same index for both arrays XColmns and YColmns

      ////////////////////////////////////////////////////////////////////////////
      // new code here
      int indexCharPos = int(random(0, AmountOfTiles));  
      CharPosX = XColmns[indexCharPos];
      CharPosY = YColmns[indexCharPos];
      ////////////////////////////////////////////////////////////////////////////
    

    Remark

    also the names XColmns and YColmns are not good. Should be XColumns and YRows because in a table to the right are the columns, downwards the rows.

  • edited April 2018

    Do you remember our good old code for the AI walker:

    case 0: //north
      AI_Walker_Position = AI_Walker_Position  - 1; 
      break;
    
    case 1: //east 
      AI_Walker_Position= AI_Walker_Position + 29; 
      break;
    
    case 2: //south 
      AI_Walker_Position = AI_Walker_Position + 1; 
      break;
    
    case 3: //west 
      AI_Walker_Position= AI_Walker_Position - 29; 
      break;
    

    It was a bit lame since we have fixed numbers here and also only 4 neighbors where we have in fact 6.

    The improvement is the usage of this list of where the neighbors are (what you have to add to get from one hexagon to all neighbors) :

    int[] vectorsForNeigbours = {
      -1, 1, -29, 29, -28, 30
    }; 
    

    Neat, uh?

    So our AI walker boils down to

        testDirection = int(random(6));
    
    
        AI_Walker_Position = AI_Walker_Position  +  vectorsForNeigbours[direction];
    

    But we have to take into account that we don't want the walker to go back and forth, like forward one and back one. That'd look stupid. So we need 3 pairs of numbers which are the back and forth and exclude them:

    return here means we leave the function and don't move the AI Walker:

        // to go back and forth is not allowed
        // (so these are 3 illegal pairs: 01, 43, 25)
    
        if (prevDirection ==  0 && testDirection == 1) 
          return;
        if (prevDirection ==  1 && testDirection == 0) 
          return;
    
        if (prevDirection ==  3 && testDirection == 4) 
          return;
        if (prevDirection ==  4 && testDirection == 3) 
          return;
    
        if (prevDirection ==  2 && testDirection == 5) 
          return;
        if (prevDirection ==  5 && testDirection == 2) 
          return;
    

    The numbers like 0/1 and 3/4 and 2/5 are the illegal pairs and refer to the list vectorsForNeigbours (so they mean -1/1 and 29/-28 and -29/30)

    for a discussion of the illegal neighbor pairs see here (numbers refer to the full red hexagon and its six neighbors, marked by red crosses X) :

    Unbenannt

    Here is the entire AI Walker function :

    void move_AI() {
    
      // for AI_Walker_Position
    
      int testDirection;
    
      if (random(100)<90) {
        return; // leave here
      }
    
      int prevDirection = direction;
      testDirection = int(random(6));
    
      // -----
    
      // to go back and forth is not allowed
      // (so these are 3 illegal pairs: 01, 43, 25)
    
      if (prevDirection ==  0 && testDirection == 1) 
        return;
      if (prevDirection ==  1 && testDirection == 0) 
        return;
    
      if (prevDirection ==  3 && testDirection == 4) 
        return;
      if (prevDirection ==  4 && testDirection == 3) 
        return;
    
      if (prevDirection ==  2 && testDirection == 5) 
        return;
      if (prevDirection ==  5 && testDirection == 2) 
        return;
    
      // -----
    
      direction = testDirection; 
    
      AI_Walker_Position = AI_Walker_Position  +  vectorsForNeigbours[direction];
    
      // check 
      if (AI_Walker_Position < 0) 
        AI_Walker_Position=AmountOfTiles; 
    
      if (AI_Walker_Position >= AmountOfTiles) 
        AI_Walker_Position=0;
    }
    //
    
  • edited April 2018

    here is a new version that uses a random walker for the initial patches and then fills the gaps

    // https : // forum.processing.org/two/discussion/26942/hexagon-generation#latest
    
    // this version: 
    //  * improved AI Walker 
    //  * patch not more or less round area but with a virtual Walker (like rivers) (still then gaps are filled)
    //  * good version
    
    
    // color red as a constant 
    final color RED = color (255, 0, 0); // RED 
    
    // list for neighbour finder as array (constant)
    final int[] vectorsForNeigbours = {
      -1, 1, -29, 29, -28, 30
    }; 
    
    float [] XColmns;
    float [] YColmns;
    
    float [] ColorR;
    float [] ColorG;
    float [] ColorB;
    
    int [] TileColors;
    //int [] TileColorChance;
    
    int AmountOfTiles = 1131;
    
    int AI_Walker_Position = int (AmountOfTiles / 2);   
    
    //int Seed = round(random(1000000000));
    float CharPosX, CharPosY;
    
    int direction=0;
    
    int centerFieldIndexGlobal; 
    int [] listOfNeighbours = new int [6]; 
    
    ////////////////////////////////////////////////////////////////////////////
    
    void setup() {
    
      size(975, 830);
    
      //println("Seed:  "+Seed);
      //randomSeed(Seed);
    
      XColmns = new float[AmountOfTiles];
      YColmns = new float[AmountOfTiles];
      ColorR = new float[AmountOfTiles];
      ColorG = new float[AmountOfTiles];
      ColorB = new float[AmountOfTiles];
      TileColors = new int[AmountOfTiles];
      // TileColorChance = new int[AmountOfTiles];
    
      // make hexagon positions
      for (int c = 0; c < 39; c++) {
    
        if ((int)c%2==0) {   
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 30 + N * 27;
          }
        } else { 
          for (int N = 0; N < 29; N++) { 
            XColmns[N+c*29] = 31+c*24;
            YColmns[N+c*29] = 43 + N * 27;
          }
        }
      }
    
      // -----------
    
      // RESET colors
      for (int TE = 0; TE < AmountOfTiles; TE++) {
        TileColors[TE] = -1; // not defined
      }
    
      // -----------
    
      // add patches 
      patches();
    
      // -----------
    
      // fill gaps between patches
      fillGapsBetweenPatches();
    
      // -----------
      // 
      // -----------
      // add ocean but then (maybe) you need to skip ocean above (starting for loop at 1)
      // addOcean(); 
    
      ////////////////////////////////////////////////////////////////////////////
      // new code here
      int indexCharPos = int(random(0, AmountOfTiles));  
      CharPosX = XColmns[indexCharPos];
      CharPosY = YColmns[indexCharPos];
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here
    } // setup end
    
    ////////////////////////////////////////////////////////////////////////////
    
    void draw() {
    
      background(226, 185, 108);
    
      //table
      fill(89, 60, 5);  
      // ellipse(-260, -330, 1500, 1500);
    
      //black board
      fill(0);
      stroke(108, 67, 4);
      strokeWeight(1);
      //rect(0, 0, width, height);
    
      for (int i = 0; i < AmountOfTiles; i++) {
        Hexagon(XColmns[i], YColmns[i], 
          14, TileColors[i], i);
        if (i==AI_Walker_Position) {
          fill(255, 0, 255);
          ellipse(XColmns[i], YColmns[i], 10, 10);
        }//if
      }//for
    
      move_AI();
      showNeighbour(AmountOfTiles/4); 
    
      for (int i = 0; i < AmountOfTiles; i++) {
        for (int i2=0; i2<6; i2++)  
          if (i==listOfNeighbours[i2]) 
            cross(XColmns[i], YColmns[i]);
      }
    
      fill(255, 0, 25);
      ellipse(CharPosX, CharPosY, 10, 10);
    } // end of draw
    
    ////////////////////////////////////////////////////////////////////////////
    // called from setup() (or its children)
    
    void fillGapsBetweenPatches() {
    
      // 130 attempts
      for (int c2 = 0; c2 < 139; c2++) {
    
        IntList array1 = new IntList();
        for (int c3 = 0; c3 < AmountOfTiles; c3++) {
          array1.append(c3);
        }
        array1.shuffle(); 
    
        // fill gaps between patches 
        for (int c4 = 0; c4 < AmountOfTiles; c4++) {
          int c = array1.get(c4); 
          if (TileColors[c] == -1) {
            int type1 = getNeighbours(c);
            if (type1 != -1)
              TileColors[c] = type1;
          }//if
        }//for
      }//for
    }//func
    
    int getNeighbours(int index1) {
    
      // checks all 6 neighbors of index1 and returns the color of the first non-empty field.  
    
      int i2=0;
    
      for (Integer i : vectorsForNeigbours) {
    
        //print(i+" "); 
    
        int neighbourIndex = index1 + i;
    
        // if valid hexagon index and tile not empty return the color  
        if (neighbourIndex >= 0 && 
          neighbourIndex < AmountOfTiles &&
          TileColors[neighbourIndex] != -1 && 
          !tooFar(index1, neighbourIndex)) {
          // return the found color of the neighbour
          return TileColors[neighbourIndex];  // leave here
        }//if
        i2++;
      }//for
    
      //println(i2); 
    
      // fail 
      return -1;
    }
    
    boolean tooFar(int ind1, int ind2) {
      // too far away 
      return dist(XColmns[ind1], YColmns[ind1], 
        XColmns[ind2], YColmns[ind2]) >= 66;
    }
    
    void patches() {
    
      // making a ***patch*** of color  
      // by using a virtual random walker (like a river)
    
      // new group of Type startingNewGroupType : loop over types of hexagon :
      // (starting with 1 = NO ocean OR starting with 0 = WITH ocean)  
      for (int startingNewGroupType = 0; startingNewGroupType < 4; startingNewGroupType++) {
    
        // attempts per color 
        for (int i2 = 0; i2 < 14; i2++) {  // starting multiple patches - you can comment out this for loop 
    
          int startingNewGroupWhere = int(random(AmountOfTiles));
    
          int newFieldIndex = startingNewGroupWhere; 
          int direction = int(random(6));
    
          // walking steps
          for (int i = 1; i < 244; i++) {
    
            if (random(100)>80) {
              direction = int(random(6));
            }
            direction = int(random(6));
    
            newFieldIndex = startingNewGroupWhere + vectorsForNeigbours[direction]; 
            if (newFieldIndex >= 0 && 
              newFieldIndex < AmountOfTiles &&
              (TileColors[newFieldIndex] == -1 || TileColors[newFieldIndex] == startingNewGroupType ) &&
              !tooFar(startingNewGroupWhere, newFieldIndex) ) { // !tooFar(startingNewGroupWhere, newFieldIndex) && TileColors[newFieldIndex] == -1  
              // define color for that hexagon  
              TileColors[newFieldIndex] = startingNewGroupType;
              startingNewGroupWhere=newFieldIndex;
            }
          }//for
        }//for
      }//for
      //
    } // func 
    
    void patchesOLD() {
    
      // more round patches 
    
      float xPrev=-10000;
      float yPrev=-10000;
    
      // attempts
      //for (int i = 1; i < 13; i++) {
    
      // new group of Type startingNewGroupType : loop over types of hexagon :
      // starting with 1 = NO ocean 
      for (int startingNewGroupType = 0; startingNewGroupType < 4; startingNewGroupType++) {
    
        // making a ***patch*** of color  
    
        int startingNewGroupWhere = int (random(AmountOfTiles));
    
        TileColors[startingNewGroupWhere] = startingNewGroupType;
    
        // going down and up from there 
        int from =  -int(random(4, 7));
        int to   =   int(random(4, 7));  
    
        for (int i2 = from; i2 < to; i2++) {
    
          int newFieldIndex= startingNewGroupWhere + i2; 
          if (newFieldIndex >= 0 && 
            newFieldIndex < AmountOfTiles && 
            dist(xPrev, yPrev, XColmns[newFieldIndex], YColmns[newFieldIndex]) < 66 ) { 
    
            TileColors[newFieldIndex] = startingNewGroupType;
    
            // for each new field going left and right 
            from =  -int(random(4, 7));
            to   =   int(random(4, 7));  
            for (int i3 = from; i3 < to; i3++) {
              if (newFieldIndex + i3*29 >= 0 && 
                newFieldIndex + i3*29 < AmountOfTiles) 
                TileColors[newFieldIndex + i3*29] = startingNewGroupType;
            }//for
          }//if
    
          xPrev=XColmns[startingNewGroupWhere];
          yPrev=YColmns[startingNewGroupWhere];
        }//for
      }//for 
      //
      // }//for attempts
    }
    
    ////////////////////////////////////////////////////////////////////////////
    // called from draw() (or its children)
    
    void showNeighbour(int centerFieldIndex) {
    
      centerFieldIndexGlobal=centerFieldIndex;
    
      int i2=0;
      for (Integer i : vectorsForNeigbours) {
        listOfNeighbours[i2]=centerFieldIndex+i;
        i2++;
      }
    } 
    
    void Hexagon (float x, float y, 
      float S, 
      float ColorSelecter, 
      int index1) { 
    
      noFill(); 
      //Ocean
      if (ColorSelecter == 0)   
        fill(16, 0, 165);
      //Grassland
      else if (ColorSelecter == 1) 
        fill(81, 195, 14);
      //Jungle
      else if (ColorSelecter == 2) 
        fill(27, 157, 2);
      //Pond
      else if (ColorSelecter == 3)   
        fill(1, 116, 147); 
      // Error 
      else                         
      println ("Error ColorSelecter "
        +ColorSelecter);
    
      // used for showNeighbour() 
      if (index1==centerFieldIndexGlobal)
        fill(RED); // fill(255); 
    
      ////////////////////////////////////////////////////////////////////////////
      //new code here                                        
      if (mousePressed) {
    
        if ( dist(mouseX, mouseY, x+S/2, y+S/2) < S) {
          if (mouseButton==LEFT) {
            CharPosX = x;  
            CharPosY = y;
          } else if (mouseButton==RIGHT) {
            // println (index1);
            fill(0); 
            text(index1, width-33, 11);
          }
        }
      }
    
      ////////////////////////////////////////////////////////////////////////////
      //new code ends here                                                 
    
      noStroke();
      beginShape();
      for (int i=0; i<6; i++) {
        float angle = i * 2 * PI / 6;
        vertex(x + S*cos(angle), y + S*sin(angle));
      }
      endShape(CLOSE);
    }//function
    
    void cross(float x, float y) {
    
      final int radius = 5;
    
      stroke(RED); // RED 
    
      line(x-radius, y-radius, 
        x+radius, y+radius);
      line(x+radius, y-radius, 
        x-radius, y+radius);
    }//
    
    // ---------------------------------------------------------
    // AI 
    
    void move_AI() {
    
      // for AI_Walker_Position
    
      int testDirection;
    
      if (random(100)<90) {
        return; // leave here
      }
    
      int prevDirection = direction;
      testDirection = int(random(6));
    
      // -----
    
      // to go back and forth is not allowed
      // (so these are 3 illegal pairs: 01, 43, 25)
    
      if (prevDirection ==  0 && testDirection == 1) 
        return;
      if (prevDirection ==  1 && testDirection == 0) 
        return;
    
      if (prevDirection ==  3 && testDirection == 4) 
        return;
      if (prevDirection ==  4 && testDirection == 3) 
        return;
    
      if (prevDirection ==  2 && testDirection == 5) 
        return;
      if (prevDirection ==  5 && testDirection == 2) 
        return;
    
      // -----
    
      direction = testDirection; 
    
      AI_Walker_Position = AI_Walker_Position  +  vectorsForNeigbours[direction];
    
      // check 
      if (AI_Walker_Position < 0) 
        AI_Walker_Position=AmountOfTiles; 
    
      if (AI_Walker_Position >= AmountOfTiles) 
        AI_Walker_Position=0;
    }
    //
    
  • edited April 2018

    Wow this is great stuff i did notice that the AI had a bug i was trying to fix it but couldn't figure it. But the AI works great just looking at all the code you posted and slowly looking threw and learning how the new code works. I agree on the XColmns and the YRows change it makes it more clear.

  • edited April 2018

    Besides of color distribution:

    think of a game.

    e.g. settlers of Catan

    https://en.wikipedia.org/wiki/Catan

    and/or a mix of Settler of Catan with some "conquer areas game".

    A simple approach:

    Possible Game e.g.

    • two human players play on your board (no AI)

    • both start with a hexagon that belongs to them (randomly assigned to player)

    • they have alternating turns. (Their moves.)

    • Now each round the hexagons produce resources (ocean=fish, forest=wood, grassland with sheep = wool...), e.g. per round 1 fish, 1 wood etc.

    • Now the player that owns a hexagon gets its resources, so they get richer

    • to conquer / occupy a new hexagon (territory grows ) you need to invest resources. Once you own a new hexagon you also get its resources next round, so you're getting richer faster

    • to make the things easier, 1 fish = 1 $, 1 wood/lumber = 2 $, next 3$, next 4$ (different prices)

    • To conquer e.g. a new field, you must pay 5 bugs to the bank. When you own 12 bugs you can conquer 2 hexagons; only adjacent hexagons can be conquered

    • You have to decide which hexagon to take (that produce more wealth, so ocean is less attractive than wood etc.; hexagons owned by other player can't be bought

    • after 5 minutes game is over and we count the hexagons both own: who owns more has won. Display Win Message, "Player 2 has won!" or so. Ask to play again.

    • can be played in theory with 4 human players also or later against AI

    Things to do

    • resources are distributed to players every turn

    • Each player has the resources he owns / money (variables for each player: money)

    • turn / round management (whose turn is it etc.)

    • select hexagons you want to conquer with the mouse, money is monitored

    Chrisir

Sign In or Register to comment.