Croatian Chess is a collection of various chess variants, starting as a simple and natural enhancement to classical chess and growing ever more complex with each new variant.
Status update
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
> 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.
Moving (closer to) home
I have been using GitHub to host my online repository for over a decade now. The problem is that I'm getting errors -seemingly at random- like this one:
Too many requests
You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
Signing in may provide a higher rate limit if you are not already signed in.
For more on scraping GitHub and how it may affect your rights, please review our Terms of Service.
Contact Support — GitHub Status — @githubstatus
even if all I did was try to access a page with my own commits. Even more infuriating, those errors now persists even if I delete all the cookies.
Also, in not-so-distant future (I hope!) I might want to use CI/CD. However, broken GitHub implementation was one of the reasons why e.g. Zig moved over to Codeberg, and I'm inclined to do the same.
So, I'll be moving my online repository to Codeberg, and also primary email and probably even this blog. In short, there will be delays before I can continue development. In theory, it should be simple to switch from one online git host to another; in practice, there is a difference.
Home? you ask. Well, this time around I'll prefer European services, preferably non-profit.
Last edit: 2026-01-26 8:31 UTC
New variants!
Quite some time ago I wrote that I'd like to add some enlarged, but otherwise Classical Chess variants, but dismiss them as not belonging to the book, and requiring their own, separate book which would also discuss mobility. In the meantime, I kinda warmed-up to the idea that enlarged Classical Chess variants do belong to the book presenting new variants, especially since their objective is to make playing on large chessboards more approachable to average, casual player.
Currently, I plan on adding enlarged Classical Chess and Croatian Ties variants as remarks at the very end of the book; those variants won't be fully featured, but will include images. I'm not entirely happy with this design choice, since it will disrupt the flow of the book; but it should be worth it, given that this new book on mobility and such is still very far away, if it will be written at all.
I plan on adding 3 new Classical Chess variants, those will feature only pieces found in Classical Chess, with exactly the same rules, except longer rushes and castlings. I'll also add 3 new Croatian Ties variants, those would be nearly identical to their Classical Chess counterparts, but all Knights would be upgraded to Pegasuses (Pegasi?), and all Pawns will be of side-ways variety; this is to compensate somewhat for decreased mobility of Pawns, Knights on a larger chessboards. New variants will be played on 14 x 14, 20 x 20 and finally 26 x 26 chessboards.
New variants won't bring neither any new pieces, nor any new interactions. Still, I'll have to expand Python application which generates images for the book to support all new variants; later, library will have to be expanded as well. This will take some time, given my usual tempo of writing (which is very slowly) I hope I'll have the book finished by the end of this year.
Tectonic shift
It's unusual to have very base data model change this late in a project; any yet, here we are. Currently, I was implementing generators of all legal paths every piece can make in a ply. Since this change will disrupt development for quite some time, let me try to explain it.
The issue I'm talking about is that currently piece and tag enumerations are separated; which would be fine in almost all designs, since most of the time one data entity is indeed independent from any other, e.g. one person's year of birth is very separated from their phone number. This is not the case here, Bishop can never get "can rush" tag, nor Knight can ever castle.
Edit: Tags and pieces have very few, and very intimate relationships; usually tag can be attached to a few pieces (e.g. rush and en passant tags for privates). Technically, tag is a link between a piece and a field at which that piece is located. Once that link is broken (e.g. a Pawn has been activated and moved away), there is no more tag present (e.g. activated Pawn has lost its promotion tag) even if both a piece and its originating field are still present in a game. Most of the time the best data model is the one designed after real-life; this is why original design featured tags separated from pieces.
Another issue with separated piece and tag enumerations is that, well, they are separated. So, every function working with pieces (and in a chess game that means all of them) has to have two separate parameters. Yes, you can combine then in a neat struct, together with some other bits (e.g. a position) to bring number of parameters down; but, they both are now present in every struct you have to pass around.
Plus, they still take too much space, in fact, twice as much as needed; and that's after a change has been made quite some time ago, so that only 1 byte (char) is stored per enumeration instead of default 4 (enums are just fancy ints). You might think that we have moved past storage issues since like forever, but that is true only for local apps. For libraries, one has to consider possibility that it might serve many users at once, also it might need to do it on a restricted hardware (e.g. micro-controllers).
There is another issue with enumeration storage, and that's space it takes in a chessboard struct; again, currently it's double the amount it actually needs. Parsing user notation and applying it to a current chessboard is not an easy task; if undo is supported then one has to apply all moves performed until that point. To speed things up (and avoid doing the same job twice) position after performed move can be stored, and later retrieved. Only problem is, the largest variant has 676 fields, 190 pieces and 14 different interactions (losing tags are not counted, as they're result of interactions), which means it can last much longer than classical chess game. The longest recorded classical chess match in tournament was 269 moves, but legal match can stretch up to 5898.5 moves with 50-moves draw rule, or up to 8848.5 moves if 75-move draw rule is used instead.
For the record, move to me always means all actions performed by one player in one turn; this is different from FIDEs definition used above which define a move as white player action followed by black player action; for FIDE definition I use term cycle. Reason why I refer to move as such is because each player moves their pieces independently to each other (current chessboard position notwithstanding), there is a meaningful choice to be made; in fact, making a choice is the whole point of a game.
So, how long can chess game go in the latest and greatest variant of them all, the One? Honest answer, I don't know. I tried to guess-timate the thing, but it's probably wildly inaccurate. My guess is that tournament games won't last much longer than 18.000 moves, and technically legal games could probably go for 10.000.000+ moves; both with 50-cycle draw rule. This post is already too long, if you're interested to hear my reasoning, let me know in comments below.
As you can see, if undo is supported by storing chessboards, just having variant enumeration as an int in a chessboard struct can easily eat up to 40+ MB of space, just for that one enum. Undo chessboards could currently use 13+ GB of RAM in total; with changes proposed here implemented, that could drop down to 6.5+ GB. This is why I'll merge piece and tag enums, and also change variant enum storage to byte. Such a change will affect everything in the project; for the time, there will be development without (much) progress.
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.
Finished once more
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.
Simplifying
Changes described in the previous post are mostly done. I'll continue working on the book, hence no update just yet. There would be no changes to rules, pieces, designs; I'll be just clarifying descriptions, most notably, movement of Shaman really needs to be simplified. Another issue is that I put a few examples in parallel into just one image. Obviously not ideal, but also not sure if it would really benefit from splitting it up.
As for changes described in the previous post, Starchild has been made transparent to all pieces, Unicorn is now transparent to Shaman, and Shaman is now transparent to all own pieces (i.e. in the same color), and to opponent's Shaman. Sometimes you just have to take the plunge; I'm not really happy with this kind of a blunt design, lumping all pieces into just three categories. On the other hand it does make sense, and can't be really more selective, while also keeping its simplicity.
One planned change that didn't make it, is that Starchild can be activated only on trance- and miracle-fields. While that can be done, both Waves and Starchilds are kinda life-line; if player ever looses all of Waves and Starchilds, (s)he cannot cascade anymore, and cannot resurrect any captured pieces, which is a major setback. To leave opportunity to save at least some of those pieces, I decided to keep activation of Starchilds and Waves on its step-fields.
While castling is special, one-off move, in reality is not that special compared to e.g. resurrection, and so it can stand to a reason that it too should participate in a mundane cascades. So, Wave is now set as not blocking when castling, and Starchild is blocking only destination fields of castling pieces. As a result, castling can now also start a cascade.
With all of those changes made, I do plan on revisiting movement of Starchild, its activation rules, just to check if all of those are sound. In fact, the book as a whole could receive a little reading from me. Yes, really.
While I did wrote the book, changes are always made to one page, one example, one paragraph at a time. So, keeping track of all rules (and exceptions to those rules) is nigh on impossible. And yet, it's necessary if one is to check that all things are inherently congruent, to themselves, and between each other. So, I'm going to re-read the book to see if rules (and their exceptions) could be simplified while keeping their original spirit intact.
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 ...
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.
Putting some sense into a journey
Month has already past since the last post, and it doesn't seem much to be done. Anyway, more, bigger, and better plans to follow ;)
Sometimes, it seems when I put forward a plan, the opposite find its way to prove to be superior choice. For instance, I was ranting how I don't like arbitrary designs when discussing limits on Shaman's movement. Well, it turns out, it's way better to have arbitrary limitation in place, then deal with yet another massively OP piece, which isn't all that tricky to move, and so fails to reward skilled gameplay. This also fits nicely into general design of variants, where almost every possible rule has an exception to it. If Shaman's movement has to be that exception to the "no arbitrary limitations" rule, so be it.
I changed the way Shamans get entranced into trance-journey, and in doing so, I also wanted the same for Starchilds. Then I realized, it's a good time as ever to have two journeys divorced, at least in name, preferably also in named functions of pieces involved. So, trance-journey will stay in its original form, involving entrancing and entranced Shamans. Newly named sense-journey would involve at least one Starchild; starting with initiating piece (Shaman, or Starchild), then uplifting Starchild, and then uplifted arbitrary piece. Not sure about function names of pieces in sense-journey, maybe I should find different terms? Anyway, the two journeys would stay related to each other; the way entranced Shamans and uplifted pieces move would stay the same, as it would notation using @ sign. This is less then ideal, I'd prefer to have different symbol for encoding sense-journey. The problem is, I'm kinda out of ASCII symbols, and it would make no sense to use anything other than ASCII for English-based notation.
Another change that I plan to do, is to finally add Scouts and Grenadiers into the mix. I was thinking about it a while ago, but wasn't so sure about designs. Even though I put it on a slow burner, and never took time to think about it thoroughly, it bothered me for quite a bit, and primary reason is because current design adds large swaths of plain, old Pawns[*] which drown out all the other pieces, just with sheer numbers. Now I have made up my mind, even though not everything is clear; I still have to have movement rules and designs of pieces sorted out, before they can appear on a chessboard. Still, Scouts would be much more mobile version of a Pawn, while Grenadiers would be more dangerous, and more tactical ones. Collectively, Scouts and Grenadiers would be called Troopers, while Privates would be any of Pawns, Scouts and Grenadiers. I'll also leave promotion/demotion limited to just Pawns; so Troopers cannot be promoted outright, and has to be demoted to Pawns before they can be promoted. Movement limit of Monolith would also stay based on count of Pawns alone. In showing their Pawn descendancy, Troopers would be able to rush, and could be subjected to en passant.
[*] sideways movement notwithstanding
My immediate plan is to deal with some fixes to notation, namely divergence, displacements of Pawns by Serpent, then review/fix as needed trance-journey. After that, I'll do sense-journey, hopefully covering its notation right after it's done. And after that, I'll do Scouts and Grenadiers. And after that still, I'll update the book; it's been quite some time, and changes, both done and planned, are significant.
No title, just plans
Since my last post I changed Serpent to displace only Pawns, not all of pieces. I deem change necessary, otherwise Serpent would be able to break any formation, not just Pawn fortresses, which would be a little too OP. Breaking Pawn formations is good though, it opens up gameplay, and effectively limits static play.
This goes in as a preparation for another planned change, movement of Serpent should be unrestricted. Currently, there is some arbitrary cap in play, and you already know how I dislike arbitrary designs. So, plan is to remove cap, but also forbid loops. So, Serpent could visit any field, but only once in a ply.
Before you ask, Wave activated by Serpent will stay limited to two initially chosen directions. If I'd allow for such a Wave to move as unrestricted Serpent does, it would have half of a chessboard at its disposal, because Wave is transparent, and does not spend momentum while moving. Which all means, Wave activated by Serpent would be way too OP. So, that restriction has to stay where it is.
As for immediate to-do, I'll change way Shamans get into trance-journey. Currently, I sort-of abused Waves to activate the other Shaman, which can then optionally go into trance-journey. I'll simply relieve Waves from that duty, and have one Shaman directly activate the other one. This all will be done on neighboring fields, i.e the ones which are not step-, not capture-fields of neither light nor dark Shaman, so it'll be very specific, and very special movement.
Reasons for the change, you ask? For one, it provides build-up to trance-journey, and a warning to the other side what a player is up to, and also provides (a little) room to counteract. This is also similar how Shaman captures opponent's pieces; first it has to close a distance to its prey, then in next move it can go capturing. Second, trance-journey is now deliberate move, not optional, mixed with other side-effects. And this also makes it so much easier to figure out in parser, analyzer code; all good in my book B).
One thing that still hasn't clicked the right way is how Starchild is activated, namely separation between activation on step- and miracle-fields, combined with all the other Starchild rules, and exceptions to them. Sure, it all have logical explanations why they are that way, that doesn't make them right. So, I'll probably have to revisit those, before deciding what to do. One option is to forbid Starchild to be activated at all, that would simplify designs, and since Starchild still has a lot of other own stuff to do, that might not be too much of a loss.
Another thing that I stumbled-upon is a realization that complex mechanisms are not explained properly, i.e. one simple mechanism at a time, and only once. I figured out, I have a tendency to stuff all of mechanics into one example, and then repeat that poorly explained mechanics over-and-over again. No good. I mean, that was main reason why I rewrote Miranda's Veil. This is, of course, completely my fault; such is a price of learning things by doing them.
But now, it left me wondering, what if I revisit all of examples from the very beginning, and rewrite all that needs to be redone? This can be done, and I think I should, since it would make the book so much better. The only problem I see is that it'll take months to finish, quite possibly to the end of a year. Again, this is something that I won't be rushing into, I'll take my time to decide if, and when I want to take the plunge.
Just to clarify, complex should not be confused with complicated; complex things are comprised of a few other, smaller things, all of which are -in, and off itself- simple. Complicated things are just spaghetti-designs, many things arbitrarily bolted on top of each other, without any regard for consequences.
Divergence on the run
I made two relatively small changes to Serpent, namely now it can displace pieces in its path. This is similar to Shaman, but without the need to be bothered with super-special, secondary movement. Given that Serpent's meandering movement lends itself nicely against opponent's Pawn structures, this might also help break those fortifications, even without capturing anything.
Another change is that I finally extended the range of a Serpent, it can now do up to 16 steps, up from 9 steps. I'm still not completely satisfied with Serpent's design. Issue I have is with arbitrary limit which has to be put onto Serpent, otherwise it would be able to loop forever, and build infinite momentum. Either I'll make loops illegal, or straighten Serpent's path in some capacity. Although, having a piece preloaded with Bongcloud-level of pure, unadultered fun is not below me.
I won't be updating the book just yet, these changes are too small to warrant that, especially because I plan to do larger changes in the immediate future. One planned change is to move divergence from Wave onto Shaman, Wave would stay transparent. Obviously, this means moving all divergence sections into Conquest of Tlalocan variant, and redo all the examples, and reword all the texts. Not difficult, just physically large change.
One other change I was thinking about was to change how Monolith moves. Currently, it has uninspired, fidgety, but still unrewarding pathing. I was thinking about changing it into accelerating Centaur, with each jump longer than previous one, preferably without an arbitrary limit to its movement. Obviously, each step has to be chosen independently from any previous choice; problem is that might turn Monolith into super-duper OP Centaur, which can reach any single field from any position on a chessboard. This is not good, even if Monolith cannot interact with any piece, so I'll try to find something more reasonable.
One crazy possibility is to limit Monolith to the number of Pawns a player posses. For instance, if light player has 5 Pawns, Monolith moved by light player can do only up to 5 steps. This also fits nicely into gameplay; at the beginning Monoliths can do a lot of steps, but are cramped on board, as game progresses Monoliths are not so confined by sheer number of pieces, but are limited by number of Pawns still on board.
And last (but not least), there is a common, recurring task; that is to sit down, and reread last two variants, and simplify (or, at least, clarify descriptions of) syzygy, and other rules regarding Monolith, and Starchild. I don't like it, but those needs to be done, to be able to hold all rules in ones head at the same time.
Book is updated
I'm updating the book, quite some time has passed since the last update, and only two small changes have been made in the meantime.
Changes since the last update:
- simplified description of Wave movement, if activated by Serpent
- removed Terms from Prerequisites
The latest update to the book was made on September 9, 2022, and the version is 20220908.223634.
I also removed all links to book preview.
Book is close to finished, I don't plan any major changes, and certainly not stretched over many months, or years. Some smaller, but still significant changes could make it into the book, e.g. extended Serpent movement. Again, this is not something I'll be doing in a hurry.
For now, I'll try to work more on library.
Edit: just as I wrote "work more on library", it occurred to me that Wave should be made transparent, i.e. it makes sense to allow other pieces to pass-through Wave, just as Wave can pass-through all the other pieces. This would also make defending Wave easier, since it has to stretch out to activate anything, and most interesting pieces to activate are opponent's.
Since the book is the most important part of the project, changes will be made immediately, after which coding will resume as usual.
Stuck in the middle of the book
I planned to redo complete parser thingy from scratch back in February, but before that a short detour to revisit book, more precisely, activation rules and do quick fixes here-and-there, then get back to coding.
Except, one thing leads to another, and here I am, two months in and still at quick detour. One reason is that I have to explain all emerging effects of rules, and new concepts in greater detail, and slower pace; so I have to redo quite a few examples. Another is that I wasn't happy with Miranda's Veil for quite some time now, so I took the opportunity, and rewrote the whole chapter.
I prefer to have a few simple rules from which all other emerging effects can be derived following logic. Sometimes, I get it wrong. For instance, last piece in a cascade can never check opponent's King, even if it has enough momentum and King is within range. This is so because activated piece, once it starts moving, can't change direction of its movement. So, to be checked, opponent's King would have to be positioned in a chosen direction before cascade even starts, which would mean King was checked before cascade even started. So, precheck and precheckmate can never happen. This is not the only thing I got wrong, or simply overlook, but it illustrates how nuanced things can become.
It's not all fixes and rewrites, either. I recalled that I read a paper on AlphaZero evaluating Classical Chess variants, so I recently added sideways moving Pawns into the fray, from Nineteen variant onward, to spicy things a little bit. I mean, c'mon, how can you say no to: "This is the most perplexing and “alien” of all variants of chess that we have considered. Even after having looked at how AlphaZero plays Pawn-side chess, the principles of play remain somewhat mysterious – it is not entirely clear what each side should aim for. The patterns are very different and this makes many moves visually appear very strange, as they would be mistakes in Classical chess. Lateral pawn moves change all stages of the game. Endgame theory changes entirely, given that the pawns can now “run away” laterally to the edge of the board, and it is hard to block them and pin them down." (assessment by Vladimir Kramnik).
It doesn't hurt that sideways Pawns are very roughly twice as valuable as ordinary cousins (which is very much welcomed for variants on an ever growing chessboards!), they offer more potential moves from the very beginning of a match, doesn't upset the balance of the game, doesn't slow down gameplay, ... all the good stuff! Would you be surprised if I tell you that I'm seriously thinking into doubling-down on sideways Pawns? I'm considering to introduce 2 new pieces, Scout and Grenadier, both remains in Pawns category (can be promoted, demoted-to, captured in Pawn-sacrifice, ...), but each with different movement. Issue is that now I'd have 3 different Pawns, and so I'd need to change en passant, and all other examples that involve Pawns. Also, introduction of Pawns category means now old Pawn piece has to be reintroduced as Private, to be able to distinguish between Pawns (category) and Pawn (old piece); this is huge undertaking. I'd like to postpone it, but I also very much like the idea, especially because thematically if fits so neatly into the book.



