Is there a workaround for the getLocation(String location) function?

I’m seeing a problem when I try to get the Point location of a hex in my HexGrid. Calling getLocation(“AA01”) succeeds, but fails for “AB01”. It actually fails for anything higher than the “AA” column.

My code looks like this:

    	final Map map = Map.activeMap;
    	if (map != null) {
	    	//show("Map = " + map.getMapName());
    		for (Board board : map.getBoards()) {
    			MapGrid grid = board.getGrid();
		        try {
					final Point hexPoint = grid.getLocation(hexName);
					show("showing hex " + hexName + " on map " + map.getMapName() + ", board " + board.getName());
					return true;
				} catch (BadCoords e) {
					// will get here if the grid is unnumbered
					// in that case skip to the next map
					show("hex " + hexName + " not found on map " + map.getMapName() + ", board " + board.getName());
    	else {
    		show("no map selected");

There’s a comment in the file that makes me think this is a known problem.

line 426
  // This appears to be the most efficient way to accomplish this without
  // using groups. It also helps when there is no separator between alphabetic
  // coordinates (as long as both coordinates don't use the same letter).
  // AAFF is not ambiguous, but AAAA is.  Coordinates like 04AB will fail.

Is there a better way to move the map to a specified hex?

The code implementing this feature for hexgrids (RegularGridNumbering.getLocation()) is really old and has not been touched for 10 years. It’s quite possible it has never worked for some types of hex grid numbering styles.

Out of interest, you could try the ‘Send To Location’ trait to send a counter to hex AB01 and see if this also fails. Theoretically, it should be using the same code path.

Ultimately, RegularGridNumbering.getLocation probably needs to be debugged and fixed, it may only need a small tweak.

I’ve almost got the regex fixed for grids the identify columns with alphabetic and rows with numbers. I don’t know if all maps use that grid cell naming convention, though.
Now I’m figuring out how to do base 26 math. The method in the parseName() function is terribly broken. It gives the correct answer AA01 (column 27, row 1), but is wrong for BA01 (also column 27, when it should be ((26^1)*2)+(26^0)*1)=53. If someone went crazy and 3 digit column numbers the decimal value of column CBA would be ((26^2)*3+(26^1)*2+(26^0)*1)=2081.

So this seems to work. My change is in the parseName() function in the file. I need to figure out how to fork the current code and create a merge request…


  protected int parseName(String name, char type) {
    int value = 0;

    if (type == 'A' || type == 'C') { // Alphabetic
      int index = 0;
      boolean negative = false;
      if (name.startsWith("-")) {
        negative = true;

      // first, reverse the characters in "name" and remove the numbers and negative sign
      String reverse_name = new StringBuilder(name).reverse().toString().replaceAll("[-0123456789]", "").toUpperCase();
      // then step through each character in string and add it, times its power of 26 digit, to value
      for (index = 0; index < reverse_name.length(); index++) {
    	  value += (1+ALPHABET.indexOf(reverse_name.charAt(index))) * (int)Math.pow(26, index);
      value--; // need to make it zero-relative again
      if (negative)
        value *= -1;
    else { // Numeric
      value = Integer.parseInt(name);

    return value;

There’s no point in creating a StringBuilder just to throw it away. You can call reverse() directly on name.

1 Like

I’m not seeing a reverse() function in the java.lang.String class.

Oh, funny; I thought sure that existed. You’re right.

1 Like

I thought so, too! It seemed like such an obvious thing.