Some of you may remember that a few years ago (2018, so that's eight years ago now) I ported Cthangband from C to C#.
While this allowed me to remove decades of cruft from the code and make it a much cleaner object-oriented codebase, it had a couple of disadvantages. Firstly, I was compiling it as a WPF application which restricted it to Windows only, and secondly I was relying on the serialization capabilities of the .NET Framework 4.5.
Time makes fools of us all, and now both of those have come back to bite me.
Around a year ago, I switched from Windows to Linux due to Microsoft's increasing enshittification of Windows 11, Unfortunately this means that without breaking out a virtual machine I can't even run Cthangband any more, let alone compile it. And if I did want to compile a new version, I'm stuck with .NET 8 which doesn't have the old serialization functionality (it was removed for security reasons).
So, like the masochist I am, I'm porting it again...
I've been using Godot game engine for the last year, making a conversion of Ularn as a practice project, and I'm now reasonably confident with the platform. It has the advantage that it can build Linux, Mac, Windows, and HTML 5 Web versions all natively so it means I get cross-platform compatibility back, and it's also FOSS, which is a bonus.
It also has the advantage that I will be able to put the source for the Godot project online and people will be able to dowload/compile it themselves rather than needing to trust the download of a precompiled executable or installation script.
The big disadvantage is that Godot's native language - GDScript - is Python-based rather than C-based. So once again I'm having to port every line of code (a quick check tells me there are around 125,000 lines of code in Cthangband) from one language to another with a different syntax.
Except that this time I'm also having to switch from procedural code that occasionally idles waiting for a keypess to a fully event-driven model that runs in a main render loop and fires out events (or "signals" in Godot-speak) when keypresses and other input happens and which expects most of your code to run between frames.
I've not got very far yet, but the basic structure and user-interface is there and I've got as far as handling the main menu, loading/creating a new game, and going through the character creation screens. It's surprising how much I've needed to implement to get that far, because even simple chargen things need a lot of data and other systems to be set up.
For example, to be able to display the character sheet at the end of the chargen process I need to call the function that updates your character when a change has happened (in this case, the change being that the character is newly created). This function takes into account what your character's ancestry and profession are, which is fine because the basics of those needed to be implemented anyway for you to be able to select them), but also what effect mutations have on your abilities, so I had to implement the mutation system, and what effect your items have on your abilities, so I had to implement parts of the item system, and when your character's birthday is and whether they start at night or during the day, so I had to implement the game's timekeeping system.
So in terms of implementation, I'm taking a depth-first approach, slowly moving forwards in terms of progression into the game while diving deep into the subsystems required as I take each step forwards.
It's going to be a long haul, though.
While this allowed me to remove decades of cruft from the code and make it a much cleaner object-oriented codebase, it had a couple of disadvantages. Firstly, I was compiling it as a WPF application which restricted it to Windows only, and secondly I was relying on the serialization capabilities of the .NET Framework 4.5.
Time makes fools of us all, and now both of those have come back to bite me.
Around a year ago, I switched from Windows to Linux due to Microsoft's increasing enshittification of Windows 11, Unfortunately this means that without breaking out a virtual machine I can't even run Cthangband any more, let alone compile it. And if I did want to compile a new version, I'm stuck with .NET 8 which doesn't have the old serialization functionality (it was removed for security reasons).
So, like the masochist I am, I'm porting it again...
I've been using Godot game engine for the last year, making a conversion of Ularn as a practice project, and I'm now reasonably confident with the platform. It has the advantage that it can build Linux, Mac, Windows, and HTML 5 Web versions all natively so it means I get cross-platform compatibility back, and it's also FOSS, which is a bonus.
It also has the advantage that I will be able to put the source for the Godot project online and people will be able to dowload/compile it themselves rather than needing to trust the download of a precompiled executable or installation script.
The big disadvantage is that Godot's native language - GDScript - is Python-based rather than C-based. So once again I'm having to port every line of code (a quick check tells me there are around 125,000 lines of code in Cthangband) from one language to another with a different syntax.
Except that this time I'm also having to switch from procedural code that occasionally idles waiting for a keypess to a fully event-driven model that runs in a main render loop and fires out events (or "signals" in Godot-speak) when keypresses and other input happens and which expects most of your code to run between frames.
I've not got very far yet, but the basic structure and user-interface is there and I've got as far as handling the main menu, loading/creating a new game, and going through the character creation screens. It's surprising how much I've needed to implement to get that far, because even simple chargen things need a lot of data and other systems to be set up.
For example, to be able to display the character sheet at the end of the chargen process I need to call the function that updates your character when a change has happened (in this case, the change being that the character is newly created). This function takes into account what your character's ancestry and profession are, which is fine because the basics of those needed to be implemented anyway for you to be able to select them), but also what effect mutations have on your abilities, so I had to implement the mutation system, and what effect your items have on your abilities, so I had to implement parts of the item system, and when your character's birthday is and whether they start at night or during the day, so I had to implement the game's timekeeping system.
So in terms of implementation, I'm taking a depth-first approach, slowly moving forwards in terms of progression into the game while diving deep into the subsystems required as I take each step forwards.
It's going to be a long haul, though.