Thank you for your donation!   Download the book!   Join the group!   Public source code repository
Showing posts with label status. Show all posts
Showing posts with label status. Show all posts

Life happens

Usually, I avoid writing in great details about whatever is going on outside this project since more often than not this then turns into its opposite. In the latest example, three weeks ago I cautiously mentioned that I'll have some family obligations, and won't be working on project for some time. What I didn't explain is that my sister (who lives in another town) is also co-owner of my apartment, and so she asked for her half to be either paid-off (for which I don't have enough money), or to sell apartment and split the proceeds. She promised to come over in October to help sort things out, clean, play tetris with furniture (since I can't go to her place, it's already crowded) while we hire somebody more skillful to do some modest renovations.

About a week later, I stumbled upon a friend of mine who also happens to have been working not just small home renovations, but basically everything except concrete pouring. I decided this is the guy; so, he's starting renovation works today. As evidenced by the lack of progress in the repository, I was playing furniture tetris already, since I had to clear rooms so that work can begin. Not only that, he was also helping me find my next place, which is fortunate. Thanks to his skillful eye he noticed all the things expensively wrong with one particular vineyard house I really liked (because it has almost all the amenities one gets in urban apartment), close to a small town I like; that expensive mistake was avoided.

Anyway, with works in the way, I won't be doing much in the repository for quite some time. Renovation works are planned to take between 4 and 6 weeks but, as is always the case, something unplanned will crop up. And after that is done, apartment needs to find a buyer, and I'll have to find my new place. In short, I can't say when I'll be able to start working on the project again, and how much (if anything) I'll be able to do in the meantime.

Status update

Hello, everyone! Here's a (bi)monthly update on things and stuff. I haven't wrote anything for last two months since I didn't have anything intelligent to say, except maybe "I'm still working on stuff". I still do, but now I wanted to share current status and a few thoughts with you.

First of all, as you might have seen it in my Codeberg repository, I'm still working on classical pieces, previously I supported all usual suspects (Bishop, Rook, Queen), then added support for Knight. Now I'm still working on King, I finished support for movement and castling on all variants, and wrote all relevant tests.

Now I'm working on checks if a field (and a piece on it) is under attack; or, should I say, again. Reason for rework is me being "clever" to speed-up development. Code was finished, tests (mostly) passed, everything was fine, except I overlooked pieces positioned between an attacker and a target. Sure, some are transparent to attacker, but not all. And so I had to get back to a drawing board, and the change isn't as simple as one would expect based on previously done code.

After support for King is finished, I'll start working on Pawns. I don't like to try to predict how long it'll take; but I'd like to finish it by early-to-mid October, since I might have some other (family) obligations, and most likely I won't be able to work at all for a week, or so (I hope); period of forced inactivity might be longer. Anyway, when support for Pawns is finished, I'll publish the very first public code release.

Generally, I agree with Drew DeVault that developers should do only code, and administrators should do distribution, but in this day and age that stance isn't very appealing, or convenient. So, I'll take a look at ways to make executables available for different platforms. So far, I have been ignoring CI/CD, or any other builders; on the other hand, application which isn't easily accessible is effectively dead.

After that, I plan on adding support for canonical variants in order of appearance, starting with Mayan Ascendancy; Croatian Ties is already supported. Recently, I started indulging myself again into thinking about changing some pieces and rules. I have already complained that Centaur might be too OP, even as I did significantly cut its reach. I already come up with a solution to straighten its course, but I'll leave this idea to take a proper shape on its own, rather then being forced into existence. You see, I really like its jumpy frolicking movement as-is, and would like to keep it if possible; problem is that at the moment I  really don't see a simple solution. Of course, if this come to pass, Waves activated by Unicorns and Centaurs would also get their straightening treatment.

There are also some other candidates likely to get rules updated, namely Starchild; regular visitors know I  already promised it'll get a proper revision, or at least a polish. Another candidate is Monolith, I don't like its diamond shaped movement pattern, it simply doesn't belong to it; but at that time I couldn't make my mind about simple to visualize, accelerating pattern. Yet another candidate is Serpent, although this change would be very simple; I'll just restrict its movement a bit, this time after I calculate its power compared to other pieces.

For now, this is mostly it. Take care!

The very first move

So far, I was trying to build game engine library which can do all variants and all pieces from the book right out-of-the-box. Recently, it occurred to me that might be a bite too big to chew. So, I decided I'll focus on simple and randomized variants, and support only classical pieces (+ Pegasus) at first. That way, I'll build complete stack, something useful for users, even if it's just a console application. Let me know if you'd prefer GUI application; depending on feedback, I might also do it. Of course, that would  mean more advanced variants won't be supported for quite some time. Currently, I plan to add them one by one, in order of appearance in the book.

Oki-doki, so I added support for all randomized variants, and simple pieces without special movement are all supported; that is Bishop, Knight, Rook, Queen, Pegasus. King can move, but currently castling is not supported. Pawns are also not supported at all, including en passant and promotion. So, only one side-effect is supported, that is capturing. Before I can publish first public version, I'll also have to add test if King is in check, and if a field is under attack (to test for legality of castling). Saving and loading current chessboard is also not planned for the very first release; simple (and randomized) variants can be played in one sitting. The same applies to in-game chess clock, I presume no one will play new variants in tournaments from the get-go.

How does it look like? Well, I took screen-full of texts from console application:

> new cc14u
   a b c d e f g h i j k l m n
   ---------------------------
14|r r n r n n r k b q b b n b|14
13|p p p p p p p p p p p p p p|13
12|. , . , . , . , . , . , . ,|12
11|, . , . , . , . , . , . , .|11
10|. , . , . , . , . , . , . ,|10
 9|, . , . , . , . , . , . , .| 9
 8|. , . , . , . , . , . , . ,| 8
 7|, . , . , . , . , . , . , .| 7
 6|. , . , . , . , . , . , . ,| 6
 5|, . , . , . , . , . , . , .| 5
 4|. , . , . , . , . , . , . ,| 4
 3|, . , . , . , . , . , . , .| 3
 2|P P P P P P P P P P P P P P| 2
 1|N R N B B N R B B K R Q N R| 1
   ---------------------------
   a b c d e f g h i j k l m n

this creates new chessboard for Classical Chess 14 unbalanced variant. As is custom across console chess applications; dark pieces are lowercase, while light ones are uppercase; in notation all pieces are written uppercase, regardless of color. Since Pawns can't be moved, today there won't be much of a game-play, but Knights can jump over them:

> move Nd3
   a b c d e f g h i j k l m n
   ---------------------------
14|r r n r n n r k b q b b n b|14
13|p p p p p p p p p p p p p p|13
12|. , . , . , . , . , . , . ,|12
11|, . , . , . , . , . , . , .|11
10|. , . , . , . , . , . , . ,|10
 9|, . , . , . , . , . , . , .| 9
 8|. , . , . , . , . , . , . ,| 8
 7|, . , . , . , . , . , . , .| 7
 6|. , . , . , . , . , . , . ,| 6
 5|, . , . , . , . , . , . , .| 5
 4|. , . , . , . , . , . , . ,| 4
 3|, . , N , . , . , . , . , .| 3
 2|P P P P P P P P P P P P P P| 2
 1|N R , B B N R B B K R Q N R| 1
   ---------------------------
   a b c d e f g h i j k l m n

and, there it is!

In short, there is still a long way to first release, this is just a peek into progress made so far.

One step back, two forward

So, I moved to new online Git repository, but since then there was no update on project status. Well, this is it; somewhat overdue, I admit, but with a (good?) reason. You see, most of my followers are chess enthusiasts, not programmers; so, I postponed my initial post since it's not that interesting, then got side-tracked, again (as one does).

In the meantime, there has been some progress on generating paths a piece can make, then comparing those generated paths with user notation, and finally executing a move if a unique match has been found. Due to a sheer scale and count of cases, tests has been separated into different executable:


All tests run One variant, since it's the most complex one, and features one of the largest chessboards in the book. One of tests (out of a few dozens!) is this one: "ta 9" command simulates user who typed "Bg3*N", and given the situation on a chessboard bellow, test then tries to establish if there is a full path (step-by-step) and side-effect (capturing), that matches user notation: 


The first thing to do is to find moving piece and its starting position. This isn't as straight-forward as one might think: there might be multiple pieces of the same kind, some with or without a tag, and sometimes opponent's pieces qualify as well, e.g. if activated in a cascade.


After finding a moving piece, all possible paths were generated; in the printout those are indented since they're all connected to each other, in one big, branching tree. The first line shows starting position ("d6"), then piece found at that position ("B", that is light Bishop) and its tag ("!", that is no tag found)., then activator (empty, since this is the first piece in a move), then momentum ("0"), which is still being accumulated ("+"). Lines starting with "<" are forking paths, i.e. all paths connected to it would inherit previous path segment(s), while lines starting with "^" are alternative paths, i.e. would replace other previous segments. Forking paths are used after the starting position, and after divergence. Alternative paths are used if there are multiple possible side-effects (interactions) between moving and stationary pieces; or, as an alternative path segment to a fork in a path. Note, alternative paths do not include displacements since there are too many possible destinations; those are handled differently (as a list of tentative (i.e. all possible) displacements, for each step).

All possible steps a piece can make are enumerated in a list, separated for each piece; enumeration starts from x-axis (3 o'clock) and then goes anti-clockwise. This is why here the first segment after the starting position goes all the way to "x26", then to "a9", then "a3", and finally to "g3". At that last path segment, application found dark Knight ("n"), with no tag ("!"), and established it can be captured ("*N" as a side-effect to the last step of a generated path segment). Momentum of a light Bishop at this moment is "3+", meaning that Bishop had already made 3 steps, and is still accumulating momentum.

Now all paths has to be generated by traversing path tree, and stitching together path segments from starting position to the very last step; each leaf node in a tree ends one path. Those generated paths are then compared to user notation, to see if there is a unique match. Except, that's not entirely correct; due to the need to maximize accumulated and minimize spent momentum, paths are searched for the shortest possible path, and then for the longest, if different. So, the longest path is preferred for the first piece in a cascade, otherwise the shortest path is used. Here, there is only one path possible, so it's saved as the shortest one, e.g. "d6.e5.f4.g3*N".

After unique path has been found, it's time to apply it to the chessboard:


As one might imagine, light Bishop left its starting position, and replaced dark Knight on a chessboard. Except, that is how it would have been done in a physical world. In virtual, digital world light Bishop on its starting position was replaced with None piece, i.e. the one used when there is no piece on a particular position; and then dark Knight on a destination field has been replaced by light Bishop after it has been stripped of its tag, even if it didn't had any. After movement all pieces lose their tag; but, tag stripping is such a simple operation that I didn't bother to check if a piece doesn't have any.

As you can see from a very cursory glance into game engine, it's not that simple to explain it, and it's even worse to implement. In the meantime, I was also trying to think of a simpler, more elegant solution to the problem, and it seems that I have found one. This is why I'll be ditching all this generating of a path tree, extracting each full path from that tree, then comparing it to user notation; and replacing all of this with functions for each piece specifically. That way, a lot of guesswork (but, what if a piece can diverge? is it transparent? to what?) can be eliminated, because in a specific function one has to handle only one piece (e.g. a Bishop) and can safely ignore interactions that are not relevant.

Why I didn't made such a transition earlier? Well, it took me quite some time to figure out that in a cascade I could use intermediary chessboards to communicate all the changes made in a previous ply, and then accumulate all those changes into the final chessboard for a move. The one thing I don't like about piece-specific functions is that can easily lead to a lot of code duplication, since similar code can be embedded in many piece-specific blocks; usually a lot of variables are shared between the two, making it difficult to refactor similar code into a function of its own. The other thing I don't like is that algorithm replaces data, and so no intermediary data is generated, and so the only way to check correctness of such a function is to debug. Oh, well ... nothing is perfect.

Even more variants!

I'm updating the book, even though only two months have passed since the last update, and not that much has changed since. In fact, the only real change is that I added 6 new, unbalanced randomized variants. As you might have guessed, those new variants are unbalanced because initial setup for each player is being randomized independently from each other. Also, there are no additional checks-and-balances, except a standard one for Bishops, so that half of them starts from light fields, and other half from dark ones. And all of this despite wisdom of the commons voting unfavorably against said unbalanced variants. Why did I add them, then?

Well, as I already wrote in the comment on LinkedIn, when sufficient number of elements are randomized, extremes tend to cancel each other out, so it's highly unlikely that one player will have too much advantage over the other. Second reason is because players should be able to choose which randomized variants (and flavors) they'd like to play. Additionally, players should also have an option to vote against a particularly unbalanced setup, if it's deemed unplayable; generating new setup is easy and fast. So, in the end, unbalanced variants might not be up everyone's alley, but they certainly don't hurt.

The book was compiled on February 12, 2026, version is 20260212.063826, and can be found behind that red button above, or in other usual places.

Moved!

Well, that didn't took all that long. I was worried because, honestly, I'm not much of an administrator. There are still some loose ends, of course, but nothing that should impact on a daily development. So, new repository is hosted at Codeberg: https://codeberg.org/mmlacak/crochess.

Old repository on GitHub at https://github.com/mmlacak/crochess was updated with new location, and then it was archived. Old repository is not mirrored, so it won't receive any further updates, but will be kept as read-only.

For now, this blog will stay as-is, I don't have much new content for it. You see, I thought I'd write in great detail about intricate design choices I made in code. Turns out, writing in great detail requires quite a bit of effort and time, if you want to introduce designs, and thinking behind them properly. Even worse, when I tried to actually write something, sooner rather than later I ended up with obsolete text, since in the meantime I also changed source code.

For instance, I wanted to write text describing CcPathNode, which is a building block for all possible paths traversed by a piece in a ply. Before I finished it, I removed subs link, because to compare each path in a tree with user notation I had to assemble complete path from root node down to ending leaf node, resulting in CcPathLink linked list. Substitute side-effects were used for displacements, e.g. every time a Serpent encounters a Pawn, there might be multiple valid choices, which do not alter moving piece path (e.g. Serpent in this example).

To prevent tree from eating all available memory, I made a simple linked list effectively just for displacements in CcPathNode. Problem is that substitute side-effect does not belong to any particular step, and so might end on e.g. the last one. Serpent can displace Pawns in each of its steps, so each CcPathNode would carry only one step (so that displacements list can be connected to their rightful step), which would be quite wasteful.

Moreover, choice made is not known in advance, so all choices has to be carried over for comparison, while still being attached to their proper step. Because user notation and generated paths share more-or-less the same data, the same struct is used for both. So, I had to add list of possible displacements to a CcStep, rendering list in CcPathNode obsolete, and so original subs list was removed. So, now each step in a ply could have either a displacement (for user notation) or a list of tentative displacements (for generated path tree). And then, after I finished changes, I recalled that Serpent has two choices after each step, so each CcPathNode in its tree will always contain only one step anyways, and with no bounds its path tree could contain up to 524,288 nodes, at 60 bytes each, giving a grand total of 30 MB ... so much for preserving memory. There are displacements in trance-journey, though, so not everything is lost ðŸ˜….

This explanation isn't very good, but you get the idea how difficult it is to convey the reasoning behind some design choices. Problem is, code is riddled with such intricate decisions, and sometimes I'm not even sure what is the best approach at times, until I try to do something, and then it turns out it has to be changed. On top of that, I have to write and maintain documentation (even if it mostly just enumerates what functions, macros exists with very little explanations) because it might also contain valuable warnings, concepts explained, without which I'd be also lost at code, with no navigation helpers.

So, now you can see why blog will mostly contain announcements when new book update is available, or when application goes live. LinkedIn group will also stay as-is, with mostly just links to blog posts.

New book update

I'm updating the book even though less than a month has passed since the previous update; the newest changes include:

  • rewrote checking opponent's King by Serpent,
  • tiny clarification, cascading en passant,
  • filled-in, clarified piece activations table,
  • removed activations on miracle-fields by Starchild, Wave,
  • removed Wave divergence on miracle-fields,
  • a bunch of tiny fixes, clarifications.

In a previous update I planned on making an exception to Wave's transparency, so that King behind it is not in check anymore. That has been revised, and so Wave transparency stays the same, and King behind it is still in check. Due to Shaman being able to capture multiple pieces in a single ply, I had to put forward rule that King is in check if it could be captured, if it was opponent's turn. Then everything else followed from there: if a Wave can be passed over by a piece due to its transparency, then attacker already have direct access to a King; and hence, King is already in check.

I also removed all activations on miracle-fields, except Starchild can still activate a Star. This is due to miracle- and uplifting-fields being the same, so it was hard to determine on-the-spot (when parsing user notation, building legal path, ...) if interaction is just an ordinary activation (on miracle-field), or it's uplifting a piece; because uplifting is a two-stage process, and so activation context has to be passed between plies, before anything conclusive can be known.

The book was compiled on April 2, 2025, version is 20250402.230028, and can be found in usual places.

En passant finally described! And checking opponent's King! More news at 11! Also, the book has been updated ...

I'm updating the book after only two months, since there has been some significant changes, including en passant being thoroughly described, for real. More detailed list of changes follows:

  • fixed side-effects table, added footnote
  • clarified displacement
  • described checking opponent's King
  • clarified static Serpent
  • clarified castling blocked
  • clarified piece actions
  • clarified Scout can be rerouted around any non-empty field
  • described en passant blocked, denied, turned into capture, divergence, ...
  • described activation after en passant
  • described multiple rushes, en passants in a cascade
  • described en passant in close quarters
  • described en passant affected by a Star, Starchild
  • switched to non-shifted tilde
  • and many more tiny edits, fixes, ...

While I was reviewing changes I made to the book since the last update, it also occurred to me that I gave too much leverage to pieces attacking opponent's King. Most pieces grew significantly more powerful, especially in late variants, while King remained the same it ever was, in effect making it much weaker against any opposing force. This is fine, and as it should be; the tricky part here is finding the right balance. This is why I already started changes to limit checks only to pieces directly "in line of sight" of opponent's King, meaning that King is in check only if all capture-fields between an attacker and a King are empty. In hindsight, what happened here is just me always leaning towards giving a player more choices, a piece more mobility; in short, more power for all; sometimes more power is just too much.

I also lean towards doing the same with Wave. Currently, due to its transparency, Wave cannot be hard-pinned to its King. With upcoming changes, Wave on a capture-field would nullify any check to a King behind it. The reason is the same one used to make Pyramid incapable of checking opponent's King, while at the same time that very same Pyramid can capture any other opponent's piece; it is to ensure all checks, checkmates are direct, simple to see, and reason about. It also helps that in doing so, it makes rules (and code implementing them) less fiddly.

It could be argued that transparency of Wave is hard principle, i.e. it should always work like that, without exceptions (which is true), and also that King would be sufficiently protected just by aforementioned changes, without changing Waves (also true). Counter-argument might be that directness of checks and checkmates is also hard design principle, i.e. no pieces between checking piece and checked King. Good game design promotes, and sticks to its own design principle hierarchy. To me, directness of checks, checkmates have precedence over any other rule; which means, transparency of a Wave will have to have an addendum.

I plan finishing changes mentioned here, then continue working on the code; book update will follow its own (give, or take) quarterly schedule. In the meantime, I'm also starting to think about revising One variant, namely Starchild could be reverted to its initial design, where any piece could activate it. Still, this is very low priority, and in very early stage; so, it most likely won't make it in time for next book update.

The book was compiled on March 9, 2025, version is 20250309.071052, and can be found in usual places.

Too much coffee

Since the very last post, I reverted most of the changes to the repository. Too little sleep, and too much coffee will do that to you. You see, I overlooked that out of 8 divergent pieces in the latest variant, 6 are available to any one player, and 4 of those are also transparent. Which means that every single piece in a move (and especially the ones starting a cascade) has to recursively build its path along chessboard, to find out its longest path.

Except, that is not completely correct; generated path for the first piece has to maximize momentum, not its length; and obviously enough, those two things are not necessarily the same. Also, I still need a way to filter out all generated paths according to parsed user notation, since it might contain specific fields visited, and side-effects exerted. And so, I do need a parser; hence revert.

Not all is lost, most of development on now archived branch was also merged back into mainline development; including newly assigned reposition symbol. I also renamed modules storing parsed notation, because those were all too easily confused with modules parsing user notation. Storage for parsed notation (at very least, steps and side-effects) should also be part of generated paths, since paths also has to contain everything encountered on a current chessboard.

Before I delve more deeply into generating paths, I plan to clean-up losing tags, try to resolve TODOs in parse modules, and also have parsing user notation covered with tests. As for tests, one can easily get drown in those, and still fail to test some peculiar interaction. I think, I should give up on testing all of interactions since there are simply too many of those, and cover only the simplest forms.

For instance, I should have one battery of tests just for step separators, the other one just for side-effects, and another still for ply separators, and one for move statuses; each of those should test only one separator, side-effect, status. It might be possible to generate tests based just on a chessboard set-up, and test all interactions that way. However, without a proper way to generate all legal moves for a given situation on a chessboard, it's too early to  think about it.

Early spring clean-up time it is, I guess. And after all of that, on to generating and filtering paths.

Conveyor-belt no more

You might have noticed in the repository that I already scrubbed clean C source code of all kinda working, but not all that useful modules. The problem is that design consists of all special cases, where every special case has its own super-special case; special cases all the way down. Trying to implement this in a super-uniform, context-agnostic code based on a conveyor-belt design is nigh on impossible.

So, this time I'll try different approach, and handle each piece and each interaction separately. Also, instead of trying to implement all of pieces and side-effects all at once, I'll start with one simple case (say, Bishop), and then do everything from parsing notation to applying that parsed ply to chessboard, just for that one piece. In short, finish vertical implementation, before going sideways (except for new Pawns ;). This will also allow for testing full stack before adding more pieces, interactions.

Downside to this approach is that adding each new piece, interaction will also require changes to already existing, and tested, API. Unfortunately, there isn't much I can do about that. Still, slow progress is much better than no progress at all.

Conveyor-belt, you ask? Well, in what seems like eternity, when dinosaurs roamed the Earth Flash-based games on the web were popular, there was one fun and engaging lil' puzzler, even if it featured sometimes wonky physics. So, when objective is to move balls to the other side of a valley, and gain some height in the process, what the most obvious solution immediately comes to mind? Conveyor-belt, of course! It works for sure, it's easy to understand, a bit grindy to implement; but hey, upsides surely outweighs its downsides, right?

If you'd like to try it yourself, here it is. Spoiler alert, conveyor-belt might not be the best solution, and by far.

Gentle sounds of Hilti in the morning

As you might have noticed, last few months were much slower than my usual. As I have announced last year, skyscraper I live in is undergoing major renovation works, even if it's one year late. Company managed to get additional year for works to complete, and now whole building sounds like, walks like and quacks like a busy building site; in short, it is properly noisy in my apartment during any work day.

While I do prefer to work during night, when there are as few distractions as possible, it's still a challenge to get some sleep, or do anything else in such a noisy environment. So, while I'll try to do my best, this mess will probably last for at least a year. Unfortunately, I don't have notebook PC anymore, so I can't even take my work to e.g. library and work from there. Will try to see with friends what can be done ... though, not holding my breath.

Book update and stuff

I'm updating the book, since previous update is already two months old, even though there aren't that many changes, but then again, there are no reasons to hold them back.

Changes from the previous update include:

  • divided, moved piece actions tables
  • fixed action tables for Pawn, Shaman, Wave
  • described mometum restrictions of actions
  • fixed notation, grammar for double side-effect (promotion + capture)
  • added examples, Pawns (not) blocked by Wave
  • described singe-step pieces and transparency
  • clarified diverging from opponent's Starchild

The book was compiled on July 21, 2024, version is 20240721.112914.

In a bit surprising, unexpected move (pun intended!), last month I decided to convert all of DoxyGen documentation into Sphinx, and also ditch my editor of choice (MS Visual Code, at the time) for something else. This was done mostly on some sort of an intuition, feeling; which is strange, since I'd usually try to do some (strategic) thinking, e.g. "syntax hilight is broken again, for xyz times", "folding comments is borked, again", "editor is getting too slow", ...

Each documentation system has its own strengths and weaknesses, just like everything else in life. I'm already missing DoxyGen warnings when e.g. functions parameters do not match content of a C file. Also, with DoxyGen, it's immediately clear what is documented, and what is not. On the other hand, for DoxyGen one better have editor capable of folding (unusual) comments.

Sphinx is much more crude, you have to specify everything by hand, write everything down explicitly, and even then stumble upon random bricks on the (yellow) road. For instance, files can be organized hierarchically; labels generated automatically from section titles are flat by default (!?), there is only option to prefix them with a filename (!?). As a result, all your sections has to be prefixed with context (by file name, by parent title, etc.); so you now have titles:

  • Piece
    • Piece data
    • Piece functions
  • Tags 
    • Tags data
    • Tags functions

instead of what should be default:

  • Piece
    • Data
    • Functions
  • Tags
    • Data
    • Functions

Sure, second option can be done, but then files might have to be split, sometimes into very small ones. It's no good.

On the other hand, Sphinx does not bloat source code files. It's free-form, and lets you easily organize any way you want, and document key concepts, designs, informal agreements, and so on. Currently, I plan to document libcrochess in parallel to its development; later I might add documentation for various build scripts (gfx.sh, pdf.sh, build.py, py/), and docs for off-screen-shot generator.

Converting documentation proved to be a bit grindy, but relaxing experience, although there were way more text to convert than I'd ever imagine I has written. Anyway, it's done now.

Changing the editor was a bit more pain. Unlike some (most?) developers, I'm not attached to editor I use. Still, I do like the ones that tend to disappear when I'm working, and have all the essentials: 

  • proper dark-mode
  • simple project management, as in a collection of files
  • find in (project) files, and with regex
  • search and replace in (project) files, also with regex
  • visual editor, e.g. commands are on clickable menu, or at keypress, not on a command line (i.e. vi is not for me)
  • split text panes, preferably both panes are proper editors

I tried Kate, but only very briefly, I wasn't able to set it into proper dark mode, since some GUI, window elements have either hard-coded colors, or under non-KDE desktop it defaults to some light colors. Tried to install some KDE control panel app, tried to  fiddle with some settings, only to fail, time and again. It seems I'd have to install full-blown KDE desktop just to set Kate right. Thanks, but no thanks.

So, I returned back to Geany, which is reasonably good, fast, small, and with selection of useful plugins. It only fails at the last item, and in a strange ways; you can split editor into two panes, but only one (left, in my case) is a proper editor with working key shortcuts, the other one can be edited, but most shortcuts don't work.

I asked devs, quite some time ago, it seems it's quite a challenging issue, since Geany was designed from the very beginning around assumption that one file will be ever edited by only one editor widget. There is a 2.0 version out there, but it does not come in Mint repository, since default gcc version does not support C++17; so I can't test if new version solved the issue. For what it is, old version is still quite usable. Shame it's not more popular, and made better.

Which left me wanting more. So, I tried Pulsar editor, and it's great. So far, I only find that it does not have "save all" option. Other than that, I have to say I'm not fond of Electron apps (and 750+ MB for an editor!), but here we are. I think I'll stick with it, for now.

Updating the book

I'm updating the book mostly due to constant interest from readers. There aren't too many changes, since previous update was just two months old. What surprised me is that there are some meaningful changes at all, I was trying to do much more on the programming side, and will continue the same (although, it's tough avocado to crack. Mind you, that text was written before divergence and transparency were introduced!).

Changes from the previous update include:

  • described tags in introduction
  • changed diverging rushed Pawn, now it can't rush again
  • clarified check, checkmate after activating a piece
  • clarified check, checkmate while diverging a piece
  • clarified Scout's forking steps
  • clarified Starchild's divergence
  • added rushing limits table, description
  • added castling limits table, description
  • described forward-displacement notation

The book was compiled on May 14, 2024, version is 20240514.045357, and can be found in usual places.

Finished once more

Oki, so the book is updated once more, and there are no more planned additions to it, so I'll call it done. That is, if I don't stumble upon a special interaction which was somehow left undocumented. For instance, I only recently stumbled upon rushing Pawn starting a cascade (nothing special here), which blocks capture-field of opponent's Pawn, so that en passant is not possible anymore (whoops!). Missing details like this are always a possibility, the best I can do is update the book as needed.

What I really wanted to write about is what didn't made into the book. First thing is a (semi-)transparency of Unicorn and Shaman. This isn't really a problem, but a nuisance; it adds so much in complexity, without enhancing game-play really.
It also does not make sense. I always tried to have all pieces congruent with their role, their story. And having physical entities suddenly becoming transparent to physical is not it.

Other things that didn't make it into the book are resized and expanded Classical Chess variants. I started doing it as casual remarks at the end of the book, but then realized that (if described in sufficient detail) these variants would significantly overgrow its casual remark status.
Worse, those variants actually do not belong to the book. Just as each piece has its story, so does the book as a whole. You most likely don't want to be reading synopsis for 1984, while finishing Alice's Adventures in Wonderland.

I was thinking for quite some time about a new book, where I'd  discuss mobility and calculated values of pieces in different variants. There is some chance that new book will be written, and  then alternative Classical Chess variants would be described in it. While I'd like to do it, right now is not the right time for it. That new book would be a major undertaking, and there are more important things I have to do.

My current plan is to finish game engine library and console application first. After that, I'll add enhanced PGN and other chess file formats support, and obviously document all enhancements done to adapt them for all Croatian Chess variants. And in a distant future, bot and networking support, then GUI application.

The book has been updated!

After almost half of a year, I'm finally updating the book. Changes from the last update include:

  • fixed grammar (castling, Serpent cannot diverge, Pawn-sacrifice)
  • clarified rushing, en passant
  • clarified blocked castling
  • changed Starchild transparency
  • clarified diverging to starting field
  • cleaned-up Wave, Starchild, Shaman intro
  • simplified resurrection destinations
  • described Starchild entering existing syzygy
  • redo Shaman's movement, capturing
  • clarified activating Wave by Shaman
  • added Shaman, Unicorn (semi-)transparency
  • removed Shaman, Unicorn transparency (yes, really!)
  • rewrote capturing, diverging Shaman
  • fixed Wave blocking castling
  • clarified Wave activated by Pawn
  • added Classical Chess chapter as an intro on how to read the book
  • added en passant turned capture
  • added blocked en passant
  • added transparency of pieces table, description
  • added piece actions table, description
  • fixed typos (thanks, RainRat!)
  • redo Pawn-sacrifice
  • started adding expanded Classical Chess variants, then discard them all (yes, really! #2)
  • improved images rendering (field-marker per corner, B&W per variant)
  • clarified trance-journey interactions
  • and more!
The latest update to the book was made on March 15, 2024, version is 20240315.011526, and can be found in usual places.

Streamlining

Usually, I would preface talk about the book with an (also, usually overdue) book update, then write something about plans for the future. Not this time. Changes done so far were minimal, and so it didn't make sense to update the book this time around, given that I'm thinking about reversing some of the changes made. Right now, I'm kinda stuck in the middle of a coding session. As soon as I put together minimal implementation for paths, routes, I'll do changes to the book, since it has priority over any code.

For example, one change committed to repository, but not yet in an updated book is clarification that all step-fields must to be empty when castling. This however is one of the carry-overs from classical chess, which doesn't have transparent pieces, and can be reverted back. After the change, Wave could be placed in-between castling Rook and King, and it still wouldn't prevent said castling.

Things do get dicey from here on, since then Wave could also be activated by either King or Rook. Sure, it could be done, and momentum could be calculated by simply counting step-fields traveled over by e.g. Rook. But, I don't like activating Wave while castling, since Rook is sort-of stepping over King, and castling is meant as an one-time super-special move, not a regular one. Maybe solution is to simply state that castling pieces cannot activate Wave, but are not obstructed by it, either; that seems the most reasonable design so far, will see.

Speaking of transparency, I'm also thinking about making Starchild transparent. You see, it kinda makes sense, but not all of the time. One design was to make Starchild transparent to pieces travelling over step-fields, but not over capture-fields. This would mostly just complicate things, but wouldn't do much for gameplay, since almost all pieces have the two kinds of fields lumped together, anyway. I tried to reconcile the two opposing design choices, but so far couldn't really make it work.

A solution (although, kinda cheesing it) could be to have Starchild transparent to some, but not all of pieces. For instance, Starchild could be transparent to e.g. Unicorn, Shaman, Starchild and naturally Wave, but not other pieces. Again, not really happy with this design, so I'll have to take a look into it. Although, past experience thought me not to relay too much on first impressions, sometimes necessary evil is necessary.

I have to admit I made a blunder: currently Starchild cannot be activated, and it's just by a simple decree ("you can't do that"). This is not good. What I should have done is describe interactions, everything else should be derived from that. In this instance, I should have written that Starchild can only be activated on miracle-fields (by other Starchilds), or on trance-fields (by Shamans). While net result is the same, one does not impose arbitrary limitations (and you already know how I feel about those), it just enumerates interactions.

Together with bad no-activation rule will go rule that material pieces gain one momentum from Starchild, by simply diverging from it. I don't know what kind of a brain-fart I had that day, but oh boy, it's still smelly. Solution is simple, if a piece has enough momentum, and Starchild is transparent to it, great; if not, it'll be blocked from moving any further, just like any other piece.

Another design that I'd like to simplify is set of potential destination fields for resurrecting syzygy. Other things that desperately needs simplifying are rules regarding multiple syzygies, be it a piece moving from one into another, or standing on a shared field, or something else.

In short, while the book is finished, some things are still settling, and it will take its time, just like everything else. On the other hand, if you look at classical chess, which is much simpler design, it took roughly a millennia to have rules more-or-less in its current form. As an additional bonus, I'm very, very slow; both in writing, and in coding. If you ask me, I'd say don't prepare your popcorn just yet ...

Updating the book & license

I'm updating the book, even though not much has changed since the last update. In fact, the only thing that has been changed is clarification of side-effects on pieces. Reason why I'm updating the book is because of licensing.

I always thought that simply stating "this book is published as public domain work" should be enough, anywhere in the world. Recently, I stumbled upon Creative Commons site, and I quote: "Dedicating works to the public domain is difficult if not impossible ...", and "... many legal systems effectively prohibit any attempt by these owners to surrender rights automatically conferred by law, particularly moral rights ...".

Now, I'm not sure what are any additional rights automatically conferred by law, beyond moral rights mentioned on Wikipedia site:

  • the right of attribution
  • the right to have a work published anonymously or pseudonymously
  • the right to the integrity of the work

I assume that situation is complicated, since every country has its own  copyright law, each unique in its own way; I'm not even sure how this is treated in a country I live in.

However, to me moral rights as listed above seems completely fine, they should not impinge on any major right granted by Creative Commons Zero 1.0 Universal Public Domain Dedication (henceforth CC0) at all, namely:

  • free access, and freedom to use the work as user wishes ("use" includes to run a program or to execute a music score)
  • freedom to access the "source" and use it as user wishes, for study or change it for personal use
  • freedom to redistribute copies
  • right to quote (freedom to redistribute copies of fragments)
  • freedom to distribute copies of user's modified versions to others 

From what I understand, if I have moral rights retained, only the last item would be affected somewhat; modified versions should be distributed under a new title, and with new authors, due to the right to the integrity of the work. I'm not sure if right to attribution applies to modified versions; for instance, if modified book should contain "this book is based on ..." clause somewhere in a colophon. It would be nice if it does, but it's not that important to me.

If that's all there is to it, then I'd like to retain moral rights, even if I have had put the book into the Public Domain. If there are some other rights that would prohibit any of freedoms listed above to any person, then CC0 should come into play, and waive those rights away; this is what I meant with "where Public Domain is not applicable".

The reason I put my book into Public Domain in the first place is to prevent any publisher from closing access to my book behind a pay-wall, and limiting its usage by the public, especially given that some publishers are getting very creative, when it comes to their own benefits. And the reason why I choose to go with CC0 is because it seems that simply stating "this book is in public domain" isn't exactly enough.

To summarize, the book itself (PDF file), source texts (TEX files), generated images (PNG files), photo (NEF, and JPG files) are all in  Public Domain, under CC0. Note that all scripts (SH, and PY files, including those used to generate images for the book) are published under GNU GPL v3+ license, as are the rest of source code (C, and H files). Licenses, and how to apply them are found in COPYING, and LICENSING files; in book folder for the book, and in the root folder of the project for source code, and scripts.

Edit: it's actually way worse than I thought. So, I decided to apply CC0 unconditionally, and to hell with moral rights; they are not worth risking any legal loophole which I might have unintentionally introduced, along with possibility to creatively interpret intended usage, and applied license. The book is already updated, and uploaded, both onto GitHub repository, and Google Drive.

Edit 2: CC0 is a dedication, not a license.

A bit more finished

... the book, that is.

I'm updating it since grammar is now finished, and all the polish it needs shouldn't mess with designs, rules, pieces. I say shouldn't, because I bit my tongue so many times already.

Updates include mostly grammar, and some side clarifications, like how to combine multiple side-effects, added some examples on how to diverge,  material pieces are now gaining 1 momentum when diverging from Starchild, all small stuff.

One thing that still bothers me, although much less so then before is that grammar alone (that is, without context) is not be-all-end-all reference. I have wrote it in the book, but it's worth repeating: entity (values) which are present only sometimes are not the same as optional entity (values). 

For instance, move status most of the time is not present, i.e. it's empty value. Except for checks, all other move statuses are mandatory to write. To sort-of convey that mandatory-ness to reader, I defined move status with an empty value, so that status after a move is mandatory not just in notation, but in grammar as well.

Similarly, Shaman stepping is not defined entirely correctly; issue is that Shaman has ordinary steps separated from capture-steps, and can switch between the two after diverging. Wave can be ignored only while making ordinary steps, but not capture-steps. However, both transparency and  capturing side-effects are optional to write, and so both steps could look the same. So, to keep things simple, I lumped all side-effects together, even though they are separated.

Lack of meaning isn't something that can be solved in grammar, and the book can only deliver so much, or so little. In the end, it's up to reader to build his/her own understanding. 

Anyways, back to the drawing coding board.

A look back, and forward

Well, that last update took way longer than I was expecting; there were no book updates for half a year. In my defense, life happens, and time flies, ever so faster. When you're young, it might seem you're invincible, nothing really bad can happen to you, and you'll live forever. Guess what, I'm in my fifties now, and this is no longer so for me. Sooner, or later, you'll too start noticing little annoyances, you'll slow down, you'll be vulnerable just like anyone else, ... if you still have parents, be nice to them.

Speaking of life, it seems it'll be happening more, and more in the future, too. Among other things, the skyscraper I live in is scheduled to have a major renovation, with works spanning a good year, or so. Or, maybe not, I'm not sure. You see, people involved in the project already tried to take advantage of naive owners at multiple levels, all the while it's mostly paid by the EU. I'm so tired of all the scummy local sheriffs; I wish EU would put a stop to it, but I'm pissimistic. Anyways, if project still goes forward, I'm not sure how much of work I'll be able to do, I assume I'll be all night-shifting for at least a year.

With the latest update to the book, I'll be so bold, and announce the book to be finished. Yes, you know, I know, it's finished, again. But unlike two-and-half years ago, this time I really don't see anything that needs to be added to the book. Sure, the book desperately needs a few finishing touches, and after that a good spanking polish, and before that I do need to finish grammar, and the last variant most likely needs rewrite. Still, all of this is non-essential in my view, and will be done at more leisurely pace, in parallel to the very next stuff I'll be doing.

What now needs to be done, is to start implementing all that new features I added in recent updates. That means, cleaning up existing code, and while it's not starting from scratch, it's not that far off, either. Just divergence added a major plot in the twist, so to speak, by adding a new layer of complexity when analyzing movement notation, and trying to reconstruct what actually was meant to happen.

On the other hand, starting almost from scratch does have liberating effect on some of code designs that are sub-par. For instance, when parsing notation, I also tried to validate some, if not most, of rules applicable to notation at hand. Prior to that, I was also going back-and-forth on validating things as soon as possible, and wasn't happy either way. Now it's clear to me, validating too early just complicated parser, while also made my job a lot harder. 

So, in the future, parser has to be completely separated from validating code. But more importantly, this little lesson also makes me rethink some of design choices I follow because they're good engineering practice. Good practice is a form of a generic design pattern, not necessary applicable to all situations, so maybe I should give up on them, just  like I did on trying to catch errors in input as early as possible. Sometimes, one has to relax, have another coffee, and accept that all errors will be caught when their (validation) time comes.

Updating the book

After quite some time, I'm finally updating the book. Changes from the last update include:

  • Monolith is opaque
  • Wave is not divergent any more
  • Shaman is now divergent
  • Centaur, Wave activated by Centaur cannot diverge
  • Unicorn can diverge
  • Wave activated by Unicorn cannot diverge
  • Serpent can displace Pawns
  • Monolith is noble
  • extended Serpent's movement limit
  • Monolith now constantly accelerates while moving
  • Serpent cannot diverge
  • Wave activated by Serpent cannot diverge
  • removed Monolith's movement limits
  • Serpent cannot loop anymore (in a single ply)
  • simplified trance-journey, fixed notation
  • added sense-journey
  • removed odd variants
  • added a new pieces: Scout, Grenadier
  • changed Pegasus symbol (G --> E)
  • and much more!
The latest update to the book was made on July 9, 2023, version is 20230709.134133, and can be found in usual places.