Oblique Hex-grid Numbering uploaded

If I had known how much work it would turn out to be, Imight have chosen another first projecty. However it is done now, and it was a great learning experience for Java and VASSAL. I have checked it in under the branch pgeerkens, down in …/mapgrid.

HexGridNumberingX is ready for prime-time, as an extension of HexGridNumbering that:

  1. Implements Oblique hex-grid numbering for all cases; and
  2. Eliminates the earlier design choice to implement the pick-window for hexes as
    a cleverly-crafted rectangle. Each hex now has a pick-window that exactly matches its interior.

HexGridNumberingX can also be added to a VASSAL module as a custom class, without
any need to edit the build file. This took some work, as the implementation of HexGridNumbering
was having its Configurer(), and hence its forceDraw(), method invoked before the private variable
grid had been defined by addToParent(). The work-around was to override Configurer(), invoking
super.Configurer() only if getGrid() returns non-null. This seems to work fine.

Part of why this was such a bugger is that there are unchecked references to ex.getMessage() that
were causing a Null Pointer Exception, erasing memory of the Null Pointer Exception that had
caused the Exception call. I will be looking for, and writing if I don’t find it, a function as
follows:

String ifNull (String msg) {
return (msg == null) ? “” : msg;
}

to simplify writing of robust Exception Handling (in my own code at least).

Thus spake pgeerkens:

If I had known how much work it would turn out to be, Imight have chosen
another first projecty. However it is done now, and it was a great
learning experience for Java and VASSAL. I have checked it in under the
branch pgeerkens, down in …/mapgrid.

You didn’t commit what you intended to commit. 7570 doesn’t have any
code in it.


J.

I will track it down - I am new to Subversion. Thank you.

OK That should have resolved it. The little black star beside my folders has disappeared now. ;-)

Also, there is a comprehensive test bed included in the module for the use of anyone who wants to try it out. The old AH games all need oblique numbering.

Pieter

Thus spake pgeerkens:

I will track it down - I am new to Subversion. Thank you.

No problem. (Don’t get too comfortable—I was thinking of suggesting that
we switch to git for version control sometime in the near future…)


J.

Don’t do that ;-)

I remember when RCS was an improvement to SCCS.

The one thing definitely worse than the second best version/configuration solution, is a solution that no-one is comfortable with.

Pieter

The one thing definitely worse than the second best
version/configuration solution, is a solution that no-one is comfortable
with.

I suggest GoogleDocs.

  • M.

Thus spake pgeerkens:

OK That should have resolved it. The little black star beside my folders
has disappeared now. :wink:

Some initial comments on your code:

  1. Don’t use

“” + foo

to convert foo to a String. Use String.valueOf(), it’s more efficient.

  1. Don’t use ‘new Boolean()’, ever. There are only two possible Boolean
    values, and instances of them already exist; creating more only makes
    more work for the garbage collector. If you want to get a Boolean from
    a String, use Boolean.valueOf().

  2. Use prefix ++ and – unless you actually need the values returned
    first.

  3. Any variable which you’re not going to reassign should be final.

I’ll try to make a more thorough review soon.

Also, there is a comprehensive test bed included in the module for the
use of anyone who wants to try it out. The old AH games all need oblique
numbering.

Tests belong under the test/ hierarchy. (Note that this is not yet observed
everywhere—there are still some tests floating around under src/, which
still need to be moved.)


J.

Thus spake Michael Kiefte:

The one thing definitely worse than the second best
version/configuration solution, is a solution that no-one is comfortable
with.

I suggest GoogleDocs.

You’re funny, Michael.


J.

Thank you for the quick feedback. I have made the changes you requested, but need a little time to get my test bed working again - the test hierarchy needs to be tweaked a bit. I will upload again soon.

#3 may take a little getting used to, as I have a 20 year habit of writing i++ except when I absolutely require --i.

Joel,

I agree with everything you’ve said here and much of it carries over from C.

But it makes me wonder, does the Java compiler optimise all this anyway?

  • M

On 15 December 2010 11:25, Joel Uckelman uckelman@nomic.net wrote:

Thus spake pgeerkens:

OK That should have resolved it. The little black star beside my folders
has disappeared now. :wink:

Some initial comments on your code:

  1. Don’t use

“” + foo

to convert foo to a String. Use String.valueOf(), it’s more efficient.

  1. Don’t use ‘new Boolean()’, ever. There are only two possible Boolean
    values, and instances of them already exist; creating more only makes
    more work for the garbage collector. If you want to get a Boolean from
    a String, use Boolean.valueOf().

  2. Use prefix ++ and – unless you actually need the values returned
    first.

  3. Any variable which you’re not going to reassign should be final.

I’ll try to make a more thorough review soon.

Also, there is a comprehensive test bed included in the module for the
use of anyone who wants to try it out. The old AH games all need oblique
numbering.

Tests belong under the test/ hierarchy. (Note that this is not yet observed
everywhere—there are still some tests floating around under src/, which
still need to be moved.)


J.

Thus spake Michael Kiefte:

Joel,

I agree with everything you’ve said here and much of it carries over from C.

But it makes me wonder, does the Java compiler optimise all this anyway?

‘new Boolean’ it definitely doesn’t optimize away. (The fact that there’s
even a public ctor for Boolean is a bug, in my opinion.)

I believe String conversion using “” + ends up happening via a StringBuilder,
while something more efficient can happen if you use String.valueOf().


J.

Yes, the extent of optimizations is limited by the fact that only partial compilation is occurring, and run-time binding must be allowed for.

Also, the more completely the programmer describes and constrains the solution, the less likely it is that erros occur later.

It might be worth knowing that the classes for Oblique Hex grid numbering had already been written as custom class imports, they just had not been included with standard Vassal for whatever reason…

An interesting exercise might be to compare these already written classes with what you’ve come up with for fun and giggles. The two classes, HexGridNumbering.java and ObliqueHexGridNumbering.java can be found in the VQSL-src/trunk/afk directory in the repository

Yes, I actually started from Brent’s implementation of ObliqueHexGridNumbering in the Afrika Korps module. However his approach was the more practical one of tackling the multiple scenarios singly, as needed for each game, and Waterloo needed settings not available in the Afrika Korps implementation. Then I discovered some subtle bugs and short-cuts in the HexGridNumbering, followed by the inability to auto-load from the Editor, and with the goal of learning quickly more about both Java and VASSAL I accepted the challenge of producing a single class that implements every hex-grid numbering known to man (any Vulcans out there?). While I do not claim to have fully succeeded, the work is good and I know a lot more Java and VASSAL now.

Pieter

I’ve run out of time this evening to finish reviewing your patch, unfortunately. Your code looks ok, on the whole, but what this has reminded me of is what an awful mess the existing grid code is generally. We had a discussion about this a few months ago:

https://forum.vassalengine.org/t/adc2-to-vassal-coversion/2635/1

Adding more grid code without refactoring sends us further down the rabbit hole. I think a large part of the difficulties you had in extending HexGridNumbering stem from it’s kitchen-sink design. This is one of those places where it would be relatively easy to disentangle all of the parts so that everything is coded to an interface and each class does one thing, and also write unit tests for them. Would you be interested in doing this if I helped you get started?

When you flatter me like that, how can I say no. ;-)

Yes, I believe you are correct, and I could spend some time to at least get it properly started.

Pieter

For Hex-Grid-Numbering, one issue is the staggering number of scenarios to be be verified on every code change. The independent switches are these:

  1. Oblique/Standard
  2. H-Descending
  3. V-Descending
  4. Sideways
  5. Reversed
  6. Stagger (if Standard) or NW_SE (if oblique)
  7. MaxRows odd/even
  8. Mox Columns odd/even
  9. MaxObliques odd/even (if oblique)

Then for each test case you need to check a minimum of 4 points, to have odd & even rows and columns checked.

By my count this makes for (128 + 64) * 4 = 768 opportunites on evey code change to break an existing module.

Okay, maybe Reversed can be left out of this chain, but that is still 384 cases to be checked on.

To be practical one would need an automated regression suite:
a) probably 6 different grids, to capture these:
____7) MaxRows odd/even
____8) Mox Columns odd/even
____9) MaxObliques odd/even (if oblique)
b) some means of efficiently selecting points to ensure coverage of this:
____minimum of 4 points, to have odd & even rows and columns checked
c) a test engine to run through these 64 cases for each grid, for the entire point set selected.
____1) Oblique/Standard
____2) H-Descending
____3) V-Descending
____4) Sideways
____5) Reversed
____6) Stagger (if Standard) or NW_SE (if oblique)

Then one outputs the entire set as a suite of reports, that can be text-differenced to the standard and manually checked set.

By checking in each small, self-contained, change independently, and running the test suite on each build, one can get an email each morning announcing whicn code changes broke which test-cases. Before one even has time to forget why one made the change.

Some work to set up, but it is a real charmer once set-up. I had the privilege of creating this for the report engine that I built in the '90’s.

Pieter

Thus spake pgeerkens:

By checking in each small, self-contained, change independently, and
running the test suite on each build, one can get an email each morning
announcing whicn code changes broke which test-cases. Before one even
has time to forget why one made the change.

Some work to set up, but it is a real charmer once set-up. I had the
privilege of creating this for the report engine that I built in the
'90’s.

It isn’t necessary to build a system like this from scratch. It already
exists. We have a testing framework (JUnit). If you’re using the Makefile
for building, you can run all of the tests using ‘make test’. There’s
some way to do that from Eclipse, as well, in case you’re using that. You
don’t need to wait for an automated system to notify you—you can run
the tests immediately.

There’s also Hudson, which is a continuous integration framework. It will
email you when tests fail. Right now, we’re using a Hudson instance that
Ken set up, but sometime in the new year we’ll have our own at
vassalengine.org.


J.