Some new design thoughts

Hi all. Been awhile.

I have recently had some more thought about the design of a boardgame engine. The topic intrigues me. Some may remember my efforts with Lua, Qt and binding.

The conclusion was that the binding simply did not work. Also, the size of the binding libraries was an order of magnitude greater than the Qt libraries themselves, not good.

On my GitHub wiki I have sketched another way of doing the binding while at the same time ensuring safety. Check it out. Being able to call the GUI from Lua like this is very cool. No binding. I use GTK because it is a standard part of Linux but any other graphic library may do, including Qt.

I will continue to analyze designs and do small feasibility tests. There are a number of issues that Vassal must deal with which I will not deal with. But I hope my design ideas will have some value. I will continue on an irregular basis and post on this thread when the wiki is updated. Comments are welcome.

By the way, how is development of Vassal 4.0 going ?

So quiet here? I hope this thread is not considered spam even if it is not directly related to Vassal.

Next up is the module, see page 2 on my GitHub wiki. Not surprisingly, the module is not too different from a Vassal module. But unlike a Vassal module it contains a directory of Luau scripts. Here I stumbled into my first big problem in design.

There is a good reason why Java classes are closely associated with their files. If all Java classes were in a single file the code would become unwieldy. In Java it is easy to reference classes in other files.

file 1: public class ClassName {}
file 2: ClassName variable;

In Lua we have the require(“fileName”). The problem is that when you load and compile Luau script files into the VM the file name of each individual file becomes meaningless. The problem was solved by using the chunk name in the load-step to define a Luau global that in a unique way can reference the script (chunk) in a file.

What does the Luau script in the design actually do? Two things. It defines a start state for the whole game, how windows, maps, counter, cards, etc. look. Second, it defines what happens when various events are triggered, like right clicking over a counter. That is why the script must be able draw a specific menu with entries. But the script never calls the GUI directly, only calls exposed C functions with parameters which in turn calls the actual GUI. For complex calls C is able to directly access datastructures (tables) in Lua for information.

In principle the module designer must be able to draw whatever on the map, like circles and dotted lines. It depends on what GUI featues are exposed.

In my tests I use GTK simply because it is available by default on Linux systems. I just have to install the header files (libgtk-3-dev).

Next up is Drag-and-Drop. This feature is fundamental and must work.


Counters and counter attributes
Counter stacks
Game state and undo functionality
… and the list goes on

The fun thing about such a design project is that you never know where it leads you. I may well stumble into problems that can’t be solved or problems I do not wish to use more time on. We will see.

1 Like

My GitHub wiki has been updated with a page on Drag and Drop.

The module designer can set the transparency (alpha) of a dragged counter. All else is located in the C++ part of the engine and need not be modified by the module developer.

The drag and drop is done with GTK3. I have not worked much with GTK. My impression is not good. The knowledge base is small. Examples of code are rare. New versions of GTK require applications to be rewritten. That must be the reason why a Linux distribution have libs for both GTK2, GTK3 and GTK4.

In GTK4 you can not set z-order. Yes, you read correctly. Maybe it’s possible to reorder the children of a container? Who knows. Why have they made such a basic feature so inaccessible?

It will likely soon be necessary to use Qt instead of GTK. But making a small suitable Qt
lib is a project in itself. I had hoped to make some simple pilot test with GTK.

It is my impression that GTK is not well designed. That each new version is so different
shows this. A good design never needs change, only additions. Linux/UNIX is an example of a design that has never needed change.

Next up is Grid. I have the basic idea of the design. Grid is the first real test for how a module is developed. I hope to show what I mean by “the script is the module”. The main idea is that you should not need a separate tool to develop a module. The script of a module tells you how it works. To test and see your modifications you just need to reload the script.

1 Like

My GitHub wiki has been updated with a section on grids.

The code generates a simple hex grid with snap-to functionality on the center dots.

It is possible to display the grid as a circle with a given radius, color and alpha. Such a display makes it possible to align the grid to the map. The display can be turned off with the function gridShow(false). If you run this code, make sure colors and alpha lie between 0.0 and 1.0. There is no input validation.

This is how the module developer will work. He will have the ability to specify the size of the grid (with what I call that the a and b parameters) and a grid offset. Be displaying the grid, he will then be able to see to what degree the grid fits with the map’s grid and make adjustment.

The adjustment is immediately visible by the ability to reload the Luau script while the engine is running!

There is no tool to align the grid, only this reloading of script. You can say that the tool is the module window itself. This is the core of the design.

There are pros and cons with such a design. Pros are flexibility and simplification. Cons may be the fact that the module developer needs to know Lua scripting, that more is done “manually” and that documentation (and good error messages) are vital. The method of making a module must be intuitive or else the design in flawed.

Next now is the counter and its traits. The concept of traits will be similar to that of VASSAL. It is also a good idea that traits exist in stacks, where a trait influences all traits below it on the stack.

There must be a separate counter window that will show the counters. A change to the counters in the script will be easily visible after a reload of the script.

The basic premise is that the definition of counters and their traits are defined in a flat Luau script file (or files). Traits can be thought of as Luau functions. Many common traits can be pre-made in the Luau part of the engine, like the Delete trait.

The interesting thing about scripting traits is that the module developer can make his own traits. Since all traits are Luau scripts, any trait can be modified or expanded as needed. The only limitation is what is offered from the exposed functions of the C++ API.

Traits have functional aspects, but they can also have visual aspects (like the Can Rotate trait). Traits may or may not have an entry in the right-click menu of a counter.

The data structures (tables) in Lua must be used to define counter-templates that can be copied up for each new counter.

The concept of traits in counters is obviously a large and complex subject. I will not try to solve all problems at once but go forward step by step. The first step is to load the image resources and give them an id. The obvious id is the filename but if a file has the same name in two sub-directories then a number must be added. By printing to a log-file what id belongs to what image file, the module developer can use the ids to specify counter images.

Later it will be time to deal with stacks of counters, among other things changing the position of counters in a stack. I’m afraid I will have to start using Qt for this, which means making a Qt library that is small, sufficient and can be redistributed. This will take time.