Currently I'm experiencing dificulties with calculating the valid moves for pieces in my implementation of hexagonal chess in python. Let me first begin with describing how the movement of the knight is defined in Hexagonal chess.
Let me focus on 1 movement action of the knight. A knight move 4 rows up and 1 column to the left. This is described in the following lines of code:
target = (position_col - 1, position_row - 4)
if on_board(target):
if empty_hexagon(target, board) or piece_color_on_position(target, board) != self.color:
move = Move(self, self.position, target)
self.moves.append(move)
Now this works for certain positions like here:

Now this does indeed work for this specific hexagon, but not for all. See for example this position:

This is happening because not all rows in my board contain the same amount of columns. My board is basically a 2 dimensional array filled with hexagon objects, which I don't think is particularly important in this example, but it has the following structure:
self.board = [
[None],
[None, None],
[None, None, None],
[None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None, None, None],
[None, None, None, None, None],
[None, None, None, None],
[None, None, None,],
[None, None],
[None]
]
I would like to create an offset function that looks at my current row and the target row and calculates an offset such that I can just use my 'normal' steps of movement and calculate the corresponding target column. Is there a way to do this, or perhaps another coordinate system which I can use to do this more easily?
Thanks in advance!
I've tried a couple of things which I either didn't implement correctly.
I used a function to calculate differences in columns per row. If a my starting row contained 3 columns, while my target row contained 5 columns, than I added this difference to my target column. This however did not have the desired effect.
Edit 1* The offset looked like the following:
offset = BOARD_LENGTH[position_row - 4] - BOARD_LENGTH[position_row]
target = (position_col - 1 + offset, position_row - 4)
if on_board(target):
if empty_hexagon(target, board) or piece_color_on_position(target, board) != self.color:
move = Move(self, self.position, target)
self.moves.append(move)
where BOARD_LENGTH = [1,2,3,4,5,6,6,6,5,6,5,6,5,6,6,6,5,4,3,2,1](these are the amount of hexagons per row in my 2d board list.)
This implementation of an offset didn't have the desired effect, because calculating the valid moves of the pieces still gave me incorrect squares to move to for a lot of starting positions.
Edit 2* Since it from my original screenshots it looked like the knight was not moving 4 rows up and 1 column to the right. I'll add a screenshot here to show my coordinate system. Here we can see that we are in fact moving 4 rows up.Since we are using hexagons the hexagon directly on top of a hexagon is not 1 row up, but 2 rows up. Hopefully this screenshot will clarify this:

Okey, I think I have found an answer here thanks to Joe. First of all thanks everyone for taking a look at this problem. I'll post my solution here if someone else needs to look for a solution to this (or a similar) problem in the future.
Looking at the coordinate system that I used the task of formulating a formula that works would be impossible for me. Therefore I've changed the coordinate system to the following:
Instead of starting each hexagon on our board at 0, we imagine that there are hexagons to the left and right of this hexagon. At position (0,3) we imagine there being 3 hexagons to the left of it, and 2 hexagons to the right of it. Our board therefore now looks like:
Note* not all elements of this 2 dimensional list are populated with hexagons.
The problem is now more easy to understand. It looks like there is currently only a mismatch between even and uneven rows. If we go from an even row to an uneven row we see that the same column index is to the right of that same index in the even row. That is to say, if we have row 10, with column 3. If we were to move to row 9 column 3 we would move up one row and go to the right. This can be seen in the coordinate system shared in the screenshot above.
Now I currently only looked at the single movement action of the knight. For this I changed the code to:
And I added the following helper function to deal with the offset:
And this seems to be working for this single knight movement. As can be seen from the following screenshot (I also tested this for other positions, but this seems to be working):
It could be that I will have to do some more tinkering with different movements and offsets for different pieces, especially moving to the left of the board and to the right of the board. However, according to me this issue has been resolved and I have a way forward again. Thanks for all the tips!