Ossa Sepia

November 9, 2025

The Pumpkin’s Problem

Filed under: Sense and nonsense — Diana Coman @ 4:53 pm

…is that it’s too soft, really. Sure, there is some icky factor at getting the whole soft entrails out of a pumpkin but that’s about it 1. And by the time a pumpkin is carved, lighted up from inside and possibly even danced about by kids in costumes, it’s really hard to keep a straight face and not burst out laughing, what fear and such?

While I don’t usually get drawn into the whole Halloween thing, this year the very young 2 being as it were really too young to know better, insisted and persisted, quite unsure as to why and how one might be in fact so utterly uninterested really – not against it, nor for it, but simply entirely outside of it. So they got all dressed up, put on their best impression of supposedly scary witches, brought me their pumpkins and pleaded rather unwitch-like for my taking part in it.

As a result and possibly adding to the lack of scariness at the time, some silly childhood rhymes came to mind instantly and I let them come out loud, too, seeing how they applied all too well to the situation at hand:

Sunt vrajitorica Ica
Bataie imi da mamica
De nu-mi place mancarica.

Or in English this time:

I’m the witch whose name is Itch,
And I’ll get it from my Mummy
If I claim her food’s not yummy.

Seeing though the rather long faces of such young witches, I relented and asked for a knife instead. They brought me the biggest knife they could find and it was indeed quite big – their choice, not mine, worth noting. And I started carving a pumpkin, but had to tone it down quite quickly as it was starting to cause comparisons and pumpkin-envy, seeing how I didn’t know there was a scary pattern to follow and apparently approved-of, familiar “scariness” and so on.

What can I say, it turned out that applied geometry can get scarier than anything, the new and unknown can get more interesting and the trouble’s not that I mind scary, more that if one insists to go looking for it, I’d rather they went quite further than it’s usually prescribed.

And since I was at it, other rhymes came to mind and I let these come out too, with the right intonation, with the large knife in hand:

Vaier trist prin camp ofteaza –
Vin strigoii, se-ntremeaza
Abur alb de prin sicrie.
Voi, crestinelor popoare,
Faceti cruci mantuitoare,
Caci e noaptea-ngrozitoare,
Noaptea Sfantului Andrii.

The original of the above is from a poem by Vasile Alecsandri, called “St Andrew’s Night”. I’m still not even happy with this version in Romanian, let alone trying to translate it now but here’s at least the gist of it in a quick translation since any translation is likely better than none:

Gloomy cries traverse the plains –
Ghouls are coming, slowly shaping
Out of vapours from their coffins.
Faithful Christians of the world,
Make your crosses at great height
On this fateful, frightful night
Of Saint Andrew’s!

As the witches in the audience were suddenly rather unsure and crowding together, I stopped there and let it end at that. With smaller voices than earlier, they asked eventually what that was exactly and knowing at least the name of it seemed quite enough for them this year – after all, I didn’t want them to have trouble sleeping that night. So they got the pumpkin I toned-down carved along theirs, they got them all light up and they even got a picture with their cousin too, so it’s all on record.

But the deeper trouble left for another time is that the verses above are already adapted, since the original is rather limping and unsatisfying to me. There is a lot of depth to the subject for any writing to bring out and feast on but somehow it fails more often than not and so each time I think of this poem or other similars, I end up itching to dive into it and make it say at least some of what it keeps avoiding 3.

You see, if a pumpkin’s problem is that it’s too soft, a garlicky garland or even a garlic clove, whether whole or crushed has no such issue – it’s neither soft, nor light in either sense, nor even easily ignored with its knobbly and tough outline, with its pungent and utterly unavoidable smell 4. And witches and devils are such generic archetypes as to lack any truly scary specifics – where I’m coming from, there’s a whole detailed panoply of lost, doomed, angry, evil, twisted, life-hungry and life-adverse creatures on the other side of that life-death divide that gets supposedly dangerously thin as the winter comes in, whether it’s the end of October in some places or the end of November in others 5.

And the trouble is that if I’m to talk of these, I’d rather do them justice – which is apparently way easier said than done, hence why I usually steer away from even trying. Because the whole point of such creatures being on the other side of life means exactly that, namely that they are the needed complementary part, deeply scary and even troubling so. If they are truly troubling it’s exactly because they actually match all too well a certain reflection of the known world, not because they are “less” in any sense of the word.

It’s quite the opposite, they are scary precisely because they are really easily recognizable as mirror images, entirely and utterly opposed and thus fundamentally hostile and unavoidable at the same time. There is no real “conquering” or “defeating” them, either, just like one can never truly “win” without losing at the same time, whenever one is really fighting oneself. There’s only balancing them and such balancing is done better or worse at any given time. Accepting both the reality and the requirements at times unpleasant, at times painful of that balancing act seems to me to be closer to what the whole winter-night thing is all about.

Then again, perhaps the whole point is to look to the other side for a moment, even if not really aiming to truly see it, even if only squinting on purpose to make sure one doesn’t end up seeing even by accident more than one bargained for. Hence the pumpkins with their crooked smiles, their warm lights in the night and the sweets they bring – to lull the senses into thinking that it’s really only the shape that’s perhaps seemingly scary but ultimately inoffensive. It’s just the shape that is at odds, not the essence, right?

One can almost hear the unspoken “it has to be” in the above… Then again, garlic never makes sweet pies, only tinctures, sauces and even soups, all strong and clear, at times even smoky, invigorating or even supposedly curing all sorts of ills but never ever plain sweet, not even in the slightest…

  1. I suppose some pumpkin meals could be indeed way ickier if one has to eat them and even downright scary if left long enough out in the open, but that’s not even on the Halloween menu as far as I know it.[]
  2. My nieces, 8 and 9, respectively.[]
  3. I suppose the “American Gods” by Neil Gaiman at least has a better stab at this than most others and unsurprisingly it draws from every mythology or even scrap and shred of folk lore he could find, as far as I can tell.[]
  4. And no, I’m not talking of “vampires”, sheesh. What next, pointy white canines, tomato-blooded smiles and polyester-silk capes as the height of scariness?[]
  5. St. Andrew’s night is the 30th of November in the Orthodox Calendar at least.[]

October 12, 2025

Bounded Containers Abundantly Leaking

Filed under: Coding,Open Sores — Diana Coman @ 10:58 am

It’s not as worse as it sounds – bounded containers abundantly leaking are still better than bounded containers unboundedly leaking, so there’s hope! And there are also unbounded containers that can at times be as good as to not even leak, it would seem. But to start from the start, let’s go through some basics first, as to what these containers even are and how did it even get to such investigations into what they might leak or not leak, when, where and to what extent.

Containers in Ada are these useful data structures for holding other data, generally in an organized manner that may be quite a good fit for various uses: vectors, doubly linked lists, hashmaps, sets and so on. According to the Ada Reference Manual (ARM), the standard library provides two 1 implementations for each type of container, with a different approach to handling the overall capacity: bounded (fixed, unchanging capacity) and unbounded (variable capacity changing as needed in use).

Before measuring anything, my own view of these two types of containers was quite simple:

  • Bounded containers: having a fixed capacity known upfront means that bounded containers don’t require dynamic memory allocation. Therefore, they are also the safer option to use whenever possible since there is no danger of memory leaks.
  • Unbounded containers: having a variable capacity that changes transparently while in use means that unbounded containers rely on dynamic memory allocation and while absolutely needed at times, they are best used sparringly since they add to the complexity of the code and they don’t provide any way to control or even query with respect to their actual memory allocation, deallocation and use at any given time. Moreover, in GNAT at least, they rely silently and entirely on the automatic mechanism for memory deallocation, the Finalization, which is great in theory indeed but turned out quite a no-go at times, in practice.

Such was the view based on what things are described as, combined with some limited experience using them. But then this whole got put to the test in the usual manner – views are to be acted upon if they are to be anything, not just “expressed” or “held”. Meaning that I took the above to inform my implementation of Ada code at all times. As a result, I had quite soon enough concrete and even stress-testing use of code with bounded containers to start noticing some unexpected inconsistencies: far from being entirely predictable in terms of memory use, code that relied entirely on bounded containers and never touched in any way any unbounded ones, was quite clearly ever-expanding in its memory use and needs.

Inconsistencies being the cleavage that they are between expectations and reality, one can certainly stare for quite a long while at them but that doesn’t heal nor solve much at all. So I set out instead to test and actually measure as much as possible what was really going on with each type of containers and with that pesky Finalization to boot.

First of all, it turned out that the GNAT bug previously found had less to do with either Iterators or Finalization specifically and more to do with the subset of restrictions that are enabled (or not) at compile time. In fewer words: the same code compiles and runs perfectly fine when there are no restrictions but as soon as restrictions are added, it’s anyone’s guess what the result might be – some specific subset or the way in which restrictions combine result in the shown bug.

Good luck tracking down the exact subset of restrictions or concrete problem when a GNAT bug pops out at times depending not even on a single restriction but on a subset of such and how they end up interacting towards the final result. The only practical way forwards with this is to note that restrictions turn out in practice more of a bug than a feature if one wants to use the full set of the standard library code otherwise. So the reality is that restrictions may be of use only in very tightly controlled cases but otherwise in general one is best served to compile without any restrictions and leave it at that.

Second, and compiling therefore everything without any restrictions, here are the results of calling in a loop 10`000 times a procedure that creates in turn 1000 local containers with a minimum of one element of their own, when using standard library unbounded and bounded hashmaps, with and without a further hashmap of hashmaps, too 2:

  1. bounded hashmaps, with hashmap of hashmaps: LEAKING memory: Virtual 3 use from 6788kB to 9916kB, Real 4 use from 720kB to 4088kB.
  2. unbounded hashmaps, with hashmap of hashmaps: LEAKING memory: Virtual use from 6704kB to 6836kB, Real use from 748kB to 1084kB.
  3. unbounded hashmaps, with hashmap of hashmaps, with clear explicitly called at the end 5: LEAKING memory: Virtual use from 6804kB to 6936kB, Real use from 780kB to 1108kB; PEAK virtual use from 6804kB to 6936kB.
  4. bounded hashmaps, without hashmap of maps: LEAKING memory: Virtual use from 6788kB to 9912kB, Real use from 720kB to 3936kB; PEAK virtual use from 6788kB to 9912kB.
  5. unbounded hashmaps, without hashmap of maps: NOT leaking memory: Virtual use from 6804kB to 6804kB, Real use from 772kB to 896kB; PEAK virtual use from 6804kB to 6804kB.

At least the inconsistencies were consistent, as it happens – as surprising as this might be, unbounded containers are in fact more reliable than bounded ones, in all cases. And on top of this, if one actually uses any container, whether bounded or unbounded, with elements that are themselves containers, memory will leak anyway – it’s only a matter of how big a leak, not of no leak, with bounded containers abundantly (or even unboundedly?) leaking, while unbounded containers at least leaking way less.

In practical terms: restrictions are best unused and then 6 unbounded containers are better than bounded ones in all cases, offering no leaks when elements are plain enough and at least minimal leaks where elements are themselves containers.

For completeness, the test code used above: memleaks_libcontainers.tar.gz

Keksum: 87d831b1e8d2615252b7f7f8f06e3f72e293c613b980d1634814b39ca2fc008ca010d8bd850bf9fefcf49b165e5a669d5c62650becc68c35f9163d4ac8d697dd

  1. If one looks at the type of data that can be stored in such a container, there is a third type, the “indefinite”, which allows in principle more flexibility with respect to data types it can handle. These are however not relevant for the discussion here since they are quite entirely separate from both bounded and unbounded containers otherwise.[]
  2. Memory use as obtained from parsing /proc/self/status []
  3. VmSize[]
  4. VmRSS[]
  5. This was done with the small hope that perhaps an explicit clear will help – it doesn’t.[]
  6. Only then, though. With restrictions in, the unbounded containers are quite useless.[]

August 20, 2025

Improved VaMP Support for Direct Communications Use

Filed under: Coding,VaMP — Diana Coman @ 3:02 pm

As with the previous additions to VaMP, these latest improvements are simply a direct and prompt answer to its increased use. Growing only when and as needed, but promptly and easily so, just check the exact dates and tell me in how many cases exactly can you truly get a tool to adapt to your needs so promptly and with so little overhead, let alone without other costs of all sort?

For the concrete uses that prompted this, first there was some play with VaMP keys and messages that highlighted some specific ways in which VaMP could be more helpful when used straight from the command line for communication matters. While up to now VaMP has been in daily use for years already, such use has been either through other code mostly, where the communications part is concerned, as part of the client for Eulora 2 or otherwise focusing more on code versioning – with the result that these parts got the most feedback as well. As the actual use increases and expands in scope, there is more to inform any needed changes or additions, so these get done and then put straight to use to be further iterated if and as needed, neither more nor less, which is exactly the best way to go as far as I’m concerned.

Quite immediately following the above, even if less publicly visible, there was as well the push towards switching all of Eulora 2’s client deployments to VaMP only and this added a request to better support some minimal automation for discovery and filtering of relevant patches. So I added it all to the growing list, proceeded then to implement, test, deploy and keep it all in sync across all relevant places, with the result bringing in enough changes that it makes full sense to document them here as well:

  1. Added command fingerprint to calculate and display the fingerprint of a key from either its .pub file or its .priv and salt files. While VaMP always did this internally and used the fingerprint as well to name the files for newly created keys, up to now it didn’t expose this for the user to call as they wish, since there was no specific case requiring it. As it turns out though, when people exchange keys, a way to check the fingerprint would be rather handy so now it’s made available.
  2. Added command pubkey to extract just the public part from a private key and write it to the usual .pub file format that can then be used just like any other .pub file.
  3. Added command sim_go to only simulate a “go” – meaning to find and list the full set of patches that make the shortest path to bring a given directory to the final state of a given target patch, without actually applying those patches. This is quite helpful for supporting some minimal scripting or other similar automation that needs to identify and find the relevant patches and their files e.g. for deploying or updating some deployed version rather than for direct code versioning as such. For the full case where one actually wants to obtain the final state of a given target patch, the previously existing command “go” remains as it was and does it all.
  4. Improved and more precise checks of the pub, priv and salt files so that the content is indeed more important than the extension at all times and when there is some obvious error or mismatch, the error message is, hopefully, more useful, too. Note here that these checks are provided to help the user figure out what is wrong whenever possible but they *cannot* be truly infallible – there are and will always be cases where the inputs *look* right enough to pass these checks but still are in fact quite different from what the user intends them to be, with the result at best an error further down the line, at worst something that looks still right but then fails to serve. There isn’t really much to do about this currently and especially not while fully preserving at the same time the core desiderata of any encryption scheme. Of course, compromises of all sorts can be made at any time but at least for now, I don’t think there’s any need for such compromise here.
  5. Fixed the issue with the way paths were handled when encrypting or decrypting files that are not in the current directory. With this fix, one can decrypt or encrypt a file in another directory and have the result written there as well, too.
  6. Added a double-entry and corresponding check of the password when creating a new key, bringing in this sense VaMP closer to the more usual practice of password creation I suppose. The similar use through the graphical user interface of the client’s can avoid this by enabling the user to actually see what password they entered and thus check it as and when they want but the command line doesn’t quite have the same option and so it has to go with what it can do and force a double entry. Perhaps if this gets too annoying, it can get an option in the .ini file to toggle it on/off but for now at least it’s simply on at all times.
  7. Added a check and prompt for confirmation whenever adding a new root patch – meaning a patch which does not currently have a direct parent in the known or given set of patches 1. This is to better support users of larger code bases and patch sets, so that there is some reassurance that no accidental breakage of the tree happens without notice, even if one doesn’t manually check the full tree each time they add a new patch. The cost for this is a further delay when adding a new patch, since the additional step has to search the full set of known patches for any known parent. In practice, I don’t find this too much of a cost to pay and moreover, if it ever gets to be too much, one can always simply use a reduced set of patches at add time to keep the benefit while greatly reducing the cost.
  8. Updated the check of the manifest file for a more flexible approach to code versioning since the various use cases that come up when having editions on top of local and shared development versions rather need this. Consequently, while the code checks the manifest files as before, a fail of such checks will prompt the user to review and confirm if they still want to proceed, rather than just forcing an abort entirely.
  9. A small code-level change, mainly ditching the use of Exception_Information throughout because its implementation in GNAT is rather dubious if not buggy altogether – suffice to say that I managed to get it to overflow its stack in a different, much more complex scenario and while I am not that bothered to fully hunt or document this currently, I will still just blacklist this method entirely. The experience did prompt a closer look at the GNAT implementation of Exception_Information and such look rather supports the blacklisting: for some reason, this function needs to follow pointers through what can end up as quite convoluted links. At the same time, there are other two functions that fully provide what I need otherwise, namely Exception_Name and Exception_Message. And these two functions take a much more straightforward approach, not following any pointers and just returning what is requested. As a result, they get used and the other one gets blacklisted, that’s all.
  10. An internal small but overdue refactoring of the way the default paths for patches, signatures and keys are handled so that they are now in a single place in the file_io package and overwritten otherwise by values read from the .ini file if such are present.

That’s all for now, let me know if you give it a spin and how it works for you. As amply documented by now, help for any productive use is still at hand when, if and as needed and asked for.

  1. Note that this doesn’t mean nor can it ever mean that this is or will forever be a “root patch” – there is no such thing, since it’s all a matter of context. Any single patch is a root patch by definition and any root patch can become a non-root patch if and when there is another patch that produces its exact, full input state, that’s all.[]

August 9, 2025

My Public Euloran Key

Filed under: Coding,Eulora — Diana Coman @ 7:43 pm

It started, as usual, with players’ activity, this time automated bots and desire to gain access to such, payment concerns and the available avenues to reward useful effort. The conversation got longer than usual and spanning a couple of days, too, but perhaps the snippet below is the best introduction here, since it is quite part of what triggered this publishing of my key now rather than at a later time – if he’s going to play with Vamp on the keys side, might as well give him something specific to play with/against, right?

keyschat_1_640.jpg

While the client for Eulora 2 handles fully automatically the whole business of RSA keys and thus uniquely recognized identities, while the environment provides support for a Web of Trust (WoT) as well, the latest activity by players pushed suddenly quite strongly forward the private interactions and even rsa-backed contracts that people might want to have with one another. And since I am best placed to know exactly what is available, how it works and how it might serve this purpose, here’s my public euloran key made specifically for player to player interaction 1:

my player’s public key in Eulora 2

Simply download the above file, run your copy of vamp to unhex it and then use the result with Vamp as you would any other public key. If you publish or send over in Eulora 2 your key as well, we can try a full back and forth communication out.

Should add here that this is simply a public RSA key like any other – only plainly rather than opaquely stored and passed around. So to the extent that you can extract the actual RSA key out of whatever other software you happen to use 2, you can then in principle use that just as well with vamp 3, it doesn’t care.

  1. This may or may not be the same public key that I use for my euloran identity. Note that within Eulora 2 itself, the server is the central authority with which everyone has to authenticate and maintain the unbroken authenticated communication in order to appear in game as the respective character that they are handling. So within the game, if any X says something, it is indeed rsa-authenticated X saying that something – at least as long and to the extent that you trust the server of the game, indeed.[]
  2. Kleopatra most likely if you are on windows, gpg on linux but in either case, attempting to extract *just the key* is a good exercise to see for yourself just how little access to the actual controls the user is supposed to ever have. You know, one of those basic, repeatedly and respectfully cited everywhere Kerckhoffs’s principles, yes? []
  3. For completeness, the euloran RSA keys limit the length of the public exponent e, hence that trail of zeroes in the file above.[]

July 2, 2025

Euloran Kronikle II

Filed under: Coding,Eulora — Diana Coman @ 3:18 pm

~ This continues the Euloran Kronikle I ~

At Preposterously Prosperous Place

In the infinite land of Eulora 2, one can easily get lost if relying solely on the landscape for clues. As one player promptly found out when going to where the others should have been, only to be welcomed by an entirely empty space with no PCs nor NPCs in sight- is this part of the world the one I wanted, the one I needed or merely the one I happen to have stumbled in by accident, when going on auto-pilot and just looking away from the keyboard for a while? Luckily, the chat works from any and all places in and even out of the euloran world, so one doesn’t have to either wonder forever alone or indeed hope for no help at all. All it takes is to tell others of one’s trouble and there’s a good chance to receive some guidance towards finding one’s own way back:

e2k2_1_640.jpg
e2k2_2_640.jpg

As a wider benefit of both misadventure and telling others about it, the situation finally gave a good reason for the euloran world to give names to places – names that people can refer to, so that they can find their own way around and even tell others where they are, with some reasonable degree of confidence that they might even be talking indeed about the same place! So the world changed indeed and places got named, with the growing settlement where it all started finding itself in the very middle of Preposterously Prosperous Place (or PPP, for short). Some known places around seem to include at the moment the Limitless Ditch of Intoxication, the Cruel Mound of Pluck, the Secluded Course of Verve, the Goatish Hill of Destiny and the Saturnine Lane of Destiny:

e2k2_3_640.jpg

As for the explorer, all ended quite well for him too, as he got back to PPP and even found that, getting lost can really truly pay in all sorts of ways, when one is finally not lost anymore:

e2k2_4_640.jpg

Life and Death Get Vitals Moving

As PCs and NPCs truly got moving around the infinite lands, the very vitals of each of them also started moving – if in a more limited sense between the usual percentage values of 0 and 100 but decidedly up and down, as everyone noticed. Just as some vitals replenish with rest when at least enough food is had, others seem to drain with it. And then, one day, two of the oldest characters around were not quite that closely around anymore as the towncrier provided their epitaphs that gave perhaps some indication as to what could have done it for them only it didn’t, as well as what actually did it, indeed:

e2k2_5_640.jpg

As it turns out, one truly died of too effective ineffectualness, you know? This game might really be noticing something there…

An NPC’s Tease

While the best known NPCs are staying in town and providing services to everyone, there’s a growing number of less known NPCs that are busy with their own trials and tribulations in the vast lands of Eulora 2. One of those seems to have set up, whether intentionally or not, quite the tease for any player:

e2k2_7_640.jpg
e2k2_8_640.jpg

Despite being thus publicly exposed as the author of the previously unexplained phenomenon of apparently exploding amounts of bags appearing in place, he seems to be still at it. More recent reports suggest he can still be found by the trail he leaves behind:

e2k2_9_640.jpg

Merchant Dips Hands in Banking

The official merchant in Eulora 2, the one and only Rainer Tracksnarl recently dipped his hands in banking as well, to further improve the service he provides for his customers. Happily for eulorans everywhere, the official merchant’s hands are quite clean indeed, so that this dipping of his comes at no extra cost, while bringing the wanted benefit of being finally able to exchange between the many denominations of the euloran coin, the ECu. Players being human though, they quickly found, of course, that there is always more that they could want:

e2k2_6_640.jpg

One Towncrier Gets Busy: Daily Rankings and Other Notices

It all started – again! – with active players talking of what they did, where they are, what they found and what they think of it. As it happened before with the naming of places, it is the players’ own activity that pushes for some concrete improvement or addition – and in this case, it was the leadership boards that came out of this:

e2k2_11_640.jpg
e2k2_12_640.jpg

Less than a week later, everything was done and in place, so that the towncrier got quite busy indeed, with a brand new Notices and Announcement board that he is in charge of. So the towncrier is happily busy now, announcing all rankings as they get calculated and even pointing out the juiciest news in the more general, public chatroom:

e2k2_13_640.jpg

Better to CLI than to Click: the Stacking Experience

While NPCs benefit from Rainer Tracksnarl’s automated methods for tidying their inventory as they go, human players have had to do it manually until now. As activity increases though, the number of items grows as well and one might find (to their surprise or not) that clicking to move items about may be “very intuitive” but it quickly starts being rather too annoying, as well:

e2k2_14_640.jpg

As before, increased activity of the industrious and helpful kind also pushes for increased support from Eulora 2, so players got an improved bot command line so that the full stacking can take as little as one short line in the Console regardless of how many items there are that need moving. Alternatively, it can still take, of course, twice as many clicks as there are items to move, if one sticks to point-and-click rather than learning to use the command line. I’d say it’s far better for you to CLI than to Click but you are certainly free to take as long as you wish to find this out, there’s no rush at all:

e2k2_15_640.jpg

What Comes Next?

This one really and truly depends on players’ activity. As for the Kronikle, this part is easiest of them all – what comes next after this II is going to be III! When it will come out and whether it will still be manually compiled by me like these first two or not and what exactly it will contain and reveal from the euloran world is yet an open matter.

March 25, 2025

Euloran Shorthand for WoT Ratings

Filed under: Coding,Eulora — Diana Coman @ 5:07 pm

WoT 1 ratings are supposedly a shorthand themselves – just plain, integer numbers between -10 and +10, with every value meant to stand for something. For what, exactly? Well, given how few they are and how diverse the situations can be, the only possible answer is that it… depends and mostly on the rater, really. More to the point, these rating values can be used and assigned in any way one wants but are generally assumed to reflect to some extent at least, the degree to which one trusts one’s own knowledge and understanding of specific others, as they are met and interacted with.

But people being people, plain numbers as shorthand never really work as well as words where any meaning is intended. Hence, in practice, any consistent and systematic approach to actually using WoT ratings ends up quite quickly with at least one, possibly several word-based shorthand schemas for the ratings themselves. And while no such schema can ever be somehow “the one” or definitive or whatever else of this sort, there is perhaps something to be gained at least from making public a first such schema – as an example or maybe even just as a first attempt perhaps, if nothing else.

As to how this first schema even came to be – in Eulora 2, WoT ratings are used not just by players as they see fit but by the NPCs and generally by the game itself. Hence, there was the need for at least one specific schema that the code can rely on to give and interpret at the very least its own ratings – though possibly as well those of others in contexts where it is meant to interpret them. And it turned out in fact quite fun to attempt a consistent approach in finding meaningful shorthand names for all those rating values! So here is the current result, with negative values simply adding a “mis” prefix in front of the same word to mark the mis-alignment between rater and ratee:

  • 0 remembered (no negative here, it’s the one rating stating that one has interacted with this person and they want to keep this marked but they prefer not to give either a negative or a positive rating – hence, the rated person is simply remembered)
  • 1 contacted, -1 miscontacted
  • 2 acquainted, -2 misaquainted
  • 3 perceived, -3 misperceived
  • 4 encountered, -4 misencountered
  • 5 believed, -5 misbelieved
  • 6 known, -6 misknown
  • 7 trusted, -7 mistrusted
  • 8 respected, -8 misrespected
  • 9 admired, -9 misadmired
  • 10 fated (the main meaning of “fated” that I am using here is that of “determined” as in unchangeable in fact because this is pretty much what I see a 10/-10 rating validly standing for – the ratee is clearly and fully determined now as in the future, whether this is for instance because they are a known deterministic code bot or perhaps simply dead and thus not further able to either act or change at all, in any way), -10 misfated 2.

This is all, the first known public shorthand schema for WoT ratings, feel free to agree, disagree or even just argue with it, whether quietly on your own or more wordy in company, in the comments section below.

  1. Web of Trust, see what it is for, how it works and how to use it.[]
  2. According to the Oxford dictionary, the word “misfated” is “obsolete” and “last recorded around 1600s.” So I suppose I’m reviving words here, even if I didn’t set out to do this on purpose. I’m not even quite sure how or why would a word obtained via a perfectly plain and common prefix ever be obsolete but in any case, here it is then “last recorded” again, quite more recently than the 1600s.[]

January 21, 2025

Euloran Kronikle I

Filed under: Coding,Eulora — Diana Coman @ 6:25 pm

A ton of tubers a day keeps hunger at bay – or at least at a small cove, perhaps

Adventurous explorers in Eulora 2 reportedly found that there is at least some benefit to eating the tubers one digs. Even if not all around nutritious as it might be desired, they are at least not poisonous either and can even give a much needed (if at times rather small towards negligible) boost to one’s hitpoints (hp) and bloodpoints (bp). Imagine then if one could one day perhaps cook them into something even more useful than this…

kronik1_7_640.jpg

Crafting supplies are in but who has the money for it?

The long-awaited crafting supplies are indeed fully and freely 1available at the one and only official merchant, Rainer Tracksnarl. He duly advertised them in chat, players duly checked them out and barely managed to buy anything at all from all the piles:

kronik1_1_640.jpg

kronik1_2_640.jpg

One-legged craft-table reportedly crafts just fine

Active eulorans have recently spotted a one-legged craft-table in the wild, apparently crafting nevertheless just fine. As precarious as the whole thing looked at first sight, its contents proceeded to transform as expected and the output came in quite good looking too, so all is fine and in good euloran tradition – after all, if the table had two (or more!) legs to start with, what leg would there be left (or even right) for further improvement?

kronik1_4_640.jpg

kronik1_10_640.jpg

kronik1_3_640.jpg

How many clumps of grass does it take to make one coarse, frangible thread?

This is the question on eulorans’ lips, as crafting gets a slow but quite determined start. Opinions on the matter are diverse but also changing quite often, it would seem. From a reported starting 1 to anything between 4 and 5 currently, there seems to be no limit to it. And it all seems quite similar to an earlier public discussion on the little bits of nothing required to build a single tiny claim:

kronik1_5_640.jpg

kronik1_6_640.jpg

Merchant gets a grip on his runaway inventory

The prominent merchant of all things euloran, Rainer Tracksnarl, recently got a large shipment of crafting items of all sorts, neatly packed and carefully stacked by type and quality. The shipment is holding well but the stacking reportedly went quickly wild with all the players’ attention going through it, so that the merchant found himself with thousands of items scattered around in his inventory. While nothing was lost, lots was thus misplaced and even more was just taking up space, pushing desired items so far away that some said they could not even find them at all anymore.

Confronted with this unexpected issue of his runaway inventory, Tracksnarl finally took matters in his own methods and invested in a reliable re-stacking after each attempted exchange. Results so far look tidy, compact and utterly worth it, especially as players get to use the neat compact packing for their own inventories, too:

kronik1_11_640.jpg

NPCs 2 wonder out loud

As NPCs are increasingly active providing their services and answering questions in chat, it emerged that they may on occasion engage in conversations of their own. On one such occasion, they seem to be quite curious as to what humans might even be:

kronik1_8_640.jpg

kronik1_9_640.jpg

  1. Possibly “Free as in free speech, not free beer” or more plainly and aptly put: publicly traded, not gratuitously given.[]
  2. Non-playing characters. Because they work in the game, they dont’ just play it like PCs do, obviously.[]

December 30, 2024

Ginger and Spice

Filed under: Lyf — Diana Coman @ 6:16 pm

If one truly wants to start from scratch, it all starts with a mortar and pestle 1, though once this work done, the fragrant, freshly ground spices can hold for quite a while if well stored. And since I had such well stored spices, this most recent time I started instead straight from the next step or the even more alchemical part – measuring, mixing and binding together the spices 2 that give in the end such a great taste to the final result that even inveterate previous ginger-haters asked for more. In my version, the mix takes roughly 3 parts cinnamon, 1 part nutmeg, 1 part ginger, a bit or pinch or otherwise more relaxed small quantity of ground coriander and ground pepper, each, mixed together in a small bowl and set at the ready for what follows.

gingerbread_1_640.jpg
gingerbread_2_640.jpg

What follows is that one spoonful of sugar gets caramelised in a small stainless steel pot and once ready, 125ml hot water gets poured into it – do mind the steam coming out when you pour the water, at least if you don’t want to burn yourself quite thoroughly with it. A bit of further mixing while still heating it all will ensure that the sugar is fully melted. Then the spices and 150g of the flour can go in it as well, all at the same time, requiring some vigorous mixing to keep it all smooth and without lumps. Supposedly using a whisk makes this part easier but for me a simple spoon has always done this job quite well so I never bothered with anything else. Then it’s time for some rest – at least for the resulting thick mixture, though it certainly can be used as well for anyone and everything else in equal need of a cooldown at the same time.

gingerbread_6_640.jpg
gingerbread_12_640.jpg
gingerbread_13_640.jpg
gingerbread_14_640.jpg
gingerbread_15_640.jpg
gingerbread_16_640.jpg
gingerbread_17_640.jpg

For the next step, the remaining 330g of flour get mixed together with a pinch of salt, a pinch of bicarbonate of soda, an egg, 50g of butter and the earlier thick mixture now thoroughly cooled down and thus quite sticky but at least not entirely solid. At this stage I let a machine do the mixing as it takes 2 minutes in total and it keeps me far calmer than doing it by hand myself so it’s a win all around. The result is a lighter brown and surprisingly not sticky, nor crumbly really – though still smelling quite inviting indeed.

A teaspoon is then quite handy for taking out chunks of the mixture that get then roughly rounded by hand into small balls to set on some baking paper on a tray. I actually weigh mine to make sure that they are all quite equal at around 40g each, simply because it really matters at baking time – if they are of different sizes, the smaller ones will end up burnt or too much done aka too tough as an end result (since these keep getting tougher after they are taken out of the oven), while the bigger ones too little done and the eye will lie in this as everywhere else if relied on for too long over a rather repetitive task. Whether measured or not, once all are done, the baking time is quite short, at around 15-20 minutes maximum, depending a bit on your oven and the tray’s position. The ones pictured below were baked in a rather busy oven indeed so one tray ended up at the very bottom and those got rather more done than the rest for all that they had been inside the oven for the exact same time. When taken out of the oven, they are meant to be still quite soft and elastic even so that if you gently push one down a bit, it makes a small indentation that recovers then by itself. As they cool down, they’ll get less soft anyhow, so if they are already tough when taken out of the oven, they are just way overdone for sure.

gingerbread_18_640.jpg
gingerbread_19_640.jpg
gingerbread_21_640.jpg
gingerbread_22_640.jpg

For the last step, the usual frosting is simply a whipped up egg white with sugar and a spoonful of hot water to make it a bit more liquid so it can coat everything nicely. I tend to be liberal with it so each piece gets turned about in it until fully coated and then left to dry on a rack of some sort so that any truly excessive amount can just collect underneath. On some pieces I pencil it instead with a kitchen brush just because at times I find it way too sweet for myself so less of it makes it all better for me but I haven’t yet have anyone else complain of too much frosting on these just as they never complained of too much spices, either, go figure.

gingerbread_23_640.jpg

As to the final result, if it lasts long enough to take any pictures of it, it needs to be apparently at least the third batch in just as many weeks around here. The middle is soft and fragrant and for all that it’s called supposedly gingerbread, it seems to me so far different from any even supposedly “same type” of gingerbread that I ever found for sale in any market stalls anywhere that it’s just an entirely different item altogether. It’s also literally the only gingerbread that I actually like, even though I tried quite a lot of different types in different countries over the years.

It’s possibly not quite the first time when it turns out that whether one likes or not something meant to be tasty is really more about how close the experienced something turns out to be to its original source, natural ingredients and happy mixture of it all. Or in other words, how close the item still truly is to the very meaning of the word as it first emerged – taste as a matter of authenticity, perhaps, why not?

  1. Every time I take this one out to use in the kitchen I keep thinking there should be a matching alembic and retort, at the very least. Fortunately perhaps, although I cook every day, I don’t actually spend that much time in the kitchen or I suspect it would acquire in short time these items and more, quite likely looking increasingly less and less like what one thinks of as a kitchen, possibly to no one’s surprise.[]
  2. For the exact quantity, details as well as a warming background story even, I fully recommend Codruta’s article as that’s where I found this recipe in the first place, quite a few years ago. Codruta is a baker so she knows what she’s talking about and she explains her recipes in detail so you’ll likely learn something more just by reading her anyway.[]

October 18, 2024

Cuteness and Monsters or the Endless Options of Euloran Graphics

Filed under: Coding,Computer Graphics — Diana Coman @ 5:25 pm

Given the huge size of the pile of pictures, I might as well start with some of them directly, so scroll down for just a few lucky models out of thousands looked at and millions in the wings waiting for their chance to get out there in the euloran worlds and make their mark or at least be seen around.

A very forward-marching version of my character in game:
gfx2_4_640.jpg

The monster with multi-eyed tentacles and vomit-like colour:
gfx2_1_640.jpg

The psychedelic duck:
gfx2_3_640.jpg

Props and shape-showing character:
gfx2_5_640.jpg

A very curious flying worm – or maybe wyrm:
gfx2_12_640.jpg

The above are just a very small selection of the output from a few weeks of focused work on the graphics generator. This work finally opened up the sort of more “organic” growth of models that I was after – in addition to fitting meshes to bone, I can now finally grow directly such meshes along the bones of any given skeleton. With results varying of course, depending on a whole other set of parameters but building up quite well on the strong foundation of everything done so far. To keep it simple, highlighting here just the major parts of it as it currently stands:

  1. There’s a new, working approach to “grow” a mesh organically around the bones of any given skeleton, thus getting rid in one go of a whole set of issues that appear when one tries to build it from pieces. As a bonus, it actually results in more interesting *and* less space-consuming meshes, too.
  2. There’s a whole set of new types of surfaces available to mix as mere building blocks of any model or indeed model type.
  3. The skeleton construction stands the test of expanded use of all sorts, from simply more bones 1 to more fine-tuned picking of joints that feeds thus back into the process what is learnt through all the exploration. With the added parameter groups and types, the same skeleton building serves now equally well for making animate and inanimate models just as fine – the only difference is in post-processing really.
  4. The texture generator got an upgrade and can both generate and apply now an image directly to a whole model just as it did to a single mesh 2.
  5. There are automated explorers 3 to help literally see what’s in any direction picked.
  6. There are settled generators fully connected to everything needed to pick up any chosen results of various explorations and add them to the gfx pipeline for direct use in Eulora2 from that point on.
  7. There’s a growing list of insights regarding not only what works and what doesn’t but more to the point *why* that is so – and thus what sort of further explorations are worth doing, what sort of new additions are worth considering and so on.

For some examples coming from all the above, there’s such a large pile of all sorts that I can just as well do simply a lucky dip to pick from it – so here are some more pictures:

Run for your euloran lives – it’s the Hungry Spikey come to feed:
gfx2_15_640.jpg

The big-headed dinosaur:
gfx2_6_640.jpg

A nightmarish winged creature:
gfx2_7_640.jpg

Snail coming out of its shell:
gfx2_8_640.jpg

The curved tails possibly attached to someone:
gfx2_9_640.jpg
gfx2_10_640.jpg

A very boldly coloured fish:
gfx2_2_640.jpg

The many legs that want to move:
gfx2_13_640.jpg

This one got named, too, say “Hi” to Catface:
gfx2_11_640.jpg

Beyond the new production pipelines and the new directions and the new everything in the above, there is something else coming out more clearly of it and it occurs to me that it might even be the most valuable of the lot, namely a better formed statement of what makes my approach so different from what exists otherwise or why exactly it is that I don’t just go with the latest framework to model yet another nicely looking set of assets made and perfected one by one. To highlight it for easy finding:

While I appreciate beauty and harmony, whether in their positive or negative forms, it’s the underlying process, the very genetics at work if you prefer, that I’m interested in. My focus here 4 is indeed on modeling, understood in its original meaning of becoming able to generate what comes next. Hence my goal at each step is on advancing that sort of deep, generative understanding, not as much on achieving this or that specific effect in itself. Whenever one takes a break or looks at the result, its beauty or lack of it is more a measure of how far one got along the modeling path, simply a natural result rather than something to go chasing after.

I think that it’s really only the above sort of explicit modeling understanding gain that makes it worth all the work and even all the “ugly” results on the way. Because a beautiful artefact may be wonderful in itself, indeed but note that the sort of brute-force data crunching freely and quite widely, even increasingly widely available nowadays 5 can and does produce any number of those from even just bits and pieces of anything that it has ever seen. And thus, by extension, anything one makes “by hand” is going to be in short order fully drowned and lost in an endless pile of cheaply and quickly made AI-replicas at best. Though most likely it will not get even that much attention as such, let alone anything else – it will be instead merely used directly as just another data point, that’s all, the product of all your effort just gobbled up as mechanically and aseptically as possible since it’s bots only after all.

As for the technical details and what more or else is coming out, how it’s done and where one can further go with it, I’ll happily discuss it with others too, as always. The best and easiest way if you are interested is directly in game, of course, but failing access to that, simply ask in that comment box below and we’ll take it from there to see where it goes.

  1. On the topic of more bones: is 99 bones a lot for the mesh to bone approach? What’s 999 to the organic one, or 9999 for that matter? There’s a cost to more of anything, of course, but if and when that cost is willingly paid, in resources and corresponding adaptation of the rest of parameters to fit, there’s no further limit at all.[]
  2. even better actually since I finally figured out what was causing that visible seam in it and how to get rid of it, too![]
  3. Run it, pick some intervals for desired parameters and then just let it get on with it. It will generate the files, load them in a viewer, take pictures from different angles, save it all and repeat until done. Then all I have to do is to go through the pile of resulting pictures and take it all in, with any needed information at hand since they are all neatly named to know what went in and what process was at work.[]
  4. And not just here but quite everywhere really, see for instance the discussion of that unnamed other.[]
  5. “AI” is the more usual term and if you wonder why I didn’t use it directly, I don’t mind the question at all – consider perhaps what it means and what it does exactly to you to fully and fundamentally equate at all times intelligence with data crunching, without even further reflecting on how well the two may or may not be truly matched.[]

June 14, 2024

One Infinity Is Lonely, Two Are Not Enough, so There’s Plenty in Eulora2

Filed under: Coding,Computer Graphics,Eulora — Diana Coman @ 7:07 pm

Quoth the log of last week to the day, the 7th of June:

Diana Coman: Meanwhile in e2 world expansions, it turns out that even infinite is nevertheless not enough for me since the expedient idea of setting the Underworld literally under the landscape may be expedient but it just kicks the can down the road and well, it’s my can so whatevers, I picked it up and upgraded the whole thing so that at least I solve more with it and have therefore now everything set to make in principle even the claims as separate dungeons for instance.
Vivian Sporepress: I gather now there can be an infinity of underworlds hiding in tiny spaces within the overall infinite world.
Diana Coman: Quite so. I guess the way to put it would be that this visible world is infinitely large but it’s just ONE world and at the very least death certainly takes one out of it, so there we go, adding the unseen dimensions.
Diana Coman: Anyways, next in line is therefore to decide on some different looks at least for the Underworld and make some crossing for starters so it can get put to use.

So it took two weeks and all sorts of work to design a visibly distinct graphics style, turn a crucial part of the code inside-out and add the unseen dimensions, add some teleporting effects as well since I was at it, play around and come up with the items to be endowed with such marvelous properties as world-crossing, test it all back and forth, consolidate everything, have the fun and take the screenshots, drink the wine, do the chores and take a break, too. This last part was just about the hardest to fit in, given that all the euloran environment is, finally, so raring to go, so willing to grow, so easy to add to that yes, it got to that point where there’s way more fun than work in working on it.

There’s rather less time for documenting the fun, as it tends to happen, but here’s at least a few screenshots to tell a bit of the tale – how my toon crossed over the euloran six – I mean sicksstyx- and found herself in another world, suitably darker in style, at the very least. I started in the good old world of Nowhere Land, studying quite intently the one single Obolus there was around – its looks were silly, its inscription quite a description and then its use should all be quite safe, too, as surely no obolus has ever been in another live person’s mouth before, has it? So in it went and its results were quite as promised, too:

underworld_1_640.jpg

underworld_2_640.jpg

underworld_4_640.jpg

Looking around and moving about a bit brought changes to the skyline and otherwise mostly more red and grays and a bit of blue, too, by the looks of it:
underworld_5_640.jpg
underworld_6_640.jpg

After a while though, one does wonder, perhaps, as to the other one side of this one side trip – how might it be to go back to a more colourful world, where others are, where merchants live and things can be found. Perhaps that broken lyre is perfectly broken indeed and might just serve as an anti-obolus, who knows. More importantly though, who is going to try it, to find out?
underworld_7_640.jpg

April 14, 2024

Revisiting, Reseeing

Filed under: Lyf,Tgdyk tgdyk — Diana Coman @ 6:29 pm

ro2024_76_640.jpg

What do you see in it, I wonder – the caked mud or the precise, fractal-like contours of the soil’s own scales? The barren soil and lack of any green or the variety of browns and the striking contrast of the almost black and white larger pieces? Some fanciful dragon bone poking out from the ground at that place or merely a mud-path in a mud place, dirt piled upon dirt?

Possibly none of the above indeed, possibly nothing at all – “it’s just a picture of some mud, ffs!” Or possibly something else entirely, why not? I know I used to see “just a picture of some mud” long time ago, when I also barely had the patience to look twice at it. Revisiting old places this year though meant as well reseeing 1 them and thus noticing not as much the changes or the lack of changes in those places as how much more I saw indeed in them 2. This is quite easy in fact when one has inquisitive children around, to bring into sharp contrast just how little seeing is truly made by the eye and how much more is rather made by… experience perhaps, for lack of a better word. Their eyes saw it all better and faster than mine for sure and nevertheless, they circled back to it for a second look when I pointed out some detail or similarity and then… they came back with further questions on pretty much everything around, of course, how else.

It all sort of started with going back to those rolling hills of my childhood for a break. The old house there is falling down but there’s a new house built now, with all modern comforts and otherwise looking inside more “authentic” to modern eyes than the actually authentic, even. It’s pretty and comfortable and all that so everyone insisted I should stay there with them, of course and I said I will, too, if they insist so much, only I’ll still set up for the night my own tent further up the hill closer to the trees and the silence and the dark. My own child jumped up with joy at the idea, the other adults shook their heads at this, of course, and I let them do it as much as they wanted, it’s long time since it stopped bothering me in the slightest. We sat with them for the day and then we went to our own quiet place for the evening – only to find that in half an hour at most, my nieces came to visit and then well, it was story time and star gazing time and eventually, reluctantly, sleeping time, even.

One day, we went also a bit further – not all that far from the green rolling hills, about one hour away by car across the serpentines, the landscape turns barren and alien, seemingly desert-like with its light brown, almost yellow dunes on which no vegetation grows at all. There are only cracked fault lines running like outstretched, grasping fingers through the dried, acidic soil:

ro2024_80_640.jpg
ro2024_85_640.jpg

What humidity there is comes directly as mud rather than water – and not any sort of mud but bubbling, overboiling mud spilling at various intervals from holes in the ground that can go several kilometres down even when they barely show as a small opening at the surface. A small opening is all it takes indeed for the gases trapped underneath to find a way out and bring with them a steady supply of water, soil and minerals that give the surfaces its colouring such as it is. The air smells at times of sulphur and some of the bubbling puddles are visibly yellow, too. In places, the mud formed small mounds with fantastic shapes but it’s all very much a work in progress, as the bubbling and the sculpting is ongoing:

ro2024_59_640.jpg
ro2024_90_640.jpg
ro2024_91_640.jpg
ro2024_93_640.jpg
ro2024_95_640.jpg
ro2024_77_640.jpg
ro2024_78_640.jpg
ro2024_75_640.jpg
ro2024_68_640.jpg
ro2024_69_640.jpg
ro2024_71_640.jpg

The child was delighted with it all – “it’s Moon-like!” – and kept trying to conquer the peaks such as they were and otherwise to dam, divert or in any case make the moving mud follow his will, of course.

ro2024_72_640.jpg
ro2024_79_640.jpg
ro2024_82_640.jpg
ro2024_89_640.jpg
ro2024_96_640.jpg
ro2024_97_640.jpg

Over the next few days, I took the child hiking and he took with him his new little drone to try out in the “wilderness” as he put it. We saw deer, hares and foxes in the woods, quite closer to the open and more easily met with than I ever saw them before but we didn’t meet nor see any other person at all, even at a distance. And the woods looked to my eye more full of dead wood than I ever saw them, while the hills seemed in places to have missed at least one round of grass cutting, sporting rather sadly the dried out long grass of last autumn, still.

People’s absence aside, the woods were slowly waking up to spring and it was, sadly, too early for any mushrooms or wild berries of any kind, despite the weather being rather warm for this time of the year. But in the open, on the hillsides, the plum trees were already blossoming all around:

ro2024_22_640.jpg
ro2024_23_640.jpg
ro2024_28_640.jpg
ro2024_29_640.jpg
ro2024_30_640.jpg

ro2024_12_640.jpg
ro2024_16_640.jpg
ro2024_18_640.jpg

Matching it all, it also turns out that those fangled new fences that were all the rage some 5-10 years ago have been so abandoned meanwhile that one can hardly tell where they were so hastily errected at that time. Apparently the initial enthusiasm in fencing out whole hills and woods for oneself doesn’t quite age that well nor does it survive the amount of maintenance required to keep the fences up in such place, who knew. Apparently all one needs to do at times is to simply wait for nonsense to exhaust itself, at least in some happy cases. We circled the village from all sides on the hills around and we found time and place for everything – for stories and drone flying as well as for climbing, resting and learning to orient oneself in that sort of rural landscape. And I took pictures this time, remembering how much I felt the lack of those I failed to take years ago so here’s the last batch including even the mandatory picture of myself, apparently still frowning in that sort of sun without even knowing it and regardless of the dark glasses – some things apparently really don’t change at all, no matter what one does or how much time passes…

ro2024_4_640.jpg
ro2024_6_640.jpg
ro2024_8_640.jpg
ro2024_10_640.jpg

ro2024_98_640.jpg
ro2024_114_640.jpg
ro2024_116_640.jpg
ro2024_117_640.jpg

  1. Why exactly is this not a commonly used word? Why can it be perfectly well recalling rather than “calling it again” but it’s supposed to be “seeing it again” rather than reseeing?[]
  2. It always seemed rather surprising to me how accounts of old, familiar places tend to either lament the ways in which those places changed (the loss of some “good old times” of one sort or another) or precisely the opposite, the ways in which those places failed to change (the persistence of some “bad old times”, I suppose). For my part, revisiting and reseeing something always felt more like adding to the previous images of it, accumulating depth as it were and not at all a flat “find the difference” or “find the similarity” exercise. So I revisit, resee and remeet – I know, I know, this is not supposed to be a valid word either, ever wondered why not? – old, familiar places quite calmly and with fresh rather than merely nostalgic pleasure or displeasure. The past remains as it was at all times, it can’t change and the present is simply made all the more substantial by it as far as I’m concerned, that’s all. Possibly a persistent and rather stubborn memory greatly supports this approach.[]

January 15, 2024

A Glimpse of the Elusive 3D Mandelbrot or Iterating in All Dimensions

Filed under: Coding,Computer Graphics — Diana Coman @ 1:53 pm

Since earlier first pictures of the 3d complex space were quite encouraging, I took the time to figure out all these additional dimensions a bit better 1 and to implement directly the generic, N-dimensional case. After all, why stop at 3 dimensions only, when the complex space clearly has in fact many more dimensions than it ever apparently got much credit for? And it packs a lot into these additional dimensions, too, so take what follows as only a first glimpse and nothing more – an appetizer, if you wish, not even by far the full course, feel free to go exploring and make your own discoveries as well.

To start with, my generalization from the classical Mandelbrot to N-dimensions is quite straightforward: while the classical formula is iterating z^2+c where z is a 2D complex number 2 and c a constant 2D complex number, I’ll iterate z^2 + c where z is a N-d complex number 3 and c is a constant N-D complex number. Setting as usual a maximum number of iterations and a bailout value means that one can obtain as a result the Mandelbrot set in 2D if the usual 2D complex numbers are used, in 3D if 3D complex numbers are used or in any N dimensions if N-d complex numbers are used. To illustrate this, here’s the section of such a Mandelbrot set, as obtained when fixing the ‘camera’ on the same coordinates 4, with exactly the same colouring 5 and simply calculated in turn in the 2D complex space and then 3D, 4D, 6D and 8D complex space:

mbrot3d_52_512.jpg

mbrot3d_53_512.jpg

mbrot3d_39_512.jpg

mbrot3d_42_512.jpg

mbrot3d_54_512.jpg

If that first picture for the 2D complex space took you a bit by surprise as it’s quite a close up of the cardioid shape, here’s the same with the average curvature colouring that highlights better the well-known mandelbrot shapes in the mini-mandelbrots emerging on the border to the right:

mbrot3d_29_512.jpg

And to remove any doubts, hopefully, let’s change the colouring method outside the set to highlight the normals via a very simple shading model that brings out into the open what’s going on exactly on that border in 2D, 3D, 4D, 5D or indeed any D:

mbrot3d_48_512.jpg

mbrot3d_49_512.jpg

mbrot3d_8_512.jpg
The more dramatic ‘half-half’ colouring in this picture is just a matter of lighting – in all the others the light is simply set to avoid this sort of sharp border at 0. Here’s the very same result with the more uniform light to match all the others in this set:
mbrot3d_7_512.jpg

mbrot3d_50_512.jpg

As for the first observations on the series above, I think that the Mandelbrot shape is quite clearly emerging in all cases, with each dimension only literally adding its detail on yet another direction as it were. There’s also quite clearly a better view in this limited 2D slicing of the results when the underlying complex space has at least an even number of dimensions. Even in the odd cases though, there isn’t a direct breakage 6, only the clear ‘cut’ of bands, which seems to me more of an indication of a trouble with the perspective/visual capacity essentially than a structural issue. Whether slicing through an odd or an even dimensional space, the 2d image even while looking supposedly at the “same slice”, it still captures quite strikingly different results. Which makes it all in turn perhaps quite interesting to consider that this is literally an illustration of how the ‘unseen’ dimensions have nevertheless quite a direct and visible impact on the ‘seen’ ones, isn’t it?

Setting aside for now any further musings on unseen dimensions, there are certainly other ways of picking a slice of the resulting N-dimensional object to look at. And the structural properties of the 3D complex space suggest at least one option that has perhaps some more usefulness in being more closely matched to the space that I’m trying to explore visually first of all: the cone xy-xz+yz=0 is quite special in that it’s only when at least one point from this cone is involved that some ‘usual’ properties hold (most notably |z1*z2| being the same as |z1|*|z2| or in other words, the size of the product being the same as the product of the two sizes).

For the next set of images, instead of mapping the flat image space to an equally flat square or rectangle looked at from a fixed z distance, I map it to the above cone – the x and y are mapped as before 7 but the z is then calculated so that the resulting point is on the xy-xz+yz=0 cone. The result is… butterflies with mandelbrot patterns on their wings. Some more obviously butterflies or more obviously mandelbrot patterned depending mostly on the colouring scheme chosen rather than anything else and I’ll let the reader figure out (or merely guess, even) the underlying number of dimensions in each case:

mbrot3d_27_512.jpg
mbrot3d_9_512.jpg
mbrot3d_22_512.jpg
mbrot3d_24_512.jpg
mbrot3d_25_512.jpg
mbrot3d_26_512.jpg
mbrot3d_31_512.jpg

Finally, for further evidence that what one sees is quite dependent on how one knows (or chooses!) to interpret what one looks at, here are a few images obtained from some of the exact same sets as calculated above, only coloured without discarding the 0 values of unperformed iterations once the bailout value was already reached:

mbrot3d_2_512.jpg
mbrot3d_10_512.jpg
mbrot3d_11_512.jpg
mbrot3d_12_512.jpg
mbrot3d_13_512.jpg
mbrot3d_14_512.jpg
mbrot3d_15_512.jpg
mbrot3d_17_512.jpg
mbrot3d_18_512.jpg
mbrot3d_19_512.jpg

  1. There’s a more structured discussion that I found quite useful on the 3D complex numbers and their geometric and algebraic properties in the paper “On a Novel 3D Hypercomplex Number System” by Jacobi, Shlomo and Shmoish, Michael, 2015.[]
  2. x+y*i with x,y real values and i^2=-1[]
  3. a0+a1*i+a2*i^2+a3*i^3+…+a(N-1)*i^(N-1) with a0, a1… a(N-1) real numbers and i^N=-1[]
  4. For the record, the section in question covers x from -1.5 to 1.5, y from -1.5 to 1.5. The image space is linearly mapped on to this 2d space. Where the complex space has more than 2 dimensions, the z is then fixed as ‘distance to camera’, at 0.375 and the corresponding transformation to x and y is applied to yield the actual components of the complex number that is then iterated. In all cases, the components beyond these 3 start as 0.[]
  5. The average stripes method which is both quite useful to show a lot of information about what’s going on *outside* the set itself and otherwise fitting really well with my trig-based colouring palette since it’s literally relying on the very same parametrisation of the cos function under the hood.[]
  6. Not even of the ‘noisy areas’ type that broke at times the fern’s tip in the first attempt – it turns out that most of that is likely an artefact of my too cautious earlier implementation when I hadn’t quite fully grasped the unexpected fact that the 3D complex space has divisors of 0 that are however non-zero themselves and thus quite entirely safe to divide by.[]
  7. To be precise, in some images the y covers from -1.0 to 1.0 hence the ‘diagonal’ ending up not quite matching the image’s own principal diagonal.[]

December 18, 2023

Some Pictures from the 3D Complex Space

Filed under: Coding,Computer Graphics — Diana Coman @ 2:49 pm

Tantalizingly, the images just about meet, coming as it were to very similar or obviously ‘same’ places only on different paths, from different starting points. Going from the classic Mandelbrot fractal to Julia sets, from the signature rotate and shrink of chaotic systems to the clever diamond square and fm plus Perlin noise cheating shortcuts, there is always seemingly just out of reach – or at least out of *my* reach for now – the common core that is unchanging throughout, the possibly illusory model that finally provides one a full understanding of the matter so that it’s clear not only all that can be obtained but also how. Most likely though, it’s truly as old wisdom says – at core the whole of it is just Maths and Language, structure and expression. So, setting aside any lofty goals and higher expectations of full understanding, I simply went a bit exploring in the 3d complex space this time – the space with one axis real and two complex (hence, a whole imaginary plane rather than merely an imaginary component). What I found when slicing through to get a 2d section was, quite as expected, the Mandelbrot shape, even if rather lusciously 1 coloured in by all three colouring methods I had already implemented for iterated polynomials:

3dcx_34_640.jpg
3dcx_35_640.jpg
3dcx_32_640.jpg
3dcx_37_640.jpg

Taking the fractal shortcuts in 3d complex space too didn’t take long to implement at all, seeing how it’s just a tiny addition to my trusty generator, merely plugging in a different function for the painting part and letting the rest do its job as usual. There’s a sort of smudgey style to the colouring overall but otherwise the underlying structure seems to my eye quite reliably, reassuringly bringing together several styles that were before obtained only from futzing around with various parameters – suggesting that this is indeed on the way towards getting the hang of a better, more useful model of the whole. Seeing how it’s such a model that I’m after rather than just pretty pictures, taking the time and the exploration to get there is fine with me and on the way, the pictures, beyond providing a possibly haunting collection of eye-like drawings, might also make for interesting Maths illustrations at the very least, I’d say, so here’s a small sample:

3dcx_10_640.jpg
3dcx_11_640.jpg
3dcx_12_640.jpg
3dcx_13_640.jpg
3dcx_14_640.jpg
3dcx_15_640.jpg
3dcx_16_640.jpg
3dcx_17_640.jpg
3dcx_18_640.jpg
3dcx_19_640.jpg
3dcx_20_640.jpg
3dcx_21_640.jpg
3dcx_22_640.jpg
3dcx_23_640.jpg
3dcx_24_640.jpg
3dcx_25_640.jpg
3dcx_26_640.jpg
3dcx_28_640.jpg

While I don’t really intend to write up this time in much detail the technical parts behind all the above, the very basics are straightforward: a 3d complex number is x*j+y*j^2+z*j^3 where j^3=-1 and zero is a full plane, x-y+z=0. I’ve taken this description that seems fundamentally correct to me, from Reinko Venema 2, who seems to have gone even further on the Maths side to n-dimensional complex numbers. Using this basic definition of 3d complex numbers, I simply naturally extended the rest of notions I needed for the various types of colouring I already had from the usual complex numbers. I’m quite happy with the results obtained so far and everything seems to fit perfectly well indeed so I don’t particularly see any need to change any part of it for now.

As to the 3d or even nd complex space itself, there is certainly plenty more to explore, especially on the expression side, since what the “eye” can see so far seems to me to be rather little and possibly way too dry, with only a hint of a glimmer in that Mandelbrot fern part for instance. Not that I ever lacked what to explore, really, so don’t wait for me on this if you are interested, simply pick it up instead and take it further. If you do, I’ll be even quite curious as to where you get with it, just let me know in the comments below.

  1. Seriously, it actually looks better than you can see here – processing the pics for the web in this instance visibly hurts, taking away apparently the sort of detail that counts and making the pics look rather dull by comparison. Still, I don’t feel at all like going again through the pile to pick them and upload them in full, glorious size and this write-up anyway waited for more than a month to get done so you’ll either have to take my word for it or regenerate them to see for yourself.[]
  2. Or so I assume his name to be, as the only place I could find a name on that whole site was in what looks like a test comment. I wanted to leave him a comment or contact him some other way to at least let him know of this tiny related use but I failed to find any contact details as such and I’m not going to go now through all the trouble of making a wordpress account or somehow digging up that 10 years+ old account of mine, if it still exists, just to leave a comment. If any of my readers has a wordpress account at hand and doesn’t find it too much trouble to comment there, perhaps there’s still a way to reach out and communicate but otherwise it doesn’t seem all that likely.[]

November 22, 2023

Growing VaMP at Users’ Request: summ and sigdiff

Filed under: Coding,VaMP — Diana Coman @ 10:46 am

As VaMP gets put to use on projects others than my own, by hands other than my own, feedback comes, discussions happen and, as a result, it’s not that long 1 until there’s added functionality in the form of two new commands: summ and sigdiff.

Alongside these two new commands, there are also smaller convenience-related changes such as a more user-friendly ordering of files in the output. Note though that large as well as all smaller changes made at this time are *not* mandatory in any way, nor breaking compatibility in the slightest. This is, of course, exactly natural and proper – changes are not impositions but offers made to the users, to be weighed and adopted if and *only* if users truly consider that they are indeed worth the cost. Not mandatory “upgrades”, not breaking compatibility, not forced through in any way. If you have a use for summ and sigdiff or would simply prefer the new ordering of files in the output, then you’ll take the latest VaMP but otherwise you are perfectly fine and welcome to keep using whatever other version of VaMP you already have and are fine with. This said and underlined, let’s dig in and see in more detail what exactly are summ and sigdiff doing in VaMP.

Summ
The aim of summ is to allow the exact reverse operation of diff. While diff takes as input two directories (or even files 2) and produces as output a ‘recipe’ for obtaining the “newer” one from the “older” one (in whatever way new and old are defined by the user, really), the newly added summ takes as input such a ‘recipe’ aka a diff file alongside a directory and proceeds then to apply to this directory the steps as found in the diff file. If one applies diff to directories a and b, producing the diff file d describing the steps to get from a to b, then applying summ to d and a will result in b.

If, however, one applies summ to d and some other directory e, the result will be failure with an error message identifying the first place where e was found to be different from the input that the diff file assumes – meaning in this case, from the original a. Because unlike the more common, non-VaMP varieties of ‘diff’ and corresponding ‘merge’, the point is to know quite clearly and explicitly the full state of the directory in question at all times, not just the bits and parts that are touched by one step or another.

As a user, I really do care about the input directory as a whole or otherwise I’d simply discard the part I don’t care about and make the load lighter to start with. Consequently, I’d much rather the tool supports my full interest and helps look after the input as a whole rather than letting it up to me to figure out afterwards what happened exactly and whether the result is what it was meant to be in the first place or not quite. This being said though, the tool will certainly *attempt* to do whatever it is set to do, simply providing as much information as it can on the results of this attempt and the likely underlying causes for failure, when relevant.

In short, summ works with a diff file aka the *unsigned* list of steps to bring one directory’s contents to match exactly another directory’s contents. By contrast, the already existing patch command works only with a patch file aka the *signed* list of steps. Thus, while diff is quite useful in practice as a preliminary step to check a set of changes before signing them, the corresponding summ has its use case in applying a set of changes whenever the user doesn’t consider signing required, such as local testing for instance. There’s a cost to signing, as there is a cost to everything and depending on the context, this cost might be justifiable or not. It’s entirely up to the user to decide at each use whether it’s worth signing or not. VaMP simply provides now the needed commands to do the job fully in either case – via patch for signed changes, via summ for unsigned changes.

Sigdiff
The sigdiff command takes as input a diff file (hence, an unsigned list of steps) and a private key, producing as output the corresponding patch signed with the given key. This decouples quite on purpose the production of a patch file at the exact sensitive point of signing – because private keys are sensitive information, it’s quite naturally the case that they are kept in more secure environments that don’t necessarily fit in with code development directly.

Without sigdiff, one would need to bring together the code and the private key at least for the duration of producing a signed patch. This is less than ideal and while it can be worked around (and verifiably has been worked around by myself at the very least) it goes against the very good practice of keeping private keys in air-gapped environments. With sigdiff however, the use is much more straightforward, quite similar to any other use of private keys: the diff is produced in the usual work environment where the code is but the key isn’t present; then, sigdiff is applied to the diff separately, in the more secure environment where the key is but the code isn’t present; finally, the resulting patch is published or otherwise used in any environment, as desired.

As a final note, there are at the moment a couple of potential further additions that didn’t quite make the threshold of current usefulness to be included. So they are noted and fleshed out in VaMP’s design document, ready to be implemented but not actually implemented until there is a clear need for them. Should there be any further requests or questions, they are always welcome, as usual, in the comments below for everyone and through more direct channels for those more closely involved.

  1. In fairness and for complete history, there’s the VaMP category on this blog to get the full timeline of additions to date:

    1. VaMP was ready to go on the 23rd August 2021
    2. more details of its workings were published on the 5th of September
    3. a discussion of what are valid files and directories for VaMP was published on the 19th of April 2022
    4. about 8 months later, on the 5th of May 2022 and then on the 12th of May 2022, there was the addition of a tidier alternative visualisation of patches and their dependencies, followed by the addition of html formatting and output production, bridging directly code and VaMP output to the blog
    5. almost one full year later, on the 4th of May 2023, the versioning and software editions capabilities were fully in place.

    In between these, there was certainly a lot of use and practical experience that turned out extremely pleasant for the most part. While the pace of changes and additions might seem perhaps ‘slow’ from some perspectives, I think it’s neither slow nor fast but just exactly right – as use informs and requires, without pressure nor ill-considered or rushed changes, allowing time to get used to things and knowing at all points that the experience thus gained is never lost but an asset that keeps increasing in value as it builds up.[]

  2. This is the corner bit where summ is currently *not* quite the full reverse of diff – it works on a directory, only. The case of diff applied on two files as opposed to two directories is in itself quite an odd and awkward special case from the point of view of VaMP when considering that a single file can’t have attached a manifest with its history, for instance, thus little to speak of. For users’ convenience and mostly in keeping with the original generic diff that did and does apply indeed to files as well as directories, VaMP’s diff does the same, producing the list of changes all the same. Nevertheless, I don’t really see much point in dragging along this odd special case for anything other than the diff command as such – if it’s absolutely imperative for you to diff and summ a single file, simply put it in a directory and apply VaMP to that, it’s not much trouble and it can even be automated via a basic script if desired, not that I can fathom such use case at all currently.[]

September 29, 2023

Straight and True, Like a Fully Connecting Punch

Filed under: Sense and nonsense — Diana Coman @ 9:53 am

“What is it that I don’t get correctly currently?”, I asked with genuine desire to know, though little expectation for any answer at all to be forthcoming. The question simply expressed my very clear realisation of a lack of precisely that sort and shape, at that time, when it was like looking at something in a mirror in which all angles are so egregiously wrong that nothing fits at all and everything is in all places so deeply incongruous within and without itself that the whole is not even wrong yet, it’s just something entirely else altogether. So I wondered essentially, since wonder is exactly what a genuine question ever is, what exactly was it that I just didn’t get at all and to such extent as to render it all so entirely… broken.

To my surprise though, the answer came this time quite promptly, straight and true, like a fully connecting punch:

“Death.”

“Well, I get it as an end, at times a release even, a removal perhaps and a resulting absence, lack or sometimes simply empty, blank, bereft space. How can I see it more accurately then?”

“Exhaustion, beyond culmination. Oppression, isolation, restriction and constraint, confinement, silence and enforced, implacable stillness receiving, containing, preserving, molding enduring shape, accumulating pressure, forging and tempering strength.”

As a result, the angles shifted, the image straightened, there is at least recognition possible, the link and similarities are striking indeed once the vision corrected enough to notice them. I’m grateful for the answer as unexpected and as straight as it was, though I’m also a bit weary of wondering that much more at least for a while from now…

September 3, 2023

Northern Sun

Filed under: Tgdyk tgdyk — Diana Coman @ 5:54 pm

The usual rarely works for me and for the ten thousand words worth of proof that it is so, here’s first how the attempt at a more conventional “sunny August day by the sea” turned out this very summer that just passed:

edinb_1_640.jpg

The above picture is taken this very August, believe it or not and before the rain settled down morosely and the winds truly took off in full blast, determined to blow off the beach any and all that failed to leave of their own accord. So we left the beaches and the supposedly sunny south to the crowds and with the same blow it turned out we also managed to leave to the same crowds the train strikes that were considerate enough to happen only before and after our days of travel and the software glitch at the airports that reportedly grounded a lot of flights for some 3 days or more across the whole country. Even in traveling matters, the right solution is right in more ways than one at times, it would seem.

The usual thus out of the way quickly enough, we headed instead north, towards the closest available sort of hills that I still need apparently more than I thought, at least somewhere close enough, somewhere in sight, somewhere within walking distance. And we didn’t stop that easily either. We kept going north until we found just about everything we wanted: green hills indeed but with solid, black volcanic rock at base leading towards the estuary carved long ago by a glacier but more to the point perhaps, days full of sun at its northern best, balanced by chilly winds and framed by running white clouds in intensely blue skies that turn nevertheless quite pale in the evenings. To get the required me-picture out of the way first of all:

edinb_32_640.jpg
edinb_35_640.jpg

While I admired the fountain’s iron work, I can’t say I cared all that much for the surrounding addition of fencing and barriers that my 10 year old photographer dutifully included for a truthful representation of reality as encountered. So there you go, the contribution of the current times is an ugly iron fence and gate of bars around the graceful iron sculptural ansemble representing no less than the science, arts, poetry and industry sitting at the top together, surrounded at the base by mermaids, walruses, cherubs and lion heads. By 2023 though, all of them are further surrounded quite resolutely by cheap and ugly metal railings plonked on the ground with such disregard for the whole that it’s possibly quite well enough that neither the sculptor 1 nor the admirer who literally bought the whole thing and moved it here all the way from London 2 are alive to see the result.

On possibly the funnier side at least, my photographer had other more pressing, if equally practical concerns with the whole fountain:

“They look like they are washing themselves in there! Why are they washing themselves?”, he asked, entirely unimpressed by the whole idea of artistic representation. So I answered him in the same spirit, knowing full well from experience that nothing else would cut it any shorter anyway:
“Well, what else would you do if you had all that water coming over you at all times?”

Fountain aside, the backdrop of it all is a castle perched on the volcanic rock and overlooking not merely the whole town itself but straight across the whole estuary with its scattered islands and former pirates. Cue extensive and involved discussion from the 10 year old wannabe castle assailant and cliff scaling extraordinaire, fully versed and interested in the opportunities that such situation and positioning might offer for the pouring of hot, boiling oil on unwanted guests. As the current saying goes, your own tourist guide might differ on the matter.

While the pouring of hot oil isn’t at least documented anywhere, the rest was reasonably close to account for something: the castle was indeed taken over repeatedly – by determined men scaling the rock at times, by more expensive if less demanding treachery at other times. For our part, we played it straight so we went up by the main road and paid the fee as stated to get in. And once in, we visited it all, such as it was, a mix of old and several times rebuilt pieces and places, a residence turned fortress turned wartime hospital and prison 3, turned army barracks and then yet again turned museum and living grounds for the keepers. We toured the place, admired the view and got dutifully startled by the usual 1pm gun shot approach to hour keeping that was nevertheless thoroughly enjoyed since “they really, REALLY shot it!!”.

edinb_138_640.jpg
edinb_2_640.jpg
edinb_30_640.jpg
edinb_4_640.jpg
edinb_5_640.jpg
edinb_36_640.jpg
edinb_39_640.jpg
edinb_40_640.jpg
edinb_41_640.jpg
edinb_43_640.jpg
edinb_48_640.jpg
edinb_49_640.jpg
edinb_50_640.jpg
edinb_53_640.jpg
edinb_54_640.jpg
edinb_55_640.jpg
edinb_56_640.jpg
edinb_58_640.jpg
edinb_61_640.jpg
edinb_63_640.jpg

In the castle grounds we got the first view of the whole unicorn opposite lion heraldics, much to the child’s delight as he finally, finally considered them to have found some sense since matching thus much more interesting stories than the whole Scotland and England history – the Amber worlds of chaos and order, patterns and shadow realities included, certainly! For my part, I took more of an interest in the various ways the unicorn was represented, from earliest stone sculptures that really looked more like deer/antlers to me, to the silver, slender one inside the grand hall and then the most modern, gold-plated, elegant depictions on the gates at the more ceremonial palace contrasted as it finds itself to those on the grounds of this more utilitarian castle. Though the truly oldest stone unicorn is opposing itself rather than any lion and is to be found still closer to the palace than to the castle, in the ruins of the abbey that was first on the site.

edinb_57_640.jpg
edinb_65_640.jpg
edinb_25_640.jpg
edinb_104_640.jpg

Castle thus thoroughly investigated, we walked again the length of the old town (which is not all that long in itself, truth be told) and we got thus closer inland to where the view opens up towards the greenery. Going as it were from the duty and defense to the leisure and ceremonial, since apparently nobody quite wants to live atop a volcanic rock if they can safely live among landscaped gardens instead. And gardening here is quite serious in spots, with the lawn tartaned, by the looks of it rather than merely cut back. On the side though, the old abbey is in ruins and the old stone shows its age and bears its holes and missing parts with dignity since that doesn’t ever really go away once present.

edinb_90_640.jpg
edinb_91_640.jpg
edinb_92_640.jpg
edinb_93_640.jpg
edinb_94_640.jpg
edinb_95_640.jpg
edinb_96_640.jpg
edinb_97_640.jpg
edinb_100_640.jpg
edinb_105_640.jpg
edinb_106_640.jpg
edinb_107_640.jpg
edinb_108_640.jpg

Between the castle and the palace, the royal mile or more simply “the street” runs nowadays more like a river of tourists than a road at all. Dotted on the way, one finds the usual greenish-tinged and pigeon marked statues.

edinb_70_640.jpg
edinb_9_640.jpg
edinb_10_640.jpg
edinb_11_640.jpg

There are also the even more usual medieval houses, if perhaps slightly taller than is the norm in other towns, since the town expanded more easily upwards than sideways, when needed.

edinb_12_640.jpg
edinb_13_640.jpg
edinb_14_640.jpg
edinb_110_640.jpg
edinb_111_640.jpg
edinb_112_640.jpg

Among the houses, one stood out to me for its position round the corner and its carefully inscribed walls that seemed to advertise the love of neighbours – perhaps the more needed at such close quarters of living than otherwise. The house’s history is perhaps at least as colourful as its exterior: while decorated thus by a relatively wealthy goldsmith by the name of Mossman who obtained it as part of his wife’s dowry and lived in it for years until he lost it for the fault of being on the losing side of the religious changes of his time, the house is nevertheless currently known as “John Knox house” because said firebrand and dominating figure of the Scottish Reformation occupied it for a few months before his death. And then, by the 1800s, when space was at a premium in the town and the old quarters were more of a slum than a prime estate, the same house was turned apparently into a sort of a mini-village in itself, with one large family living in each room, as they could. Nowadays it’s a museum to said John Knox and in part an asylum for older furniture recovered from other houses that were demolished rather than renovated.

edinb_15_640.jpg
edinb_16_640.jpg

The usual scattering of churches is present too, of course, made perhaps a bit more interesting by their clearly different designs. There is the Canongate Kirk that looks more Dutch than anything else and turns out to be built indeed in “Dutch-style” around 1690.

edinb_17_640.jpg

There is St. Giles Cathedral that doesn’t seem quite sure as to the exact style it sports, which is perhaps quite to be expected given how many ages it’s seen, how many “right way” changes were imposed upon it and how many fiery “our way is THE right way” it heard within its walls. At one corner, there is even a building that looks like a church but serves as an indoor arts and crafts market.

edinb_6_640.jpg
edinb_8_640.jpg

Further away, in the “new town” built outside the former town walls, there is yet another church that shows off the new money, the new interests, some of the newer people as well as yet another unicorn and lion story to link it all. The name’s St. Mary Cathedral and the sign is a big rusty key erect at the entrance, seemingly stuck in unlocking perhaps the foundation and the netherworld if not directly the underworld.

edinb_123_640.jpg
edinb_124_640.jpg
edinb_125_640.jpg
edinb_126_640.jpg
edinb_127_640.jpg
edinb_128_640.jpg
edinb_129_640.jpg
edinb_130_640.jpg
edinb_131_640.jpg
edinb_132_640.jpg
edinb_133_640.jpg

edinb_137_640.jpg
edinb_136_640.jpg

Leaving aside both the old and the new town, there’s more to discover up the hill, even if it is indeed of the rather odd and folly sort – there’s a portuguese cannon brought all the way from Burma, several imitations of ancient Greek architecture, an old as well as older observatory and a monument to admiral Nelson, all clustered up atop the same hill to one side of the town.

edinb_72_640.jpg
edinb_73_640.jpg
edinb_74_640.jpg
edinb_75_640.jpg
edinb_79_640.jpg
edinb_82_640.jpg

Back on lower lands and running towards the sea, the neatly square plan of the town holds though surprises less advertised or described otherwise. There’s a medical building as identified by the caduceus on its facade and serving apparently still in its original capacity. There are also others where the appearances are deceiving for the interior turns unexpectedly to uses such as gym and office spaces. These aside though, the portrait gallery reddish building is an unexpected treat inside in terms of the rooms and decor itself first and foremost. Though one has to pass first past a statue of Burns, of course, since it’s after all the national poet so he gets put at pride of place, with various busts scattered behind him in the second line.

edinb_88_640.jpg
edinb_89_640.jpg
edinb_84_640.jpg
edinb_85_640.jpg

As last surprise perhaps, one finds as well even this far north the much more southern decor of Spain – in a vast cafe 4 that stretches over a few floors and across two entrances, boasting inside vases, ceramics and intricately ornate stairs in all the bright colours that one realises suddenly are otherwise quite utterly missing from the streets outside where the most common colour is still a sort of sooty black for all the fact that coal burning hasn’t really happened on any large scale this last hundred years at least.

edinb_113_640.jpg
edinb_114_640.jpg
edinb_115_640.jpg
edinb_116_640.jpg
edinb_117_640.jpg
edinb_118_640.jpg
edinb_119_640.jpg
edinb_120_640.jpg
edinb_121_640.jpg
edinb_122_640.jpg

Back at the temporary base after all the walking, sightseeing and climbing, the tall chairs are put to lazy use and the symbols are thoroughly misleading so don’t believe perhaps everything you see written or even pictured…

edinb_140_640.jpg

  1. Jean-Baptiste Jules Klagmann[]
  2. A local gun maker by the name of Daniel Ross. Guess whether the fountain is called the Klagmann or the Ross fountain, eh?[]
  3. The child was quite interested in the ratios given to prisoners – they didn’t seem to be that bad, he sad, beer and butter, bread and meat for doing nothing at all! Though he was quite offended at the treatment of American prisoners as pirates – not as much by the fact that they were considered pirates, since that’s not a bad thing in his book, but by the fact that pirates were given only water![]
  4. While I’m the one willing to try anything in terms of food, my companions were staunchly against any local cuisine and so the food remained reliably non-local in preparation manner at all times. Perhaps with the one notable exception made by the youngest to some mint-flavored fudge. []

August 6, 2023

The Syntax of World Knowledge in Eulora2

Filed under: Coding,Eulora — Diana Coman @ 2:05 pm

~This is a work in progress, to be discussed and expanded as the game progresses further. This article brings together and builds on the work already done and the preliminary concepts that were already described in previous articles, including a first draft of a data hierarchy, its subsequent refinement and an initial brief discussion of how it works in practice.~

To support players in their quest to explore, make their name and write their own history in the infinite and infinitely expanding world of Eulora2, the game’s client acquires and maintains at all times a dynamic view of the game’s world, as it becomes accessible and known to each player and as it responds to their actions or as it changes otherwise, with time or due to other players’ actions and to the game’s own internal rules.

The above means specifically that the game’s client successfully retrieves and makes use of any new data in its relevant context on the fly, as it becomes available and without knowing it upfront – because it simply can *not* be known upfront, since it’s the players’ actions that decide the very evolution of the game’s world! Playing Eulora2 truly means exploration and discovery in full, not just a pretense kept alive by some sort of agreement between server and client to merely not show or not use some data until the server says it’s “available” and the client is “updated” to have it and be able to handle it. In Eulora2, the player doesn’t need to avoid for whatever reason to even look at the files on their own disk. Quite on the contrary and unlike in any other game to date, in Eulora2 the player is warmly invited to look at the files on their own disk, to make full use of all the data and knowledge that they can access at any time, to write or use their own bots and anything and everything else that they can gather or even think of.

The game’s own client as I made it to date supports the above by design, as it is entirely and fully dedicated to serve the player with all it has and all it can actively and continuously acquire. These are not empty words but fundamental principles of mine and thus I made the client according to them, quite on purpose: it continuously checks, discovers and acquires new data and new knowledge of the world as it becomes available and it makes full use of it and of any new assets on the fly and as unobtrusively and quickly as it can.

How is such continuous discovery of knowledge and on the fly use of new assets even possible? In short, it’s made possible by knowing the very syntax of the game’s world representation – thus, instead of trying to enumerate upfront the world entire and getting stuck as soon as a new element is added, my client for Eulora2 simply starts off knowing how to discover and make sense of new elements as they appear.

My client starts without any of the game data but with the full ability to acquire and make sense of any and all such data, as soon as it has a working connection to the server. The way it does this is by knowing the rules of how the Euloran world describes itself, the very syntax of world knowledge in Eulora2. Unlike the usual game clients that start by having upfront a ton of data and graphics assets, my client starts without any of those but with a full working knowledge of the solid structure that contains and gives meaning to such data within the game. In other words, my client starts knowing how to obtain and make sense of data and then it proceeds to do exactly that, for as long as it runs and handling without any trouble all sorts of new situations as they appear, supporting thus the expansion of the player’s own increasing knowledge of the game’s world as it evolves with active play.

Knowledge of the game’s world as seen by any given player in Eulora2 is at all times a tree – a finite tree for sure but one that can have any number of branches and any number of levels, changing continuously as well, in response to the player’s actions and to the evolution of the game’s world as the time passes. To support the player, my client repeatedly explores this tree, pruning dead branches, growing new ones as relevant, updating and further interrogating parts of current interest and showing to the user the corresponding world view and its changes as they are obtained from the server in response to specific requests 1. Such showing of the world view is done through the graphical user interface (GUI) by default and through command line on demand. Playing the game relying entirely on the GUI alone is certainly possible but like all and any exclusive reliance on GUIs alone, this is a very limiting proposition really. Up to each player though how they play the game at any given time, for sure, but if you choose to limit yourself in some way, don’t expect that everyone else will necessarily limit themselves the same way, that’s all.

The above approach works to make sense of new content as it appears for a very simple reason: while the exact tree of knowledge for each player will be different and will keep changing throughout the game, its structure will always be syntactically correct, obeying thus at all times the known rules of describing the Euloran world. And since the game is by design and with intent fully open and encouraging players and developers to make or tweak their own clients as it serves them best, this syntax is public and will remain so at all stages. Moreover, any new additions to it will expand its capabilities as needed but without breaking at any point the compatibility with what came before – meaning that there is no requirement to “update” anything at any time. There is the option to do so or not, as and if it suits, nothing more. Like all Euloran evolution, even the world’s own language and corresponding syntax may certainly expand but in an organic manner, opening up new options on top of and building on existing ones, not contradicting nor “obsoleting” anything. In Eulora2 and as a fundamental principle, experience is an asset that keeps on giving – if one builds it up and uses it for all its worth, of course.

As for this knowledge tree itself, let’s illustrate it with an actual small example first and see how it describes the Euloran world or, more accurately, how it describes what one player happens to know about the game world at one given time:

(null, null)
- (Self, 23523903281)
-- (PlayerID, 123503920)
--- [10950238522]
-- (Salt, 8908319)
--- [2a891d0f] 2
- (Sector, 513250013)
-- (NameVal, 120945693)
--- [Waypoint]
-- (Ground, 935410)
--- (CSModel, 10853092)
---- [ea3420d8982]
-- (Sky, 1930582)
--- (CSModel, 8273509)
---- [8ff24351ab92c]
-- (PC, 10950238522)
--- (NameVal, 82082501)
---- [Edward Wealthgore]
--- (Cal3DModel, 98357102)
---- [183cca82bf82e]
--- (Image, 125935601)
---- [1f98eb246caa28]
--- (PosRot, 2795927491)
---- [101, 252, 114, 124, 42, 90]
--- (Item, 9873592011)
---- (NameVal, 873798211)
----- [Coarse Cordage]
---- (CSModel, 17349272)
----- [ff32ea1d89cb0]
---- (Image, 72985711)
----- [91a0b3f28ea8d]

Reading the above would yield the following description of the world: starting from the root of the tree (that null,null first line), there is first of a all a Self (with ID 23523903281) and a Sector (ID 513250013). Further asking the server as to what exactly that Self with id 23523903281 contains yields as children nodes a PlayerID (ID 123503920) and a Salt (8908319). Both PlayerID and Salt are leaf types in our tree and this means that upon asking the server to expand further on these two IDs (123503920 and 8908319), the response will provide directly values rather than further tuples (type,ID): the actual ID of the player’s own character is thus revealed to be currently 10950238522, while the value of the Salt turns out to be 2a891d0f, standing for a file with this exact keccak sum 3.

Going back up in the tree and asking for further information about the Sector (ID 513250013) reveals that it contains a NameVal (ID 120945693), a Ground (ID 935410), a Sky (ID 1930582) and one PC with ID 10950238522. At which point, the client will have found therefore the player’s own character in game, since this ID is exactly the one indicated by that earlier PlayerID node. Given that there is currently no other PC in this sector, it seems that for the time being, this player is either alone in the world or at least not yet seeing anyone else – possibly others are somewhere in the world but not yet within interacting/seeing range.

Drilling deeper into this PC node will reveal that the player’s character goes by the name of Edward Wealthgore, is located at some specific point as given by the value of that PosRot node, carries a Coarse Cordage item and uses as 3D representation as obtained from the graphics assets packed in the file with keccak hash 183cca82bf82e (the value of the Cal3DModel node) and as 2D representation what can be obtained using the file with keccak hash 1f98eb246caa28.

Repeating the same sort of exploration as above for the remaining nodes, in turn, there will be detailed information about each, as relevant, including any contained nodes as well as graphical representations and additional characteristics. I’ll leave the detailed description of the remaining nodes in the above example as an exercise for any reader wishing to test their understanding with a practical application.

While the above may seem tedious when written down in full detail, note that it’s done at all stages internally, automatically and extremely quickly by the client code – it’s exactly the perfect task for computers anyway, using a well and clearly defined structure to hold and process data repeatedly. As the player moves about, they are likely to encounter others and perhaps items too and thus more PC and Item nodes, each with their own IDs, will appear as children of that same Sector node above. If the user drops the Coarse Cordage that they are currently carrying, the corresponding Item node will simply move from its current place as child of the player’s own PC node to become a direct child of the Sector node and perhaps other characteristics of the PC node (not shown in this minimal example) will change to reflect the lighter load carried. Similarly, if the user picks up an item, that item’s node will move to become a direct child of the player’s own PC node and other values may change as well. When the user starts some work, a corresponding node will appear, holding the relevant information and allowing thus the client to provide feedback to the user as to the effect of their action in the world etc.

As to obtaining new data and assets as they become available, the mechanism is the same throughout: on-demand discovery followed by explicit request. For instance, when the client encounters in the world tree a filename that it doesn’t currently have, it will simply request it from the server according to the lower level communication protocol that fully supports such requests and then proceed to use the file as soon as it’s fully downloaded and checked to match the expected hash. Similarly, when it encounters a new node where previously there was none, it will request further information drilling down repeatedly until it gets to the leaves and it knows thus that there is no further information to obtain.

Following exactly that earlier mentioned principle of the client aiming to fully serve the user and empower them to make use of any and all information whenever available, the player can directly interrogate and explore themselves the current tree at any time, simply via an ls command in the game’s own console, quite similarly to how one explores the tree of files on disk from the command line on any computer. Note that this is made available without being either mandatory to use nor in the way of play otherwise – the whole point is to enable and support users at any and all stages, not to force on them anything and especially not to overwhelm them with more information than they request or are able to handle at any given time. Unless asked otherwise, the client will happily do all the above in the background and simply present the results in graphical form as accurately as possible but whenever the user wants to dig deeper and take advantage of the additional flexibility and power that a command line always offers over a graphical user interface, the option is and remains entirely available.

It’s worth noting that the graphical user interface (GUI) is always and at all times a simplified and thus reduced set of options for interaction, never the reference as to what can be done or accomplished. This is simply because it can never be any other way really – the way computers work is always through a set of rules that are quite unaware and unimpended by whatever limitations are introduced by the GUI that has to pick some set of shortcuts essentially out of the full set of real possibilities. Hence, while the game can certainly be fully played through the graphical interface alone and the GUI – or at least the one I make and maintain – will at all times aim to support the user as much as possible, it’s really unlikely that any implementation of a GUI will be ever able to provide in full the same flexibility as the command line offers. For this reason, my client at least has and will always have the command line integrated, alongside the GUI, as the more flexible and ultimately more powerful way to explore and act. Moreover, since the command line is always the reference as to what can be tried and attempted too, be aware that if you limit yourself to the GUI alone, you are more likely than not to miss out.

As for the syntax of world knowledge in Eulora2, the current set of node types and their possible direct children is the following:

ID Node Type Possible children types (if not leaf) Value type (if leaf)
null null 4 Self, Sector, GUI, Chat N/A
0 Sector NameVal, DateTime, CSModel, Ground, Water, Sky, LightSource, PC, NPC, Item N/A
1 Self PlayerID, Salt, WOTFile, DateTime 5 N/A
2 DateTime N/A 3*uint8 for hour, day, month + 2*uint64 for year and era
3 PC NameVal, PosRot, Cal3DModel, Image, Particles, Work, Exchange, Item, Vitals, DateTime 6, Unit_Size, Unit_Capacity, Inventory_List N/A
4 NPC NameVal, PosRot, Cal3DModel, Image, Particles, Dialog, Item, Vitals, DateTime 6, Unit_Size, Unit_Capacity, Inventory_List N/A
5 Item NameVal, PosRot, Image, CSModel, Stack, Item 7, Description, TextLine, Flag 8, Category, RefID 9, Unit_Size, Unit_Capacity, Inventory_List N/A
6 Particles NameVal, Image, Light N/A
7 PlayerID N/A uint32 (4 bytes)
8 NameVal N/A Text
9 PosRot N/A 3*uint16 for position, 3*uint8 for rotation
10 Stack N/A 2*uint64 for quality and count, uint32 for slot number, uint16 for version
11 Cal3DModel N/A text for filename, 16 octets for keccak hash of file
12 CSModel N/A text for filename, 16 octets for keccak hash of file
13 Image N/A text for filename, 16 octets for keccak hash of file
14 Ground NameVal, CSModel, PosRot N/A
15 Water NameVal, CSModel, PosRot N/A
16 Sky NameVal, CSModel, PosRot N/A
17 LightSource NameVal, Light, CSModel, PosRot N/A
18 Light N/A 3*uint8 for r,g,b colours, uint16 for radius of effect
19 Salt N/A text for filename, 16 octets for keccak hash of file
20 Dialog TextLine, Beg, Bribe, Threaten 10 N/A
21 Beg N/A text
22 Bribe N/A text
23 Threaten N/A text
24 TextLine N/A text
25 Work NameVal, Percent, NPCID N/A
26 NPCID N/A uint32
27 Percent N/A uint8
28 GUI Skin, Branding N/A
29 Branding N/A text for filename, 16 octets for keccak hash of file
30 Skin N/A text for filename, 16 octets for keccak hash of file
31 Exchange PartnerID, Give, Receive N/A
31 Give Flag 11, Item, FixedList N/A
32 Receive Flag 11, Item, FixedList N/A
34 PartnerID N/A uint32
35 Flag N/A uint8
36 Chat NameVal, Lowest, Highest, Description N/A
37 Lowest N/A uint64
38 Highest N/A uint64
39 Description N/A Text
40 WOTFile N/A text for filename, 16 octets for keccak hash of file
41 Vitals N/A 12*uint8 for percentage of each vital
42 Skill NameVal, Description, Level N/A
43 Level N/A 2*uint8 for experience and knowledge, respectively, followed by 1*uint64 for rank
44 Category N/A Text
45 RefID N/A uint32
46 FixedList N/A count (uint8), count*(uint32, uint64) for count pairs of id,quantity
47 Training PartnerID, Flag, FixedList N/A
48 Rating PartnerID, Flag, Description, DateTime N/A
48 Unit_Size 12 N/A weight (uint32), bulk (uint32)
48 Unit_Capacity 13 N/A weight (uint32), bulk (uint32)
49 Inventory_List 14 N/A version (uint16) 15, n (uint8), n * (count uint64, quality uint64, SHC 16, 6 octets)

In addition to the above, some constants have a fixed assigned meaning in their respective contexts:

Context Constant Values and Meaning
requesting to attempt a specific activity ID of activity 0 for Explore (and default);
1 for Use

The above syntax has been in use successfully for a couple of years already so it’s not going to change fundamentally. New node types are likely to be added as the implementation proceeds further but they will be added to this list, as needed. Even at this time, I don’t quite see the case for removing some node types and even less so for altering them since that would indeed be the only way in which compatibility is broken. Nevertheless, until access to the client is widely open to everyone, consider the list above as a work in progress rather than fixed and otherwise as an invitation and opportunity to get involved perhaps, if you do your own implementation and have any questions related or otherwise relevant to it.

Any related discussion is welcome and can best happen in the comments below, as usual.

  1. Note that the server for Eulora2 serves essentially as an oracle for the game – it answers any and all queries but it never pushes information unasked. This is by design, fully intended as such and entirely unlikely to ever change. There’s a wide scope for client implementations to compete though on different approaches to best make use of the server oracle for their users and thus provide an in-game advantage that players will be willing to pay for.[]
  2. This as all numbers in here are given as example only and as such, rather shorter than the actual values.[]
  3. Given here in hex for easy distinction of file hashes vs other values so it’s easier to follow with an actual client at hand, since the client uses this hex string to name the file on disk. Otherwise the value of that keccak sum is sent from the server directly as a number as obtained from keccak, of course.[]
  4. This is by convention the root of the tree and there is always at all times one single root.[]
  5. Expiry date meaning the in-game time until when current sustenance lasts.[]
  6. birth date, if known[][]
  7. This is because some items can contain other items, of course.[]
  8. Currently used masks over this are 0x10 for Locked, 0x02 for Inaccessible[]
  9. referenced object, if any, e.g. keys reference the item they unlock[]
  10. This was an early test and it works fine but meanwhile my design moved away from pretending to have “dialog” with bots and towards an altogether more promising quest system. For now though this node is still possible to encounter, indeed, hence it’s shown in here.[]
  11. 0x10 for locked, 0x0C for approved[][]
  12. This is the approximate size of one unit of whatever the parent is, given in some consistently-used unit across the whole game at any given time.[]
  13. This is the approximate capacity of one unit of whatever the parent is, given in some consistently-used unit across the whole game at any given time.[]
  14. A faster but more restricted view of the items contained in something – the server decides at all times whether this is used or not.[]
  15. Increased by at least 1 and at most 255 at each change.[]
  16. Shorthand code, unique across basic items in Eulora 2, obtained as upper case letters as found in order in the item’s basic name excluding any additional prefixes and suffixes[]

July 10, 2023

Static Standalone Zip Lib for C or Ada Use

Filed under: Coding,Eulora — Diana Coman @ 5:23 pm

‘Why?’
Because I need and use it.

‘What?’
The full, C-only code for zip archive operations of all sorts, entirely standalone and free of autotools and the like, ready for my intended use directly from Ada code and easily extendable for any other specific use from either C or Ada. It produces and uses standard zip archives. It comes with all needed headers, bells and whistles, a minimal .gpr file for compilation with GNAT as a static library and some commented out examples, too. The heaviest part of it is, unsurprisingly, the code for zip operations that weighs in at 10130 lines in miniz.h. The rest of the code adds about 2400 lines more in total.

To expand a tiny bit on the above, I’m using this exact code as part of the fully automated graphics pipeline that generates on demand any and all graphics that Eulora2 needs, as it needs it. I haven’t bothered to “clean” the code to any specific extent beyond the very functional – it either serves or at least stays out of my way. As such, I think the code as it is currently makes, if anything, a good place to start for someone wanting to learn to read effectively code, perhaps – it’s reasonably big without being too big and otherwise written and packed at all points by people focused on their own needs for it, not on ticking something off some check lists or using up some time at work.

I’m publishing the code as a 1st edition of MiniZipLib, in VaMP format, of course, since it can be perhaps useful to others if/when they want to avoid depending on external code for any zip-related needs.

Note also that the client for Eulora2 relies currently on something else, essentially external zip code even if this external dependency happens indirectly, via CrystalSpace. This is because all graphics assets are stored and used as .zip files that group together the various parts and pieces that are required at times to make a full model or item. While my current main interest and use for this lib is mainly serverside, the client could certainly benefit as well from reducing its dependency on external code and integrating this. Currently I don’t have the time to do it though as the further development of the game itself takes precedence but I’m making the VaMP tree for it public via this 1st edition, so that others can pick it up if they need it.

As usual, feel free to ask relevant questions in the comments, below. If you don’t know and need to find out where the code is thus published, it’s likely though that you are still missing an earlier step, namely interacting with people so read perhaps a bit more around and see what pulls you in so that there is some better starting point for it all than mere code ever was or ever will be.

June 13, 2023

The Communication Protocol for Eulora2, Restated

Filed under: Coding,Eulora — Diana Coman @ 12:48 pm


As the game‘s development is progressing beyond the emergence of time, past the addition of vitals and into enabling player activities, all the design and implementation work done so far feeds as well into clarifying and refining the game-related parts of the communication protocol that were previously tentatively and incompletely stated 1. Specifically, it’s again that ‘Character Actions’ section 7 that comes into focus but this time the changes go beyond just simple additions and move things forward from where the previous effort towards specification stopped. Consequently, I have to bring together the different parts and restate the current take on the protocol in full, in here, where it can be further iterated and discussed as needed:


This is the current take on Eulora2’s communication protocol, last revised June 13th, 2023.

1. Overall Goals:

  • 1.1. All communications between clients and server to be encrypted.
  • 1.2. Clients to be able to receive from server any data they lack (including maps, skins, sound or video content etcetera), on demand.
  • 1.3. Clients to be able to choose and adjust both the level of security and their volume of communications with the server, as they will ultimately have to pay for the load that they generate.

2. Explicit Dependencies :

3. Data Structures :

    3.0. Basic types :

    • char / uint8 (1 byte) ;
    • uint16 (2 byte) ;
    • uint32 (4 byte) ;
    • uint64 (8 byte) ;
    • float 2 (4 byte) ;

    3.1. Special types:

    • hash (128 bits) ;
    • chunk [of file] (bitfield, 11760 bits) ;
    • serpent-packet (1472 bytes) ;
    • rsa-message 3 (1872 bits 4) ;
    • rsa-packet 5 (1470 bytes) ;
    • object (size of 104 bits 6: uint32 7 followed by 3 uint16s representing position 8 followed by 3 uint8s representing rotation 9 ) ;
    • legacy-text (size of n+n/256+1 bytes ; where the leading byte is the bytecount of the 2nd segment and the 2nd segment is the bytecount of the third segment) 10.
    • text (2 byte hearder containing the ~total~ byte length ; up to 1470 bytes of text ).

4. Serpent Packets 11 :

    4.1. Serpent Key Set:

    • uint8 (type ID, =100), followed by
    • uint8 (count of keys in this set, n), followed by
    • n*(4*int64 + uint32) (32 bytes each key followed by a 4 byte ID calculated through crc32 12 ), followed by
    • an uint8 flag (LSB bit set — keys to be used to talk to client ; MSB set — key to be used to talk to server ; client-set MSB is ignored), followed by
    • uint16 (message count 13), followed by
    • padding to Serpent-message length.

    4.2. Serpent Keys Lifecycle Management:

    • uint8 (type ID, =102), followed by
    • uint8 (count of server keys requested), followed by
    • uint8 (count of client keys requested), followed by
    • uint8 (id 14 of serpent key preferred for further inbound Serpent-messages), followed by
    • uint8 (count of burned keys in this message), followed by
    • n*int8 (id of burned key), followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length.

    4.4.a. File Request, manifest

    • uint8 (type ID, =3), followed by
    • hash (corresponding to the sought file 15), followed by
    • uint8 (manifest packets sought count, 0=all), followed by
    • n* uint16 (manifest packet index sought), followed by
    • padding to Serpent-message length.

    4.4.b. File Transfer, manifest (always sent and only sent in response to ID 3)

    • uint8 (type ID, =4), followed by
    • uint16 (count of manifest packets for this file 16), followed by
    • uint16 (index of current packet in list above), followed by
    • uint8 (fragment count 17), followed by
    • n* uint64 (hash of the nth fragment of manifested file).
    • uint16 (keccak hash of foregoing), followed by
    • padding to Serpent-message length.

    4.4.c. File Request, chunks

    • uint8 (type ID, =5), followed by
    • hash (corresponding to the sought file), followed by
    • uint8 (file chunks sought count), followed by
    • n* uint64 (the hash of fragment sought), followed by
    • padding to Serpent-message length.

    4.4.d. File Transfer, non-last chunk (always sent and only sent in response to ID 5)

    • uint8 (type ID, =6), followed by
    • chunk.

    4.4.f. File Transfer, last chunk (sent at most once per ID 3)

    • uint8 (type ID, =7), followed by
    • uint16 (bytesize of useful part of the chunk following 18, followed by
    • chunk 19.

    4.5. Client Action 20 :

    • uint8 (type ID, =8), followed by
    • text (fully specified action, see section 7), followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length.

    4.6. World Bulletin 21:

    • uint8 (type ID, =9), followed by
    • uint32 (id of top level item 22), followed by
    • uint8 (count of objects), followed by
    • object list 23, followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length.

    4.7. Object Request:

    • uint8 (type ID, =10), followed by
    • uint8 (count of objects), followed by
    • n*int32 (id of object), followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length.

    4.8. Object Info:

    • uint8 (type ID, =11), followed by
    • uint8 (count of objects), followed by
    • n times uint32 (id of object) and text (object properties, as per extant game structures, including art files needed and so on 24), followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length.

    4.9 Line Request

    • uint8 (type ID, =12), followed by
    • uint8 (count of lines), followed by
    • n times uint32 (id of chatroom), uint64 (lowest line number requested), uint64 (highest line number requested), followed by
    • padding to Serpent-message length

    4.10 Line Info

    • uint8 (type ID, =13), followed by
    • text (line content), followed by
    • uint32 (chatroom ID), followed by
    • uint32 (speaker ID), followed by
    • uint64 (line number), followed by
    • uint64 (keccak hash of the line’s content and number), followed by
    • padding to Serpent-message length

    Updated 30 Oct 2024: ratings are now fully integrated and used in-game, being fully handled via the relevant Rating node in the data hierarchy. Consequently there is no need anymore to have dedicated message types for discovery and retrieval, so the “rating request” and “rating info” message types below are removed entirely. Rating someone remains done as an action (see the action types further down) and discovery happens as part of the usual game play.

    4.11 Rating Request

    • uint8 (type ID, =14), followed by
    • uint8 (count of requests), followed by
    • n times uint32 (source ID), uint32 (target ID), followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length

    4.12 Rating Info

    • uint8 (type ID, =15), followed by
    • text(rating comment 25, followed by
    • uint32 (source ID), followed by
    • uint32 (target ID), followed by
    • uint8 (rating value 26 ), followed by
    • uint16 (message count), followed by
    • padding to Serpent-message length

5. RSA Packets 27 :

    5.1. RSA key set 28.

    • uint8 (equal to 251 to indicate packet contains a new RSA key), followed by
    • uint8 (protocol version), followed by
    • uint16 (subversion), followed by
    • uint32 (IP of server 29), followed by
    • uint32 (IP of client 30), followed by
    • uint64 (keccak hash of client binary), followed by
    • uint64 (e of RSA key), followed by
    • uint8*490 (N of RSA key), followed by
    • uint64 (preferred padding — the magic value of 0x13370000 requests random padding ; all other values will be used as such, bitwise, ie like an infinite-length OTP consisting of the value repeated), followed by
    • uint16 (message count), followed by
    • padding to RSA-message length, 1424 (5616-8-8-16-32-64-64-3920-64-16) bits exactly.

    5.2. Serpent key set 31:

    • uint8 (equal to 157 to indicate packet contains new Serpent keys), followed by
    • uint8 (count of keys 32 in this set, n; n<=19 33), followed by
    • n*(4*int64 + uint32) (32 bytes each key followed by a 4 byte ID calculated as crc32 on the key itself), followed by
    • an uint8 flag (LSB bit set — keys to be used to talk to client ; MSB set — key to be used to talk to server ; client-set MSB is ignored by server ; server will set LSB on keys requested by client for its own use thus supporting clients with no trustworthy random generators of their own), followed by
    • uint16 (message count), followed by
    • padding to RSA-message length.

    6. Protocol Mechanics :

      6.0. All communications between server and client will consist of messages. These messages may be encrypted either via eucrypt.RSA or eucrypt.Serpent. All RSA-encrypted messages will be exactly 1`470 bytes in length ; all Serpent messages will be exactly 1`472 bytes in length 34 . The server will handle Serpent messages in preference of RSA messages (which are processed on an as-available basis). Clients that send garbage will be punished ; the costs involved (encryption/decryption ; generating entropy ; lookups and whatnots) will be pushed onto the client, for which reason writing the clients lightly pays off.

      6.1 The handshake works as follows:

      • New client issues 5.1 packet keyed to the server’s public key, including its own RSA key.
      • The client’s IP is recorded, and will have to be explicitly changed by the client later if needed. Server replies with 5.1 packet keyed to the client’s announced key, including its private RSA key for use by that client ; and with 5.2 packet containing key material for client’s use in keying messages to the server. If the client fails to provide its own set of serpent keys, the server will further issue it a set of serpent keys ; thenceforth the server will send more serpent keys mirroring the client’s supply, and will similarily mirror key burning and select operations on its own set.
      • Should the client’s IP change, it will issue a 5.1 packet keyed to the server public key immediately followed by a 5.1 packet keyed to the server’s original private key. The server will then update the client’s IP accordingly (this also trashes the extant Serpent keyset and triggers 5.2).
      • The bulk of communication is intended to go through the Serpent system ; outside of identification and bootstrap handshakes RSA isn’t used. Should either party believe the Serpent keysets’ve been FUBAR’d, a 5.2 packet will reset that keyset.

      6.2. The server will issue type 4.6 packets in response to relevant type 4.5 packets received — these can either signify the acceptance or the rejection of the client action, and the client must adjust its internal state accordingly.

    7. Character Actions :

      7.0. Lock:

      • uint8 (type ID, =0), followed by
      • uint8 (count of objects), followed by
      • n* uint32 (object ids). Defaults to currently targeted item.

      7.1. Make 35:

      • uint8 (type ID, =1), followed by
      • text (title of quest), followed by
      • u64 (count of how many different times can this quest be completed – note that the reward will be divided accordingly), followed by
      • uint32 (arbiter id, defaults to nearest town crier), followed by
      • uint32 (object id of a sample of the required item), followed by
      • uint64 (wanted quality, defaults to 1), followed by
      • uint64 (wanted quantity, defaults to 1), followed by
      • uint8 (expiry day, defaults to 1), followed by
      • uint8 (expiry month, defaults to 1), followed by
      • uint64 (expiry year, defaults to next year), followed by
      • uint32 (object id of reward item stack, no default)

      7.2. Attempt 36:

      • uint8 (type ID, =2). This is a request to start the chosen activity (see next field), followed by
      • uint32 (object id, indicating the intended activity, defaults to explore 37), followed by
      • uint32 (object id, defaults to current target or location, as relevant), followed by
      • uint32 (object id, defaults to currently equipped method, followed by 38)
      • uint32 (object id, defaults to currently equipped tool)

      7.3. Exchange:

      • uint8 (type ID, =3), followed by
      • uint32 (object id, the other party), followed by
      • uint32 (object id, the trade itself 39), followed by
      • uint8 (count of objects), followed by
      • n* uint32 (object ids) and uint64 (object count), followed by
      • uint8 (flag, set to 0x10 to lock a trade and to 0x0c to approve a trade previously locked by both players).

      7.4. Attack:

      • uint8 (type ID, =4), followed by
      • uint32 (object id, the other party), followed by
      • uint32 (object id, the battle itself (server set, exactly in the way trade works). This not currently implemented, except player setting itself the bomb results in instadeath.

      7.6. Move:

      • uint8 (type ID, =6), followed by
      • uint32 (destination id, defaults to current target), followed by
      • uint32 (slot id), followed by
      • uint32 (object id, of the item being moved), followed by
      • uint32 (quantity moved).

      7.7. Train:

      • uint8 (type ID, =7), followed by
      • uint32 (object id, the other party), followed by
      • uint32 (object id, the train session itself (server set, exactly in the way trade and battle work). This not currently muchly implemented, except some NPCs train for money — but will get greatly expanded asap. Meanwhile, it actually got both expanded and implemented, see the relevant comment for more details.

      7.8. Relocate:

      • uint8 (type ID, =8), followed by
      • object type, containing new client position.

      7.9 Say 40:

      • uint8 (type ID, =9), followed by
      • text (line content), followed by
      • uint32 (room ID), followed by
      • uint64 (keccak hash of the line’s content)

      7.10 Rate:

      • uint8 (type ID, =10), followed by
      • text (rating comment), followed by
      • uint32 (target ID)
      • uint8 (rating value)

      Please leave your comments below.

      1. This type of iterative refinement and interaction between design and implementation is neither new nor surprising to me, really. The only difference is that I’m doing now out of necessity all sides of this. Experience helps *a lot*, of course, even or perhaps especially beyond and above what one ‘expects’ or what one ‘wants’ or what one ‘signed up for’ and so on and so forth. It might even help in the sense that it makes it possible at all, at that, even if it doesn’t make it easy by any definition of the word.[]
      2. Floating point item deliberately not specified[]
      3. Each such message is OAEP-padded and then encrypted with a (3920 bit) RSA key. Three such messages are strung together to form a RSA packet. Because of the significant overhead involved (both in terms of space and time), Serpent-encrypted comms are preferred whenever feasible. []
      4. See TMSR-RSA OAEP padding for the principle and this discussion for details.[]
      5. This is the total size of a packet containing RSA-encrypted material. The useful size (ie payload) of such a packet is merely 702 bytes.[]
      6. We really really want to keep this down. 13 bytes is the lowest I can conceive of, but I would so not mind halving it.[]
      7. Representing the identifying hash of the object in question.

        We’re using the narrower size to save on network traffic — all the expenditure of another 32 bits here would buy us is de-ambiguation for cases where the count of objects around makes 1 in 2 billion collisions relevant. It doesn’t seem likely a client could support such abundance of objects.

        Note that the hashes used here are client-specific, the server doesn’t leak its own internal representation of objects to the clients.[]

      8. Coordinates X, Y and Z in that order. Because the map goes from -512 to +512, the relationship between the given figure (GF) and map coordinates (MC) is GF / factor_coord – max_coord = MC, where max_coord is 512 and factor_coord is 65535/(2*max_coord).[]
      9. As a full rotation is 2 pi, the relationship between the given figure (GF) and object rotation (OR) is GF / 128 * pi = OR.[]
      10. This arrangement permits the representation of arbitrarily large textfields (2nd segment can represent up to 115`792`089`237`316`195`423`570`985`008`687`907`853`269`984`665`640`564`039`457`584`007`913`129`639`936 bytes, which is more than enough space for all the text ever produced — or likely to ever be produced — by humanity) at the modest cost of a fixed 3 byte header.

        Unfortunately, it has no longer any utility for Eulora, since we’ve moved to fixed packets. I’m preserving it here because I really like it in the abstract and it has no other place to go.[]

      11. These packets consist of 92 successive 128 bit chunks, Serpent-enciphered individually. To extract the payload one splits the message into 92 16-byte chunks, deciphers them then collates the output into a final result. To produce the packet one cuts a 11`776 bit payload into 92 128-bit chunks, Serpent-enciphers them, and collates the results into the outbound packet.[]
      12. Polynomial generator 0x04c11db7. Keys with null IDs are discarded and regenerated.[]
      13. Each client and the server will keep a count of messages they sent each other. This value must be incremented on each subsequent message sent by no less than 1 and no more than 255.[]
      14. Keys are maintained by both client and server in an ordered ring buffer 256 elements long. The server will not send more keys than the total count of 0(absent)-keys in the respective buffer, irrespective of request count. If the message contains an unknown ID or otherwise is unprocessable, the issuance of a 5.2 packet is adequate response.[]
      15. This is the keccak hash of the actual file contents. By convention this hash rendered as a 32 alphanumeric character string is also used as the filename for the file in question.[]
      16. This system allows up to 65`536 manifest packets, adding up to potentially 11`993`088 (65`536 * 183) fragments representing a file of up to about 140 Gb (141`038`726`624 = 11`993`088 * 11`760 + 11`744 bits exactly). This will have to be sufficient.[]
      17. From 1 to 146 inclusive.[]
      18. This also means the protocol does not allow the transfer of files of certain sizes (within 8 bits of a multiple of 11760), which is fine with me.[]
      19. The final fragment of the file will have to be padded to length as per this spec. []
      20. This is never issued by the server.[]
      21. This is never issued by the client.[]
      22. As discussed in comments, the world is a hierarchical structure of objects within objects.[]
      23. This portion will get more clarification later on! []
      24. The complete list of these is currently exposed by the extant client, but in any case we’ll publish a complete schematic. The server will set the “target” of the player on the last object in the list.[]
      25. Limited to at most 1445 characters, matching the maximum length of a chat line.[]
      26. Valid rating values are integers between -10 and 10. For a given rating value here GR, the corresponding actual rating value RV is therefore calculated as: Min(GR, 20) – 10.[]
      27. These packets consist of three 490 byte successive chunks RSA-encrypted individually. To extract the payload one splits the message into three 490 byte chunks, RSA-decrypts and de-OAEP-pads each one, the collates the results into a final result. To produce the packet one cuts a 5`616 bit payload into three 1`872 bit chunks, OAEP-pads and encrypts them, and collates the results into the outbound packet.[]
      28. This is the manner in which new clients register their RSA key with the server (thereby opening a new game account). Later replacement of a registered key IS NOT POSSIBLE. Keep your client’s RSA key safe.

        This is also the manner through which IP changes for an account are registered with the server. See the Protocol Mechanics heading for details.[]

      29. This is used by the server when signalling to the client to talk to a different server (which is a thing for scaling, because different sectors will be handled by different servers).[]
      30. If the client doesn’t know its own IP, it’s acceptable for this to be zero. []
      31. This permits either client or server to declare Serpent keys via RSA. It is not mandatory (as there exists a Serpent-encapsulated mechanism for the same end) but entirely legal. The server will always respond with at least one 5.2 packet after an accepted 5.1 packet creates a new player account, consisting of 40 Serpent keys to be used to talk to the server. Should the client respond with any other packet than 5.2 or 4.1, the server will send a 2nd 5.2 packet, containing 40 Serpent keys for the client’s use. []
      32. Keys obtained through a 5.2 packet are always indexed in the client’s buffer in the order they were found in that packet, starting with the first position.[]
      33. A RSA packet has 702 total bytes available, of which 5 are used otherwise and the remainder of 697 are available for packing serpent keys, which take 36 bytes each (crc32 id inclusive).[]
      34. Length being actually how they’re sorted on the server side.[]
      35. This is meant as a production order, essentially. I expect it will get further refined as its implementation gets nearer. It already got further refined and more specifically defined as a way to issue/create Quests or “wanted” posters fundamentally, see the relevant comment on quests.[]
      36. This is a generic initiation of player activity and as such literally an attempt, with the contents defining the exact activity. It replaces both Explore and Repair from earlier versions of this protocol but it further stands in for *any* game-defined activity even ones that may appear only at a later time. It’s as generic as it gets and quite on purpose, since this is the network layer, not the game layer. For more details on the game-defined activities, see the description of the data hierarchy.[]
      37. Known activities are obtained like everything else in game as part of the data hierachy representing the client’s view of the world at any given time. The relevant grammar for it will be made public as it serves as the in-game protocol specification just as this serves as the network-level client-server protocol specification.[]
      38. Known in Eulora 1 as ‘recipe’ and ‘equipped in mind’. At this level, the protocol for Eulora2 is really more generic than that, without any loss otherwise whatsoever.[]
      39. This is set by server through a type 6 message for both players involved, the trade is an object like any other that the OP has to request. The server will also expire trades, enforce them etc.[]
      40. Note that this is an action and as such just a part of a 4.5 message, Client Action, where the overall message structure is specified.[]

June 5, 2023

The New Action Type That Almost Was

Filed under: Coding,Eulora — Diana Coman @ 3:32 pm

The quickly progressing work on euloran vitals and physical characteristics is pushing already the design – and the fun, obviously! – into previously unmentioned and thus entirely uncharted areas. This time it all started easily enough: given that at least some vitals certainly drain with activity, what does unrest truly do to one’s wellbeing, what is rest going to even look like and what can one really do -or not do, rather- about it for best results?

As all good questions, the above has, of course, a common-enough answer that isn’t much good really but still has to be properly considered, first of all: unrest tends to do more to one’s worsebeing rather than to one’s wellbeing and rest is certainly needed so introduce a ‘rest’ action that the player can choose to do whenever they feel like and the game permits! Which sounds reasonable enough and doable enough, to the point where I even sketched out a new addition to that section 7 of ‘character actions’ in the communications protocol, since it’s really not all that difficult to add or use: have another ID, give some duration in hours now that time is ticking away at everyone’s lives and use otherwise the existing infrastructure without much trouble at all. It would certainly work too, so what’s the problem with adding it, right?

Well, the problem starts with that ‘adding’ really, since the whole point of having a flexible and generic communications protocol is exactly to have a set of messages and structures that can serve a wide range of uses while being preferably as short as possible 1. So any addition to the protocol itself comes with a non-negligible cost and thus with a strong requirement for considering first whether there is indeed enough of a fundamentally significant difference compared with already existing structures to justify a new one 2. Unsurprisingly perhaps, it turns out that where euloran rest is concerned, there isn’t that strong a case for a new action type as such – or at least not yet!

So then, if resting is both possible and needed in Eulora2 but it’s not to be done in the common style of being an action, how is it going to happen? The very simple answer is that it will happen by *effect*. Meaning, specifically, that different items will have a resting effect when consumed or otherwise used (and their use or consumption might take some time, too, possibly).

Further, the above approach to rest implies, of course, that one has to have such an item to even be able to rest at all, which might, at a first encounter, seem quite the alien and possibly harsh imposition (everyone can rest whenever, all they have to do is go to sleep!!), except it’s not really – just try it and see how well it goes when you try to rest without having at the very least some reasonably safe (quiet and cosy don’t even come into it) place, enough peace of mind and enough food to keep hunger at bay. Rest is indeed basic in the sense that it’s a basic requirement for survival not in the sense that it’s somehow effortless or a given at all times.

As a side effect of the most positive kind from the above, it follows of course that one would do better to keep an eye on their levels of tiredness – at least in Eulora2, since this is what the context is here. Because if they fail to rest when needed, things aren’t likely to go that well and for sure they aren’t going to go forever just because it’s a game or something. Past a certain point of tiredness, the body would naturally shut down and thus rest indeed of sorts, only it’s not all that clear if, when or how one still wakes up from such last-resort rest that is indeed guaranteed and a ‘natural right’ of everyone 3, certainly.

In summary, in Eulora2 you’ll live either responsibly or very, very briefly indeed! Practical learning, at its best.

  1. And seriously, I can still fully recall the spidery mess of a ‘protocol’ that PS originally had and what a pain it was to first work with it at all, then attempt to clean it and finally sideline it enough until one could entirely get rid of it. That experience certainly is more than enough to teach one to NOT rush into adding stuff just because it’s possible.[]
  2. For the record, such was indeed the case with the Chat additions – while they *could* be fit into the already existing structures, such fit was a very poor one because the types of use are quite different fundamentally and have thus very different requirements.[]
  3. Weeell, maybe just about everyone? I don’t promise that there won’t be any immortals/vampires/rest-impaired creatures in Eulora2![]

May 30, 2023

The Many Moons of Euloran Time

Filed under: Coding,Eulora — Diana Coman @ 4:31 pm

The latest development in Eulora2 is the emergence of time itself, quietly but definitely ticking away at the hours that became days, then months and years of the very first era that eulorans ever knew. Euloran time is already past the half mark of the first month and it follows its own rules, whether anyone is aware of them or not. So far, there are at least some signs that some people have indeed noticed something new:

back in, and noticing a new euloran clock.

e2_clock_1_640.jpg

It’s possibly best if one starts becoming aware of the rules of time or at least aims to figure them out sooner rather than later, because the time in Eulora2 is definite indeed: definite in the same way that Maths is definite but also, perhaps of more pressing interest for eulorans, in the same way that Death is definite. On the more reassuring side, so far at least, Death is yet to be met with in Eulora2 but that’s about as much knowledge as anyone has on the matter.

As to the durations and even structure of euloran days, months and years, these are still to be observed. What I will let slip is that Eulora2 has several moons that might be abstract or concrete but that certainly have very concrete effects on the world as a whole. To some extent, it might perhaps be not even false to say that the very ticking of time is just one of the more visible such effects – the rest yet to be noticed, observed and perhaps made some sense of. Not that there is any rush to do or even to notice any of it – at least there isn’t anything to rush one just yet. It’s a young world after all, still emerging, unhurriedly but unstoppably, too.

The whole first era of Eulora2 will cover in fact exactly the interval when the core structure of the world and of its interaction principles is brought in and settled in place, piece by piece. Those present and active in this first era will be essentially the actual ancestors and prime movers quite literally – after all, they are taking the risk on a nascent world and so they get also, by rights, a special status and the unique chance to leave their inprint on each part as it emerges. And there certainly are quite a few parts in the works, with next on the list the actual vitals and physical characteristics of player (PC) and non-player characters (NPCs) just the same.

Time, in this sense of Eulora2 emergence, is quite literally only the beginning!

May 4, 2023

Software Editions

Filed under: Coding,VaMP — Diana Coman @ 7:48 pm

How about approaching the hot problem of ‘getting people to care about what software they run’ 1 from a place of meaning rather than mere ease of use?

To get to such place of meaning, one would need at the very least to be able to tell confidently at any time what a software version even is and what does it mean. Surprisingly or not, the current way in which software versions are ‘defined’ and reported doesn’t really provide much to be confident about and even less to rely on. Luckily though, the needed tools to change this for the better are in fact available, so let’s look at the whole trouble and then the working solution to it all, too.

Through historical accident rather than planning of any sort, software ended up with a rather weak approach to versioning that seems good enough only as long as one doesn’t try to lean on it too strongly. Generally, versions for software code are given simply as numbers picked more or less transparently 2, embedded in the code and then simply read and reported to the user at runtime, on request. So the code says that it’s version x.y and the user… takes the code at its word because there isn’t much else to do.

Well, there *wasn’t* much else to do until now but from now on, there is, courtesy of VaMP: software editions rather than mere versions, offering cryptographic guarantees and embedded historical records that you can check at any time and as often as you like.

Let’s start directly with an illustration of use, checking the software version and edition of VaMP itself – and not just any edition but precisely the one that makes available… software editions:

$ vamp version vamp_sw_ed/
************
The code in vamp_sw_ed/ matches a signed software edition and has the following version description from manifest.vamp in vamp_sw_ed/:

787977 vamp_sw_ed Diana Coman Adds software editions, check and reporting via the new ‘version’ command including authorship (from patch), readership (from sigs) and version info (from manifest file). Further cleanup and improved usability including consistent usage help and order of parameters for all commands (generally the aim is to have command input(s) resource(s) output(s) where resources are supporting the task rather than direct inputs to the task at hand and are usually given as paths, e.g. location of patches, sigs or keys to consider). Adds better support for multiple signatures of the same file through a naming scheme for sig files that includes the base name of the relevant keyfile (which is by default the key’s fingerprint).

The software edition producing this exact code version is:
data/patches/vamp_sw_ed.patch
authored by 7ddde85da027e48a9a23aa8573079fff
signed by 7ddde85da027e48a9a23aa8573079fff

Software editions are the code equivalent of literary editions. Just as there are any number of drafts produced before an edition of a book is published, so there are any number of code versions made before a software edition is published. Just as there are others besides the author of a literary work that have a role in and responsibility for a literary edition of a book, so there are other roles and responsibilities for a software edition besides that of writing code. In the most direct terms, a software edition contains and requires more than the code itself – it’s a more rounded product that includes as a minimum and in cryptographically verifiable forms, three main parts: the record of the code’s history, the published code and the personal responsibility assumed by the publisher, whether that is the same person as the writer or not.

In more concrete terms and as a standard minimum, a software edition will therefore include:

  1. The cryptographically verifiable means to obtain a specific code version, consisting in:
    1. A VaMP patch.
    2. The publisher’s 3 matching signature of the above patch.
    3. The publisher’s public key that can be used to verify the above signature.
  2. An embedded record of the code’s versioning history in the form of a plain text file called manifest.vamp that is part of the code version published in this edition. Each code version adds a new line to the manifest.vamp file, including:
    1. The Bitcoin blockheight at the time when the new code version was created, as the only universal timestamp currently available. Wherever you are in the world when you write a new code version, the blockheight is a more accurate description of time than any ‘local time zone’ and as such, it’s entirely immune to any and all ‘challenges’ of traditional timestamps, of course.
    2. A short name for the new code version. This tends to serve as the filename for the patch that results in the new code version but note that this is just a convention, not mandatory in any way. The patch can really be called anything at all and one can certainly have any number of different patches that still result, each of them, in the same code version 4.
    3. The name of the writer of this new code version
    4. A summary of the main changes/additions to the code brought in by the new code version.

In addition to the above, a software edition can include, of course, just about anything else that the publisher wants to include. There is for instance a reasonable case to make perhaps for a record of editions themselves, seeing how they are essentially on a different level than software versions and as such not included in or made visible through the manifest.vamp file. To make the distinction clear, the manifest.vamp file is a historical record of all changes made to the code, hence strictly speaking of all code versions whether published or not. By contrast, editions are signed packagings of specific code versions for which the publisher assumes personal responsibility by signing them with their own key.

Different publishers can maintain their own sets of editions even for the same software and the patches involved may very well be different but the same version of the code has to have the exact same manifest.vamp file in all editions – if that’s not the case, then it’s simply not at all “the same version of the code” regardless of what one might claim. So publishers may well keep an additional record of their own software editions, whether signed or not, whether in file format or web format and so on. In doing so, they build up their own record, of course and as such can reap the accumulated benefits for their own work over any period of time.

For some additional clarity, let’s see also side by side what would the differences be between software changes, versions and editions as supported by VaMP:

Description Format
Change Any addition, deletion or substitution. A change can be as small as one character in one single file and as big as a full replacement of all files on one’s computer, there is no limit to its scope. There is also no responsibility assumed explicitly and verifiably by anyone for it. The thing changed and you as a user might know or might not know about it but you’ll certainly have to live with the results of it, regardless. Automated updates and other viruses.
Version A code state that is fully described and signed for in a cryptographically verifiable manner and that includes a relevant line in the manifest.vamp file describing the changes made from the previous code state. Whether some code is or not in the described state matching a specific version can be checked reliably at any time and as often as desired without any side effects and detecting any change regardless of its size. A VaMP patch together with its signature by a RSA key in your WoT. Alternatively, an index of the relevant code state together with its signature by a RSA key in your WoT.
Edition The cryptographically verifiable and signed means of obtaining a specific code version including as a minimum its historical record of changes, its known authorship, readership and the identity of the publisher. One or several VaMP patches together with their signatures by the publisher and possibly by others, as well as the publisher’s public RSA key.

In a nutshell, by providing software editions, VaMP leverages cryptography to empower personal users, writers, readers and publishers of software or in other words, everyone who uses computers at all. Combined with RSA keys for personal identity and the Web of Trust (WoT) as public record, software editions are a part of the wider structure and approach that can give people as opposed to bots (or the ‘AI’) the edge even in this digital environment which is otherwise not at all human-friendly.

Whether enough people figure it out and make good enough use of it before the deluge of bot-created ‘content’ is too great to even find one’s way to any meaning anymore is something that depends on each individual person, as simple as that. As my public record shows, I have always been firmly on the human side on this and I don’t plan to stop any time soon so I’ll continue working to increase and support people’s leverage as connected individuals, first and foremost, not the bots’ training data sets or the like. What you do though, as always, is entirely your choice and note that you make it with every action you take or refuse to take, whether you realise what you are thus choosing or not.

  1. It is actually a hotter problem than it might seem. It’s not *just* that so much runs today in and on software of all sorts but also that the bots (alternatively termed ‘AI’) have the natural advantage when it comes to the digital environment in general and code or machines in particular. The popular current approaches to ‘make coding like plumbing’ or to rely on ‘AI’ to ‘write code’ can only make it worse, not because they’ll take away jobs but because they’ll end up inevitably by drowning everyone in such an endless amount of meaninglessness that it would take several lifetimes to even filter through it, let alone get to understand or use or be in control of any part of it. And if you go along with it and get therefore well and truly caught, what you’ll end up doing under the guise of ‘using it’ is much more ‘being used by it.’ There are better options for sure but they tend to require work.[]
  2. The main approach uses two numbers, one considered ‘major’ and thus changing only when there are ‘significant’ differences and the other ‘minor’ and thus changing in principle for any code change. Note that there isn’t any clear definition for what ‘major’ or ‘minor’ mean in the first place and I doubt there can even be some reliable definition that holds for everyone involved since quite often the versioning is not even a matter of coding really but one of marketing and/or responding to market pressures of all sorts.

    Even leaving this aside for the moment and to make matters more confusing, it’s quite clear that not all changes get to increase even the minor number since there are plenty of code changes that are lumped together at a later stage into what counts then as a new minor version.

    Worse even, there is no reliable way to actually *check* a version, whatever that might be. The traditional way in which versions are ‘checked’ is simply by interrogating the code itself at runtime and such self-reporting is nothing more than reading and reporting some embedded numbers, without checking anything and without any real link to the whole as such – whether the code changed or not overall or in any of its parts, it can certainly keep reporting the same number for ever and ever.

    []

  3. Note that this may or may not be the same as the writer of the code. More importantly here is the *reader* of the code and this means specifically the one who is willing to publicly and personally assume responsibility for a software edition by putting their signature on it.[]
  4. A VaMP patch fully describes and guarantees a *resulting* code state starting from an equally well defined *starting* code state. Hence, to obtain the code version you want, you can use one patch or another depending on what code state you are starting from, there’s no problem with that and there are clear benefits to it, too. For instance, there’s no reason to have to apply 101 patches every time just because the version you want happens to be, indeed, the 101st – you just make a ‘shortcut’ patch that gets you straight to version 101st and use that without losing for it any of the history or any of the guarantees, it’s as simple as that.[]

April 27, 2023

More Direct than Direct_IO or Choosing Ada over GNAT

Filed under: Coding,Eulora — Diana Coman @ 1:31 pm

Back when I started programming in Ada, I trusted the GNAT implementation of the Ada standard, mostly because I had no choice 1. A few years and a lot of experience with said GNAT implementation later, I know for a fact that the I/O packages of GNAT such as Direct_IO and Sequential_IO are broken and merely obfuscating rather than helping in any significant way.

By the time I discovered in 2021 just how broken and uselessly complex these packages truly were, there were already several places where the game‘s client relied on them. Unpleasant discovery for sure but even so, given that there was plenty more pressing work to do and I had managed at least to restrict the use of such packages enough so that their bugs didn’t get a chance to manifest in my code at all, I left the existing code as it was and simply avoided using these packages in code written *from that point on*. After all, the client is anyway open source and thus easily changed by anyone who cares enough about it – if anything, this sort of known and well understood issue makes exactly for a low hanging fruit to pick, something that can even help newcomers to get more easily and more satisfyingly involved.

Recently though, as other parts get finally integrated and the client is getting ever closer to release, I reviewed this matter again, especially as VaMP came into the picture as well. As a result, it turns out that there still is a place where I can’t quite leave hanging this exact sort of fruit, namely when it comes to reading and writing cryptographic keys to the disk. First, this is quite clearly a sensitive operation and as such one where the fewer dependencies and the greater the clarity the better at all times. Second, this is integrated into the client indeed but it’s part of a base layer that is not really client-specific and as such I would really keep it as clear from any unwanted GNAT dependencies as I can 2. So I took the time to review again all the i/o code and then to sort it out in the most straightforward way possible.

The solution turns out to be both short and sweet – all the sweeter for being in fact so obviously well supported by Ada as a language and by all the rest of the code that I have implemented so far. All it took was one short new package that takes advantage of the very thin wrappers I wrote for the read/write C library functions (over which GNAT wraps layers upon layers of obfuscation more than usefulness) and uses otherwise direct memory mapping to convert between any given type to its raw representation and back.

Such direct memory mapping for composed types relies in turn on a very tight specification of how such type should be represented in memory but this was absolutely no trouble at all for me currently since… I had already taken the time when I defined the needed types to fully specify their representation as well! So there it was, my own work done well in the past quite directly and obviously paying its dividends in the present and compounding the dividends for the future, too.

As for the relevant code, here’s the new mmap_io package, helpfully formatted already by my own VaMP 3 for publishing on the blog:

eucore/src/base_layer/src/mmap_io.adb

6_1 
	-- DC, 2023
6_2 

6_3 
with Ada.Directories; use Ada.Directories;
6_4 
with Interfaces.C; use Interfaces.C;
6_5 
with System;
6_6 

6_7 
with Raw_Types; use Raw_Types;
6_8 
with Raw_IO; use Raw_IO;
6_9 

6_10 
package body MMap_IO is
6_11 
	sz: constant size_t := T'Size / System.Storage_Unit;
6_12 
	procedure Write(tval: in T; fname: in String; append: in Boolean) is
6_13 
		local: aliased T := tval;
6_14 
		--for local'Size use T'Size; -- this would be static as required only for scalar types
6_15 
		data: aliased Octets_Buffer_Pkg.Elem_Array(0..sz-1);
6_16 
		for data'Address use local'Address;
6_17 
	begin
6_18 
		Write_Octets(fname, data, append);
6_19 
	end Write;
6_20 

6_21 

6_22 
	function Read(fname: in String) return T is
6_23 
		local: aliased T;
6_24 
		data: aliased Octets_Buffer_Pkg.Elem_Array(0..sz-1);
6_25 
		for data'Address use local'Address;
6_26 
		ptr: Octets_Buffer_Pkg.Elem_Array_Pointer;
6_27 
		fsz: size_t;
6_28 
	begin
6_29 
		if not Exists(fname) then
6_30 
			raise Failed_IO with "inexistent/inaccessible file " & fname;
6_31 
		end if;
6_32 
		fsz:= size_t(Size(fname));
6_33 
		if fsz < sz then
6_34 
			raise Failed_IO with "file " & fname & " too short (" & fsz'Image & " vs expected " & sz'Image & ")";
6_35 
		end if;
6_36 
		ptr:= new Octets_Buffer_Pkg.Elem_Array(0..sz-1);
6_37 
		Read_Octets(fname, ptr);
6_38 
		data := ptr.all;
6_39 
		Octets_Buffer_Pkg.Free(ptr);
6_40 
		return local;
6_41 
	end Read;
6_42 

6_43 
end MMap_IO;

eucore/src/base_layer/src/mmap_io.ads

7_1 
	-- DC, 2023
7_2 
	-- memory-mapped I/O for types that are explicitly and fully specified with representation clause given that they are read/written as raw octets directly memory-mapped.
7_3 

7_4 
generic
7_5 
	-- any type but the user of this package is responsible to ensure that a direct memory mapping works correctly and reliably for T both ways and at all times
7_6 
	type T is private;
7_7 
package MMap_IO is
7_8 
	-- write the value tval of type T to file fname either appending or overwriting (append=false)
7_9 
	-- this creates the file if/when needed
7_10 
	-- raises exception on error
7_11 
	procedure Write(tval: in T; fname: in String; append: in Boolean);
7_12 
	-- reads one value of type T from given file fname
7_13 
	-- raises exception on error (eg inaccessible file, wrong size, failed mapping etc)
7_14 
	function Read(fname: in String) return T;
7_15 

7_16 
	-- reads the idx-th value of type T from file fname
7_17 
	-- function Read(fname: in String; idx: in Natural) return T;
7_18 
end MMap_IO;

With the above done, the actual writing and reading of rsa keys was actually *simpler* than it was when relying on direct_io and the likes. As a result, the udpated code is shorter by about 30% – the relevant keys_io.adb implementation went from 471 lines when using Direct_IO to 152 lines when using my own MMap_IO and this doesn’t even take into account the dropped dependencies and how much additional code they brought in.

For anyone interested in using the client whether now or at any future date, the good news from the above is that the previously low hanging fruit of switching client i/o to a more straightforward non-gnat implementation is now even lower hanging, seeing how there is the MMap_IO package to rely on and/or to use as example for the case where something slightly different might serve better. To further help in this vein, note that the client still makes use of Sequential_IO mostly for the ‘torrents’ part, meaning the read/write of files obtained at run time from the server – essentially game assets of all sorts.

Possibly a slightly different package would serve better to replace that use for game assets since the MMap_IO package isn’t aimed specifically at sequential i/o – one might perhaps make a generic package receiving both the file and the type desired, reading the whole in memory and operating from there. It would certainly be a faster and more reliable solution that GNAT’s imagined ‘control’ over multiple simultaneous accesses to the same file on disk. I’ll leave this for another day though and possibly, even preferably for another person, too, so feel free to pick it up if it’s of any interest to you.

If you set to work and have something to show or to ask, I’ll be happy to hear of it as well, so use the comments below confidently, there’s nothing to lose for it for sure.

  1. Perhaps it’s truly very naive to trust this way but at times it is also unavoidable – what you don’t know yet, you have to take on trust, there is no third way available. At best, you get perhaps the choice to trust a person based on what you know *of them* but at worst, as in this case, all you ‘get’ is to trust an unknown entity, pretty much, the ‘code itself’ aka all 360M of it or an ‘organization’ aka Adacore with all its changing history and multitude of people that you can’t ever know or get to know in any meaningful way anyway. So you trust, if and when you must but hopefully you then work as well towards reducing your own need for such blind trust. As you learn more, it’s worth remembering to revisit, reevaluate and correct or adjust misplaced trust, where necessary – this is exactly what this article describes and documents, my reevaluation and correction of previously assigned trust, as I got to know better what it was exactly that I ended up relying on.[]
  2. Especially since on review, I realised that even Direct_IO and Sequential_IO packages from GNAT *still* rely on the ugly and gnarly “streams” even though they avoid the broken ‘finalization’ and although there is both no need for such reliance nor any use for it. The very code in question states clearly in places that the streams abstraction is meaningless for the task at hand but nevertheless it’s brought in and adhered to because of the need to fit a predefined form, a need of comformance and uniformity across the board basically, that’s it. For instance, directly from s-direio.adb:

    — The following is the required overriding for Stream.Read, which is
    — not used, since we do not do Stream operations on Direct_IO files.

    In other words, it’s most likely a deeper issue at core – the GNAT implementation values uniformity and ultimately fungibility above everything else as it sets purposefully to shield the user from the requirement of deeper understanding and actual grasp. It’s a perspective entirely at odds with my own and so it’s no surprise its fruits are unpalatable to me.

    []

  3. Compounding dividends yet again, see?[]

April 22, 2023

What about us? Ausweis

Filed under: Dark Modern Ages,Word Therapy — Diana Coman @ 3:25 pm

‘Who’s that?’ asked the child as we walked again, the other week, through the streets of my old hometown.

‘A poet, Nichita Stanescu. He was born and grew up quite clearly and indisputably in this town instead of in some embarrassingly named “Hooligans” village on the county border like that unruly Caragiale 1. He won an international prize for his poetry and he didn’t write anything biting about the town itself, so his bust made it to the central park. His admirers described him as very sensitive and undoubtedly he was quite sensitive indeed. Others described him mostly as perpetually drinking and he died of cirrhosis of the liver. He was thirsty, he said and he drank vodka primarily but since he was a poet, it was considered he meant mostly a thirst for eternity.’

ph_11_640.jpg

As you can probably tell from the above description, I was never particularly moved by Nichita Stanescu’s poetry despite the local and even contemporary connection 2, international prizes and all that. Nevertheless, it occurred to me that I had never quite taken the time to figure out just why exactly I’m so immune to it. Looking now again through his complete set of poems, it’s quite obvious though – it’s not that I don’t get what others see in his writing, quite on the contrary, if anything I’d say he was definitely very talented indeed. But what starts quite vigorously and full of life in his 1955 volume turns gradually and quite painfully to watch into the willingly ineffectual and dissipated. The appreciation he got precisely for keeping it up in such vein probably didn’t help at all, either.

Two of his poems though, from the 1970s 3 read to me as if he might have seen around himself at least at times still more clearly than he liked to. So I’d rather regrind these two in preference to all the ‘well known’ ones:

Fine but where does that leave us 4? They were great, tragic, saints… They ate the bread of their days and to our parents, the parents they were 5.

But us, what’s it going to be with us?… They endured the cold, suffered the passion, walked through the snow, trudged through the mud, died and made themselves undying.

We are living but what about us? Has something been decided about us 6? Has it been decided? When and what has been decided? We exist but it’s boring 7 to us!

I take my duly certified blood out for inspection 8. I’m let go. I take the sculpture in my bone out for inspection. It delays me a second but I’m let go.

I take my tolerant spoken tongue out for inspection. The dictionaries are at the ready, so I’m let go.

‘Why do you want to pass?’ death asks. ‘I’m free,’ I reply, ‘so I don’t feel like answering you.’ She staggers for a while and then, she lets me go.

I’m wearing all stamps of approval. If you want to know, I, for one, am in order, I’m let go.

Mind that the above is from 1970. It’s 2023 now and the bots are quite literal, not all that concerned with figurative meaning and poetry. Has it been decided yet and are you wearing all stamps of approval?

  1. Yes, Caragiale was born in a village called literally Haimanale (Hooligans) and on the border of the county so that he’s either born in Prahova or in Dambovita county, depending on who and when you ask. During his lifetime, nobody really cared anyway, of course, and by the end of his life he found both counties and the whole country even quite unappreciative of his work but nevertheless, once safely dead, they each claim him as ‘theirs’ and they even gave the village his own name since well, he didn’t have any further use for it, did he? It’s an honour, I know, only there might be some different perspective as to who is the honoured party exactly in this.[]
  2. He lived from 1933 to 1983 and I actually attended the same highschool as he had attended, so there was plenty about him around me for sure.[]
  3. None of which are really much known, of course. His best known poems are ‘Leoaica tanara iubirea’ which made it into the school textbooks and ‘Ploaie in luna lui Marte’ which made it into pop through Nicu Alifantis who set it to music and sang it first.[]
  4. Din nou, noi, 1970. The original is ‘white verse’ in principle but I’m setting it up in plain text already, don’t tell me the meaning is somehow lost through losing the ‘poetic’ indentation now.

    Bun, dar cu noi cum ramane? Ei au fost mari, tragici, sfinti… Ei au mancat paine, parintilor nostri le-au fost parinti.

    Dar noi, dar cu noi?… Lor le-a fost frig, au patimit, au mers prin zapada, prin noroi, au murit si s-au nemurit.

    Noi traim, cu noi cum ramane? S-a hotarat ceva? S-a hotarat? Cand anume si ce anume? Suntem, dar ne este urat!

    []

  5. Wholesome nutrition and nurturing is what he means, perhaps basic and unpretentious but fundamental and reliably sustaining.[]
  6. By central committeedemocratically elected representatives I expect. Do you hear that? Has it already ‘been decided’ what will be about you?[]
  7. The original is a reflexive construction without direct equivalent in English. The most direct translation of it would be something quite unyielding such as ‘one’s own living is ugly to oneself’. Yes, the Romanian language puts it plainly that at least one way of being bored is essentially reflexive ugliness.[]
  8. Ausweis, 1970

    Scot sangele stampilat la vedere. Mi se da drumul. Scot osul sculptat la vedere. Intarzii o secunda, dar mi se da drumul.

    Scot induratoarea limba vorbita, la vedere. Dictionarele sunt pregatite, asa ca mi se da drumul.

    De ce vrei sa treci, m-a intrebat moartea. Sunt liber, i-am raspuns, asa ca nu am chef sa-ti raspund. Ea a stat un timp descumpanita, apoi, mi-a dat drumul.

    Am pe mine toate stampilele. Daca vreti sa stiti eu, unul, sunt in ordine, mie mi se da drumul.

    []

March 21, 2023

Will I Need to Run Linux for Eulora2?

Filed under: Coding,Eulora — Diana Coman @ 11:09 am

Since the question in the title comes up with some regularity, I’ll write out the answer here for everyone to see and for myself to have it at hand when next needed:

It’s most likely for your own sake that you’ll need to run some sort of Linux, especially if you never ran it before, but otherwise sure, Eulora2 can serve as a good motivator for it, too.

To elaborate on the above, note that *all* you need to run Eulora2 is an environment where you can compile C, C++ and Ada code from scratch 1. Arguably, any and all operating systems are capable of such a basic feat as this, since it is, quite literally, what “operating” 2 a computer system is supposed to be about – making it process (“compile”) written instructions (“code”) into a form (“binary”) that the machine can then follow (“run”) to do exactly what you told it to do. And if you don’t like what it does or you change your mind or you simply want to play around and tell it to do something else, all you need to do is to tweak the code and have the machine process it all happily again, as many times as you please. Hence the importance of *all* the steps in that process, not just the last one, not just “run this”, but absolutely all of them, from first to last.

Does your current operating system allow you to do all and any of the steps above, routinely and easily? Then you don’t need anything else and you are set to go, nobody will mind you running Eulora2 there or anywhere else and you’ll find running it just as easy as running anything else. Moreover, I’d be very glad to hear from you how it goes, what you are running it on and what changes you are making to it, too – after all, it’s meant to be *your* client to play Eulora2, not in any way someone else’s.

If your current operating system doesn’t really make it easy to even know all that much, let alone perform and control one or several of these basic steps, then you’ll probably need to try out something more useful. What exactly might that be is entirely your choice but it is indeed more likely to be some version of a unix-based system. And if you truly want to have an easier time compiling and running everything as well as perhaps changing it to better fit your needs at some point, I suggest you pick an older version and never ‘upgrade’ it with all the bells and whistles that might or might not do anything useful for you but will likely break the toolchain and leave you stranded while also eroding to various degrees those hardly ever mentioned attributes of access, control and consistent return on your own learning efforts 3.

There is no reason at all and no intention even for there to ever be just *one* client for Eulora2 or otherwise put “the” client. Currently there is indeed only one, for the very simple reason that I made it and nobody else made theirs. As a result, my client is and will remain the reference client but it’s still not meant to remain the only one. Quite the opposite, I’m open to any number of developers and/or maintainers of clients coming forward to make and promote their own versions, getting paid for it, too. The way I intend to set it all up, developers and maintainers of clients will get paid for their work based on how many users choose to run each developer or maintainer’s client and for how long, as all this information is directly visible from the serverside. While this is still some way into the future currently, count this as the heads up on it – you won’t be able to say later you didn’t know it or didn’t have time to get ahead of others with it.

As for the reference client that I made and maintain, I would recommend currently that you run it on one of Debian 8 (Jessie), Ubuntu 10, CentOS 6 or Gentoo 4. This is not because the client “requires” these or it can’t otherwise run in a different environment but simply because it is already known to run smoothly directly out of the box with as little effort as downloading and starting *one* single script that does it all. Of the four versions mentioned, I don’t have any particular favorites, as they all have their own specific pluses and minuses, but I’d say they are all fairly easy to try out, too. Depending on your machine though, you might want to pick one that plays more nicely along something else and possibly out of the list above, it’s Ubuntu that is more likely to do so.

As mentioned previously, currently the entry point for Eulora2 remains through interaction with those involved, on this blog or on others. And there is help available as well, just read around, follow the links and you’ll find both the people involved and ways to interact – it’s the meta-game, if you wish, happening in plain sight, even if it seems invisible to some. If it’s not invisible to you though, just make and pick your quest(s), explore it all leisurely and when you’re ready, start commenting and interacting with people, too, it helps. In short, ask and you’ll get an answer. Better yet though, ask a good question and you might just get more of an answer than you even hoped for!

  1. More precisely, this means specifically that gcc 4.9 runs fine and the whole toolchain is not broken, either.[]
  2. For all the quotes, operating computers is not even all that far removed from other types of operating that may be more familiar, since they all come, of course, from the more direct physical operation aka use of tools of all sorts – after all, computers are merely more complex tools, basically tractors for plowing the information bitfields, nothing else. For this same reason, operating computers has in common with operating any other tool further requirements that don’t get mentioned explicitly nowadays all that often, most notably the ones related to requiring some amount of study that actually pays off and offering full access and control over all its parts.[]
  3. Convenience that caters to your lack of knowledge *always* costs more than is directly made visible and its hidden costs are quite often the ones that you’ll regret paying in the long term. Yes, it gives you a boost in the short term – quite often “now”- and it robs you of ~everything in the long term. At the very least it gives dependency, too. Just like any other drug of choice, you know?[]
  4. For Gentoo, there is no versioning possible even, since it’s always and by design a sort of mix-and-match, so you’ll need to pick your versions of everything in there. There is however a neatly written summary of a successful install of Eulora on Gentoo, so you might find some help with it, if you ask there.[]

February 17, 2023

How Are Things Moving in Eulora2?

Filed under: Coding,Eulora — Diana Coman @ 2:41 pm

Promptly and on demand, that’s how things are moving in Eulora2. To wit, one day in Eulora2, the discussion turned suddenly and quite literally to the skies above and whether the speakers knew it or not, the demand was thus made and fully heard:

Diana Coman: what, does that sky look flat to you?!
Vivian Sporepress: haha
Vivian Sporepress: Diana Coman: certainly not flat, possibly not even any sort of crystalline sphere; it seems to have some axial tendencies, perhaps an ellipsoid; and I have no hypotheses yet for the nature or causes of its cloud patterns though they appear unchanging to the unaided eye
Vivian Sporepress Diana Coman: ah, the ‘axial tendency’ looks more like a bilateral symmetry across a vertical plane, suggesting either a peculiar optical phenomenon or a decidedly nonrandom process behind the cloud formation
Diana Coman Vivian Sporepress – well, the clouds have to fit the sky’s …geometry and that one is indeed quite regular
Vivian Sporepress Diana Coman: the geometry of the sky might not be possible to infer with the present euloran technology level, for instance a sufficiently large cube shaded just right can be indistinguishable from the inside from a sphere!

Finding itself under such interesting scrutiny, the sky clearly took notice. Only a couple of weeks later, among many other improvements and developments, there was also this confirmed change:
skies_1_640.png

To be fair, there are quite a few other movements of things and of people happening at the moment in Eulora2, even if very little of it made it on to the blog. As always though, movement is the hardest to capture in pictures so the best way is to be there to see it happening as it happens, perhaps finding ways to be an active part of it as well. Second to being there, read along and comment underneath, perhaps, as I’ll aim to let it spill on to the blog in bits and parts at least from time to time, why not. There’s certainly plenty interesting and ready to move in there, from the multiple moons orbiting around Eulora2 and their impact on the grounds below, to the more prosaic issue of reconciling local movement with server’s view of the same.

The best part about it all is that the solutions, when found, turn out to be so easy to implement currently, given the supporting environment and a very much cleaned client code that it really doesn’t take long for something new to become visible in game once articulated clearly and meaningfully enough. This might change in the future perhaps but for now it is exactly so and turning gradually into a lot of fun, too.

How many other games do you know of, where truly all it takes to make a visible change is to speak up convincingly enough, without having to argue for it, without even having to frame it as a request? It’s enough to make sense and to pick at an interesting problem, that’s all.

January 13, 2023

Regrinding Kerckhoffs’ Desiderata for Online Cryptography

Filed under: Coding,Sense and nonsense — Diana Coman @ 2:40 pm

Regrinding is, at core, an attempt to give new expression to an older result so that it’s not merely referenced 1 but actually integrated into the modern context and thus given a new life as an active part of new developments. Such new expression preserves the substance while enabling the older result to take full advantage of the current context, connecting it meaningfully to new things, discarding its limitations that were specific only to the older context and retaining otherwise in spirit if perhaps not fully in letter the still valid underlying principles. In fewer words, regrinding is a rejuvenation, so much more than just a reference 2.

I’ve done such regrinding previously to software from the 1970s and it enabled the development of very useful tools that pushed quite quickly for further developments and new connections that were simply not even visible before the successful regrind. This time though, the scope is even wider as it all started with a legitimate question regarding the cryptographic choices of my infrastructure and it turns out that a fully grounded response requires first of all going back all the way to 1883 and the original statement of Kerckhoffs’ desiderata because its exactly their regrinding -although implicit until now rather than explicit- that exposes a clear root from which one can then reason and evaluate existing cryptographic options as well as any specific choices made in a given context.

Let’s start from the source 3, meaning the desiderata as written by Auguste Kerckhoffs 4 in his article “La Cryptographie Militaire” 5 published in two parts, in January and February 1883, respectively, in the Journal des Sciences Militaires:

  1. Le système doit être matériellement, sinon mathématiquement, indéchiffrable. 6
  2. Il faut qu’il n’exige pas le secret, et qu’il puisse sans inconvénient tomber entre les mains de l’ennemi. 7
  3. La clef doit pouvoir en être communiquée et retenue sans le secours de notes écrites, et être changée ou modifiée au gré des correspondants. 8
  4. Il faut qu’il soit applicable à la correspondance télégraphique. 9
  5. Il faut qu’il soit portatif, et que son maniement ou son fonctionnement n’exige pas le concours de plusieurs personnes. 10
  6. Enfin, il est nécessaire, vu les circonstances qui en commandent l’application, que le système soit d’un usage facile, ne demandant ni tension d’esprit, ni la connaissance d’une longue série de règles à observer. 11

Except for the 4th with its direct reference to telegraphic communications, the desiderata above are essentially expressions of “soft” requirements that are derived quite directly from human nature and from the core purpose of cryptography – neither of which fundamentally changed or are likely to ever change significantly. Consequently, the principles captured in these desiderata are as valid now as they were back in 1883 and it is only their expression and concrete practical implications that have to change in order to be fully and directly relevant in the modern context.

Taking the 4th desideratum above as the most obviously outdated in its original form, its core is that the cryptographic system needs to be applicable to the prevalent medium of communication. Hence, the change of expression required here to bring this fully to the modern day is simply that the cryptographic system has to be applicable to online communications instead of telegraphic ones. Obviously, there are deeper implications for a cryptographic system due to this change of medium from telegraphic to the online but the underlying principle so neatly expressed by Kerckhoffs remains the same: the system needs to be applicable to the relevant medium of communication (and this means, in term, fully taking into account the constraints and opportunities specific to the medium). Before attempting to explore in more detail the implications of this new expression though, there is further understanding to be gained from the original by reading and adnotating Kerckhoffs’ own brief discussion of the above desiderata:

Tout le monde est d’accord pour admettre la raison d’être des trois derniers desiderata ; on ne l’est plus, lorsqu’il s’agit des trois premiers. 12

C’est ainsi que des personnes autorisées soutiennent que l’indéchiffrabilité absolue du chiffre ne saurait être considérée comme une condition sine quâ non de son admission dans le service de l’armée; que les instructions chiffrées transmises en temps de guerre n’ont qu’une importance momentanée, et n’exigent guère le secret au delà des trois ou quatre heures qui suivent le moment où elles ont été données; qu’il importe donc peu que le sens d’une dépêche secrète soit connu de l’ennemi quelques heures après son interception; qu’il suffit, en un mot, que le système soit combiné de telle façon que la traduction d’un cryptogramme exige au moins trois à quatre heures de travail. On ajoute que la possibilité de pouvoir changer de clef à volonté ôte d’ailleurs au défaut de non-indéchiffrabilité toute son importance 13.

Cette argumentation peut, au premier abord, paraître assez juste ; au fond, je la crois fausse 14.

C’est en effet, selon moi, oublier que le secret des communications envoyées à distance conserve très souvent son importance au delà de la journée où elles ont été transmises ; sans énumérer toutes les éventualités qui peuvent se présenter, il me suffira de citer le cas où le commandant d’une ville assiégée envoie des renseignements à l’armée qui doit la secourir. De plus, une fois qu’un cryptogramme intercepté a pu être déchiffré, toute nouvelle dépêche, écrite avec la même clef et qui subit le même sort, peut être lue instantanément. Il arrivera par suite que, pendant un temps plus ou moins long, des dépêches seront expédiées dans toutes les directions, dont le déchiffrement se trouvera en quelque sorte fait d’avance : à moins d’admettre que dans un corps d’armée toutes les instructions chiffrées émanent d’un seul, ou du moins passent par les mains d’un seul, ce qui serait réduire la correspondance secrète à un rôle singulièrement modeste 15.

La faculté de pouvoir changer de clef à volonté est certainement une condition essentielle de tout système de cryptographie, mais c’est un avantage trompeur et sur la réalisation pratique duquel on aurait tort de compter, à travers les mille péripéties d’une longue campagne 16.

Quant à la nécessité du secret, qui, à mes yeux, constitue le principal défaut de tous nos systèmes de cryptographie, je ferai observer qu’elle restreint en quelque sorte l’emploi de la correspondance chiffrée aux seuls commandants en chef. Et ici j’entends par secret, non la clef proprement dite, mais ce qui constitue la partie matérielle du système : tableaux, dictionnaires ou appareils mécaniques quelconques qui doivent en permettre l’application. En effet, il n’est pas nécessaire de se créer des fantômes imaginaires et de mettre en suspicion l’incorruptibilité des employés ou agents subalternes, pour comprendre que, si un système exigeant le secret se trouvait entre les mains d’un trop grand nombre d’individus, il pourrait être compromis à chaque engagement auquel l’un ou l’autre d’entre eux prendrait part. Rien qu’à ce point de vue il y aurait lieu de condamner l’emploi du dictionnaire chiffré, qui est en usage aujourd’hui dans l’armée 17.

On m’objectera peut-être qu’en admettant le deuxième desideratum, il n’est guère possible d’établir un système complètement indéchiffrable. Il faut s’entendre : je sais très bien que vouloir dans ces conditions trouver un système mathématiquement indéchiffrable est chose mathématiquement impossible ; mais j’affirme, et non sans de bonnes raisons, que, tout en réalisant les différents desiderata que j’ai énumérés plus haut, on peut parfaitement combiner des systèmes, sinon mathématiquement, du moins matériellement indéchiffrables 18.

Il paraît qu’il est sérieusement question, au ministère de la guerre, de remplacer le dictionnaire chiffré par quelque autre système plus pratique. Eh bien! si l’Administration veut mettre à profit tous les services que peut rendre un système de correspondance cryptographique bien combiné, elle doit absolument renoncer aux méthodes secrètes, et établir en principe qu’elle n’acceptera qu’un procédé qui puisse être enseigné au grand jour dans nos écoles militaires, que nos élèves seront libres de communiquer à qui leur plaira, et que nos voisins pourront même copier et adopter, si cela leur convient le dirai plus : ce ne sera que lorsque nos officiers auront étudié les principes de la cryptographie et appris l’art de déchiffrer, qu’ils seront en état d’éviter les nombreuses bévues qui compromettent la clef des meilleurs chiffres, et auxquelles sont nécessairement exposés tous les profanes ; alors seulement cet article du règle ment du 19 novembre 1874, que j’ai mentionné plus haut, pourra recevoir une application pratique et réellement satisfaisante 19.

Doubtless both the agreement regarding the need for the last three desiderata as well as the lack of agreement regarding the need for the rest of them were indeed true in Kerckhoffs’ time exactly as stated. But the more interesting part is the fault line on which such agreement breaks: what made at the time the last three desiderata so obvious to anyone and the first three so very much *not* obvious? Most likely, it was quite literally a matter of direct exposure and immediate feedback versus indirect exposure and longer term or even entirely lacking feedback – while any lack of adherence to the last three would cause direct, clear and immediate inconvenience to anyone attempting to use cryptography at the time, a fault or lack related to the first three would be more subtle and less easily or directly noticed, especially on the spot. Specifically, there isn’t any direct or immediate visibility of failures that are caused by an encryption method being in practice more easily decrypted than it was generally thought, the secrecy of the system being in practice less of a secret than considered or the inability to communicate, recall or change the key at will being an impediment to maintaining secrecy of communications over the long term. In other words, the agreement is lacking where the feedback loop is both longer and more complex, with practical results going at times even directly against the more natural intuition or even simply against the prevalent belief or custom.

The new context of computers and online communications brings in some changes to the above in that it renders some parts more obvious than they were (most notably the weakness of many ciphers that *seem* indecipherable at first sight) but it is unlikely to change this sort of underpinning of how different requirements are perceived and evaluated as obviously necessary or not. So it’s arguably wiser to focus less on how the consensus/agreement might have changed meanwhile and more on addressing the underlying fact that increased complexity and longer feedback loops are more likely to obscure and even shield potentially fundamental faults than to somehow render obsolete any of the core requirements. Restating thus Kerckhoffs’ argument in more general terms that are just as valid now as they were in his time, there tends to be consensus on desiderata that are clearly and directly linked to obvious and immediate failures while there is less consensus on desiderata linked to failures that are more subtle and may have effects that don’t become obvious directly or in real time as encryption is used.

To see the above in action, it’s useful to consider how the consensus has concretely changed, as the present simply shifted the fault line on which that same agreement breaks. Nowadays there is full agreement regarding the importance of the 2nd desideratum that has been perhaps quite well re-ground already and even in various forms at that, e.g. “no secrecy through obscurity” or Shannon’s maxim that “the enemy knows the system”. Not surprising perhaps, given that the powerful computation capabilities of modern computers simply made this particular part of it much more directly obvious than it was in Kerckhoffs’ time.

Interestingly though, something else seems to have happened to the last two desiderata: even as computers certainly made the operation and use easier and even effortless for much more complex ciphers than Kerckhoffs ever worked with, they have also replaced the physical and directly observable usability issues with less obvious ones that are likely therefore to receive less direct attention unless specifically investigated as such. As cryptography moved from slow mechanical contraptions and manual calculations to swift computer-assisted systems, opaque software and even pocket-sized hardware devices that “do it all” for the user, the more common view seems to be that the last three desiderata of Kerckhoffs are either not relevant anymore or simply fulfilled by default and thus no longer needing any further consideration. To paraphrase Kerckhoffs himself: on the face of it, this may seem a fair assessment; on a fundamental level, I think this is false.

Even though the encryption/decryption operation itself is arguably easier to perform nowadays as a device will do all the required calculations quickly and transparently, this doesn’t make cryptography as an activity any easier – if anything, it makes it harder as the complexity is higher, there is less intuitive and direct feedback for any action and the potential blunders and resulting vulnerabilities have only morphed to different shapes that are harder to spot and potentially better hidden as well 20.

The desired ease of use of a cryptographic system goes deeper than the purely mechanical or operational aspects and it includes as fundamental aspect the ease with which the system and the required actions can be understood well enough to avoid pitfalls. Thinking of cryptography as an activity, its “ease of use” refers to being able to obtain reliably, consistently and even verifiably the exact desired effect without any undesired side effects. The lack of physical or mental strain are in this context desired requirements only as means towards a purpose, as they support the user and they arguably reduce the chances of user error but they aren’t themselves the goal nor can they be pursued as such.

Kerckhoffs himself quite plainly argues in the discussion above precisely for the routine and thorough study of a cryptographic system by those who are expected to use it. Moreover, he makes the argument that it’s *only* through such study – thus markedly *not* merely through the system’s ease of operation – that the user of a cryptographic system can avoid blunders that are both unavoidable otherwise and effectively compromising security regardless of the strength of the cipher by itself. If anything, I’d say that this is all the more relevant today given the much more widespread use of encryption coupled with the increased complexity of approaches and the double-edged sword of software making operations easier in a mechanical sense but much more difficult and less intuitive to understand or even simply to check/evaluate on the spot as to full implications of any given action.

Quite interestingly, the requirements of portability and single-person handling introduced by the 5th desideratum retain their relevancy in the online space even though it might seem an unlikely fit at first sight. To see the link though, it’s enough to switch from the physical portability and handling that Kerckhoffs undoubtedly had in mind to the more direct meaning of whether one single person has at any given time all that they need to successfully encrypt, decrypt and check a message. Considered in this light, any cryptographic system that stores the keys remotely is already unlikely to meet the portability requirement and arguably fails even the single-person handling requirement since the remote end is effectively in itself requiring the involvement of another (hence a second “person”, whether that might be an organization rather than a physical person as such). Even more directly, any schemes that fragment and distribute any part of a cryptographic system (whether it’s some checks, some signatures or outright keys) are effectively going against that single-person handling requirement. If one considers the even more fundamental meaning of “single-person handling” as the ability of one person to have full control over the actions performed, it follows that it’s not even enough to have everything locally and unfragmented: the crucial point is whether the user truly has both the access and the understanding required to be in control.

Considering Kerckhoffs’ own discussion of the 6 desiderata in their context of use and aiming to maintain thus their fundamental meaning, a first attempt at a regrind can be perhaps made with some minimum initial notes, as follows:

  1. The system must be practically, if not mathematically, indecipherable. 21
  2. It must not require secrecy and its workings should be clearly and fully exposed for anyone to access. 22
  3. It has to provide the means to observe, communicate, retain, change or modify the key as and when users see fit 23.
  4. It must be applicable to the prevalent medium of communication.
  5. It must allow at all times full access, control and interrogation of any and all its parts by the legitimate user without requiring for such actions the involvement of any other parties.
  6. Finally, it is necessary, given the circumstances of its application, that the system’s complexity is minimal and all its functioning is made as explicit and clear as possible so that its use with full understanding can be achieved with some reasonable amount of study but without requiring continuous mental strain or the knowledge of a long series of rules to observe.

The above is meant as a first attempt to regrind the full set of Kerckhoffs’ desiderata while recovering as well their original discussion that is quite informative and adds useful context. Perhaps better expressions can be found with time and with the experience obtained through the explicit use of this first regrind. The “re” in regrind is not limited at one, after all, nor does it ever have to be.

For my own use, I find that these fundamentals make together a useful and entirely usable lens through which one can see more clearly and evaluate the various developments in cryptography as well as any new methods or systems that have been or might be proposed. While this article took more effort to write and grew in size well beyond what I initially intended, I think it has all been time and effort well spent as it finally makes explicit the fundamentals that inform all further decisions regarding my own choices related to cryptography.

The next steps for anyone interested would be to have a look at the main current approaches and directions and the degree to which they fulfill or not these six desiderata. Such exercise gives in my experience quite a refreshing and empowering perspective that is both well grounded and able to handle quite effectively and efficiently the otherwise seemingly overwhelming volume of material to go through. One of these days I might even make the time to write it fully down and publish it as well but don’t wait for me on this – go ahead and do it yourself for your own needs, then leave me a message in the comment box below so we can compare notes, results and perspectives, learning perhaps something further through the interaction itself. This is anyway how it works best, each and every time.

  1. Certainly, Kerckhoffs is widely and even reverently cited in modern cryptography but in most cases it’s only one sentence of his seminal article that is referenced, usually under the name of “Kerckhoffs’ principle”. The rest hardly receives any explicit attention and at times it’s even dismissed as out of date essentially. My take on it though is that the substance of Kerckhoffs’ 6 desiderata is still very much relevant today and moreover, the full set rather than just one desideratum makes in practice for a much more solid base for a cryptographic system than is currently explicitly available otherwise. []
  2. If the term is still not all that clear to you, note perhaps that it’s a term of art and thus its full meaning is embedded in its own wider context, not entirely captured by any straightforward definition. In other words, there is perhaps some closer link than it might seem between art and culture on one side, steganography and cryptography on the other.[]
  3. As is quite often the case with old enough material, “from the source” means in practice “as close to the source as currently available”. Since I don’t currently have the originals and I’m rather reluctant to postpone this until I get a chance to see it for myself at the British Library where it is in principle still available, the copy I’m using for now is the one made available by Fabien A. P. Petitcolas who maintains electronic versions of part 1 and part 2 that are made in turn from a copy of the originals as obtained by him in 1998 from the British Library.[]
  4. His full name was Jean Guillaume Auguste Victor Alexandre Francois Hubert Kerckhoffs but he didn’t seem to have used it in full all that often, so I won’t use it in full any further either.[]
  5. The title in full being actually “La cryptographie militaire, ou des chiffres usités en temps de guerre, avec un nouveau procédé de déchiffrement applicable aux systèmes à double clef” according to the British Library where the original is held. Decrypting the French to English, for my readers lacking the key to read directly the original, the title would therefore be “Military cryptography or cyphers used in times of war, with a new decryption method applicable to double key systems”.[]
  6. The system must be practically, if not mathematically, indecipherable.[]
  7. It must not require secrecy and the enemy knowing it must not cause any inconvenience.[]
  8. The key must be communicable and retainable without requiring written notes and it must be changeable and modifiable at the will of the correspondents.[]
  9. It must be applicable to telegraphic correspondence.[]
  10. It must be portable and its use and functioning must not require more than one person.[]
  11. Finally, it is necessary, given the circumstances of its application, that the system be easy to use, not requiring mental strain nor the knowledge of a long series of rules to observe.[]
  12. Everyone agrees to admit the reason for existence of the last three desiderata; such agreement doesn’t exist though when it comes to the first three.[]
  13. This is how authorised persons hold the view that the absolute indecipherability of a cipher shouldn’t be considered as an absolutely necessary requirement for its use in the army; that the encrypted orders transmitted in times of war have only a temporary importance and hardly require remaining a secret beyond three or four hours after being issued; that it matters therefore little that the meaning of a secrete missive would be known by the enemy several hours after its interception; that it is enough, in a word, that the system is scrambled in such a manner that the translation of an encrypted message requires at least three hours of work. In addition, it’s considered that being able to change the key at will renders the defect of non-indecipherability utterly unimportant.[]
  14. This argument can seem, at first sight, fair enough; on a fundamental level, I think it’s false.[]
  15. It comes down in fact, in my opinion, to forgetting that the secret of distance communications very often remains important beyond the day of transmission; without ennumerating all the cases that may arise, it will be enough to point to the situation where the major of a town under siege sends intelligence to the army that must save it. Moreover, once an intercepted cryptogram was successfully decrypted, all further intercepted messages encrypted with the same key can be read immediately. It follows that, after more or less time, there will be messages sent in all directions for which the decryption will have been already done of sorts, in advance, unless requiring that in an army corps, all encrypted instructions come from a single person or at least are handled by a single person, which would mean reducing secret messages to a peculiarly modest role.[]
  16. The ability to change the key at will is certainly an essential condition for any cryptographic system but it is a misleading advantage and it would be wrong to count on its practical implementation throughout the numerous adventures of a long campaign.[]
  17. As to the necessity of secrecy, which constitutes, to my eye, the main defect of all our cryptographic systems, I’ll observe that it restricts in a way the use of encrypted communications to commanders in chief. And here by secret I don’t mean the key itself but the concrete tools of the system: tables, dictionaries or whatever mechanical gear is required. In fact, one doesn’t need to create immaginary phantoms and to cast doubt on the incorruptibility of employees or of subordinates, to understand nevertheless that, if a system requiring secrecy is found in the possession of too many individuals, it can be compromised at any point where one or another is involved. This point of view alone would give enough grounds to condemn the reliance on a dictionary of codes, as is currently the case in the army.[]
  18. One might object perhaps that, by admitting the second desideratum it would hardly be possible to establish a system entirely indecipherable. To understand one another: I know very well that, wanting under these conditions to find a system that is mathematically indecipherable is a mathematical impossibility; but I state, and not without good reasons, that, even while fulfilling the various desiderata that I ennumerated above, one can perfectly well construct systems that are, if not mathematically, at least practically indecipherable.[]
  19. It would seem that the army ministry is seriously raising the question of replacing the dictionary of codes by some other system that is more practical. Well! If the Administration wants to fully benefit from all the services that can be provided by a cryptographic system of communications that is well made, it should completely discard secret methods and establish as a principle to accept only a method that can be taught in the open in our military schools, one that our students will be free to talk about with whom they please and one that our neighbours could even copy and adopt, if that is suitable and even more: only when our officers study the principles of cryptography and learn the art of decryption will they be able to avoid the numerous blunders to which all laypersons are exposed and that compromise the key of the best ciphers; only then will this regulation article of 19 Novembre 1874 that I mentioned above stand a chance to receive a practical and truly satisfactory application.[]
  20. There is even a whole new scope and strong incentives for purposefully though transparently sabotaged systems but even leaving that aside for the time being, there are many examples of direct blunders and vulnerabilities inadvertently introduced through encryption systems or “improvements” to such systems as proposed and promoted by experts in the field. To pick just one of the most visible examples, take for instance the OCB2 mode of operation which was included in the ISO2009 standard, widely adopted and implemented due to its technical advantages and then found to be entirely and easily broken in theory as well as in practice, with direct, real-world attacks exploiting an overlooked interaction between two of its underlying constructs. For full details, see for instance the paper by Inoue, Iwata, Minematsu and Poettering, “Cryptanalysis of OCB2: Attacks on Authenticity and Confidentiality”, Journal of Cryptology, Vol 33, Issue 4, Oct 2020, pp. 1871-1913.[]
  21. All the devils here are in what that “practically” means in a modern context. The original expression though is general enough so that it still stands exactly as it was and it’s quite a joy to see this, too.[]
  22. I’m trying to be more explicit here even at risk of making this way more verbose than the “Kerckhoffs’ principle” usually is.[]
  23. The core part that is still relevant about “without help from written notes” is more difficult to capture here. Kerckhoffs’ point was essentially the same one made today about passwords, namely that one that is too difficult to be remembered will therefore be written down and thus easily found out by an adversary. This runs however into the unescapable fact of the modern environment that computers are simply too powerful for humans to rely only on their memory. Consequently, any practical security will require some form of external help, thus “written notes” in the widest possible sense. But I think that Kerckhoffs’ point still stands and there should always be *as well* and in addition to all other protection layers (such as NOT keeping such notes in plain text, for instance) at least one part that remains at all times solely in the mind of the legitimate user.[]

December 19, 2022

Chat and Eulora2’s Communication Protocol

Filed under: Coding,Eulora — Diana Coman @ 1:07 pm

This article builds up on the existing, well-iterated specification of the communication protocol, aiming to detail the new developments and to provide a place for current and relevant discussion going forwards. For the core structure of the protocol though, the linked article remains the reference and although the discussion of that part moves out of necessity here as well, I see no need at the moment to copy its content too. If your question concerns the parts that are not directly described here, simply link precisely the part you are talking about, as needed.

The first further addition to the communication protocol enables chat in Eulora2 and is currently implemented and fully working. Worth making it explicit and right from the start that the chat in Eulora2 is by default encrypted 1 whenever in transit and effectively authenticated as well, as it fully benefits from the whole existing infrastructure supporting the game’s world 2. The WoT layer that is currently in the works will further provide the means to seamlessly keep out any automated noise, spam and the like while simultaneously enabling all users to effectively retain both control and accumulating benefits for everything that they put into participating. To the extent possible, I fully intend to further align the incentives as much as I can to support meaningful conversations that are worth re-reading, too – without any unnecessary restrictions and with fully owned responsibility as well as benefits for each participant, too. It is to my eye the only way in which having a chat capability is even worth it in the first place.

To add the chat capability to Eulora2, there are two new message types added in section 4 (Serpent packets), to request and receive chat lines, respectively, as well as one new action type added to section 7 (Character actions) describing the “Say” action. Using the same specification format, the newly added sections are the following:

4.9 Line Request

  • uint8 (type ID, =12), followed by
  • uint8 (count of lines), followed by
  • n times uint32 (id of chatroom), uint64 (lowest line number requested), uint64 (highest line number requested), followed by
  • padding to Serpent-message length

4.10 Line Info

  • uint8 (type ID, =13), followed by
  • text (line content), followed by
  • uint32 (chatroom ID), followed by
  • uint32 (speaker ID), followed by
  • uint64 (line number), followed by
  • uint64 (keccak hash of the line’s content and number), followed by
  • padding to Serpent-message length

Updated 30 Oct 2024: ratings are now fully integrated and used in-game, being fully handled via the relevant Rating node in the data hierarchy. Consequently there is no need anymore to have dedicated message types for discovery and retrieval, so the “rating request” and “rating info” message types below are removed entirely. See in any case the protocol specification for the full protocol.

4.11 Rating Request

  • uint8 (type ID, =14), followed by
  • uint8 (count of requests), followed by
  • n times uint32 (source ID), uint32 (target ID), followed by
  • uint16 (message count), followed by
  • padding to Serpent-message length

4.12 Rating Info

  • uint8 (type ID, =15), followed by
  • text(rating comment 3), followed by
  • uint32 (source ID), followed by
  • uint32 (target ID), followed by
  • uint8 (rating value 4 ), followed by
  • uint16 (message count), followed by
  • padding to Serpent-message length

7.9 Say 5:

  • uint8 (type ID, =9), followed by
  • text (line content), followed by
  • uint32 (room ID), followed by
  • uint64 (keccak hash of the line’s content)

7.10 Rate

  • uint8 (type ID, =10), followed by
  • text (rating comment), followed by
  • uint32 (target ID)
  • uint8 (rating value)

A line of chat in Eulora2 has a maximum length of 1445 characters. This is fixed and unchangeable as it is the maximum that fits in a 4.10 message (which has the least space for the line’s content out of all the messages relevant to chat lines and therefore effectively decides the *maximum* allowed line length). This limit is unlikely to be perceived all that often in practice but even if it is, note that it’s anyway more generous than most other existing chat protocols, irc included. Any client implementation is however entirely free to take its own approach as to how it handles this – whether it splits some user input into several lines if needed or whether it restricts input to this maximum of 1445 characters to start with, to give some concrete examples.

Beyond the above specific characteristics, for all intents and purposes chat rooms in Eulora2 are otherwise like any other game entities and thus the above additions to the communication protocol itself are both minimal and all that’s truly needed for a practical, working implementation. The speakers themselves are also characters (whether player controlled or not) in the game, hence fully described otherwise through the existing messages.

Messages 4.10 (Rating Request), 4.11 (Rating Info) and 7.10 (Rate) provide, respectively, a way to request and obtain from the server any desired ratings between two known entities in the WoT and to register/update one’s own rating of another. The comment part of a rating is meant to provide some context for the chosen value but as the value itself, the actual meaning and use is up to each individual and likely to be different from one person to another.

Worth noting that messages 4.10 and 4.11 are provided mainly as a basic and potentially last resort means of requesting and obtaining specific ratings. They are however quite unlikely to be the best choice for exploring or obtaining the full set of existing ratings, especially across a relatively large WoT, since each rating will require its own message and the traffic thus generated is to be paid for by the requesting client. A much cheaper and more convenient way to explore and update a local copy of the WoT will be provided in-game through an abstract object providing the full representation of the WoT in a single file and taking thus advantage of all the existing infrastructure, without requiring any new types of messages or other changes to the existing protocol.

Feel free to ask any relevant questions in the comments section below.

  1. Serpent keys[]
  2. Obviously, any of the users can otherwise make public the chat logs they have when and as they see fit but if you rely on something outside Eulora2 for that, it’s strictly between you and that provider, nothing to do anymore with either Eulora2 or the support and protection it provides.[]
  3. Limited to at most 1445 characters, matching the maximum length of a chat line.[]
  4. Valid rating values are integers between -10 and 10. For a given rating value here GR, the corresponding actual rating value RV is therefore calculated as: Min(GR, 20) – 10.[]
  5. Note that this is an action and as such just a part of a 4.5 message, Client Action, where the overall message structure is specified.[]

November 16, 2022

The Client for Eulora2 in Glorious Detail (and Picture!)

Filed under: Coding,Eulora — Diana Coman @ 4:38 pm

~Referencing, of course, the previous version of EuCore and even that very beginning of creating a useful structure to it all.~

As I’ve opened up a test environment for helpful people to give a go to the latest client, they are likely to benefit as well from an updated and more comprehensive overview of the full client code, as an initial map of sorts, at the very least. So this is what I’m aiming for with this article – to provide an up to date map of the current client and a place for questions and answers on it all, in the comments.

While the previous article focuses exclusively on the EuCore part, meanwhile I really had to deal as well with the GUI part, as there wasn’t anybody else doing anything about it otherwise. So the GUI part got significantly trimmed, mostly overhauled and otherwise changed from inside out to provide the sort of flexible and reasonably structured functionality that I need as opposed to the assumptions-ladden and spaghetti-shaped sort of “service” that was previously available. As a result, out of all those half a million lines of code and countless files, there are now… 40308 lines of c/cpp code in total remaining. More than half of this (27584 lines according to a wc run currently) is in fact the only remaining sprawling mess that got now at least insulated in its own directory, namely the PAWS horror. In more practical terms though, there are 11 classes that are almost entirely re-written and make up the bulk working part of the GUI, 2 classes (one entirely new and one adapted) for providing the whole set of views, windows and overlays that Eulora2 needs and otherwise a bunch of the remaining “utility” classes that are quite often simply dragged in by various spidery includes of the PAWS variety. Here’s the full remaining tree of the GUI (ie the C/CPP part of the client):

~/client20/src/
├── client
│   ├── err.cpp
│   ├── err.h
│   ├── euaction.cpp
│   ├── euaction.h
│   ├── euloader.cpp
│   ├── euloader.h
│   ├── eumovement.cpp
│   ├── eumovement.h
│   ├── globals.h
│   ├── meshattach.cpp
│   ├── meshattach.h
│   ├── paws
│   │   ├── gameviews.cpp
│   │   ├── gameviews.h
│   │   ├── pawsborder.cpp
│   │   ├── pawsborder.h
│   │   ├── pawsbutton.cpp
│   │   ├── pawsbutton.h
│   │   ├── pawscheckbox.cpp
│   │   ├── pawscheckbox.h
│   │   ├── pawscombo.cpp
│   │   ├── pawscombo.h
│   │   ├── pawscrollbar.cpp
│   │   ├── pawscrollbar.h
│   │   ├── pawsframedrawable.cpp
│   │   ├── pawsframedrawable.h
│   │   ├── pawsimagedrawable.cpp
│   │   ├── pawsimagedrawable.h
│   │   ├── pawslistbox.cpp
│   │   ├── pawslistbox.h
│   │   ├── pawsmainwidget.cpp
│   │   ├── pawsmainwidget.h
│   │   ├── pawsmanager.cpp
│   │   ├── pawsmanager.h
│   │   ├── pawsmenu.cpp
│   │   ├── pawsmenu.h
│   │   ├── pawsminimalslot.cpp
│   │   ├── pawsminimalslot.h
│   │   ├── pawsmouse.cpp
│   │   ├── pawsmouse.h
│   │   ├── pawsnumberpromptwindow.cpp
│   │   ├── pawsnumberpromptwindow.h
│   │   ├── pawsokbox.cpp
│   │   ├── pawsokbox.h
│   │   ├── pawsprefmanager.cpp
│   │   ├── pawsprefmanager.h
│   │   ├── pawsprogressbar.cpp
│   │   ├── pawsprogressbar.h
│   │   ├── pawspromptwindow.cpp
│   │   ├── pawspromptwindow.h
│   │   ├── pawsradio.cpp
│   │   ├── pawsradio.h
│   │   ├── pawsselector.cpp
│   │   ├── pawsselector.h
│   │   ├── pawsstringpromptwindow.cpp
│   │   ├── pawsstringpromptwindow.h
│   │   ├── pawstabwindow.cpp
│   │   ├── pawstabwindow.h
│   │   ├── pawstextbox.cpp
│   │   ├── pawstextbox.h
│   │   ├── pawstexturemanager.cpp
│   │   ├── pawstexturemanager.h
│   │   ├── pawstextwrap.cpp
│   │   ├── pawstitle.cpp
│   │   ├── pawstitle.h
│   │   ├── pawstree.cpp
│   │   ├── pawstree.h
│   │   ├── pawswidget.cpp
│   │   └── pawswidget.h
│   ├── pscamera.cpp
│   ├── pscamera.h
│   ├── pscelclient.cpp
│   ├── pscelclient.h
│   ├── pscharcontrol.cpp
│   ├── pscharcontrol.h
│   ├── psengine.cpp
│   ├── psengine.h
│   ├── psmainwidget.cpp
│   ├── psmainwidget.h
│   ├── smgdata.cpp
│   └── smgdata.h
├── common
│   ├── placeholder
│   └── util
│   ├── command.h
│   ├── consoleout.cpp
│   ├── consoleout.h
│   ├── fileutil.cpp
│   ├── fileutil.h
│   ├── heap.h
│   ├── log.cpp
│   ├── log.h
│   ├── psconst.h
│   ├── pserror.cpp
│   ├── pserror.h
│   ├── psstring.cpp
│   ├── psstring.h
│   ├── psutil.cpp
│   ├── psutil.h
│   ├── psxmlparser.cpp
│   ├── psxmlparser.h
│   ├── README
│   ├── singleton.h
│   ├── stringarray.h
│   ├── strutil.cpp
│   └── strutil.h
└── placeholder

4 directories, 104 files

The main method is in psengine.cpp 1 and that starts and initializes everything needed, then enters the loop provided by the graphics engine and at the end cleans up whatever is left. The first initialised is the graphics engine, CrystalSpace and that comes with its own “object registry”, configuration and initialisation dances that have been however trimmed to a minimum and corralled into a single method (and a single, shared configuration file, too!) that is hopefully reasonably easy to read. After that, the Ada part of the client, namely the EuCore library (see below for more on its role) is given the green light to start and provided all goes fine, the next steps are to simply initialise the GUI logic that is in psengine itself and then to enter the CrystalSpace loop that runs for as long as the game is running.

The GUI part has the following main components:

  1. psengine – the central part that provides access to everything else and otherwise registers with the graphics engine to receive regular callbacks on events of interest. Such events of interest include each frame drawing and all user input. The callbacks on each frame drawing act effectively as a sort of heartbeat of the client as a whole and thus coordinating the different parts of the GUI. User input is generally received and then passed on to the relevant action handler (see euAction below) or to further potential handlers where relevant.
  2. pscelclient – a class 2 that is meant to keep track of and otherwise provide all logic and management related to game entities. This is one level above the graphics engine and acting as a sort of bridge between the data as obtained from EuCore and its translation into the graphical format that the user gets to see. So pscelclient uses what the graphics engine provides, asking it to create, move, change and delete any graphics in the game’s world to match the information it gets from the data available from EuCore.
  3. pawsmanager – meant to keep track of and otherwise provide all logic and management related to “widgets” aka the various windows, views and overlays that make up the game’s interface rather than its world as such. This relies especially on the various views and overlays that are specific to Eulora2 and are defined in gameviews.h/cpp. This has most of the original mess intact but mostly sidelined and otherwise the useful bits and parts wrote in. The trouble cleaning this up is that ~all the paws calls back home to this and quite often with hardcoded include and calls too so it really wasn’t worth yet my time to clear it all up on top of everything else.
  4. pscamera – a class that provides and maintains the available ways to view the game’s world as it is otherwise populated by pscelclient.
  5. controlsManager – a class holding all the mappings of keys and mouse buttons so that they work as set in the configuration file and otherwise allow the user to provide input and interact with the game.
  6. euaction – a hierarchy of classes that provide the required input, processing and output capabilities to enable the user to perform all relevant actions in the game. The central psengine initialises a full set of objects from this hierarchy and then simply passes on to the relevant one the request for execution with any parameters as provided by the user at that point.
  7. euloader – a static utility class providing ways to create on the fly any graphics entity of the required type and using the assets indicated simply by a path. This includes creation of very simple elements such as textures but also quite complex ones such as animated characters that require a rather long list of calls to fully make when starting with just a bunch of files. While the creation of such graphics is quite tedious, at least it’s enough to have it packed this way once and then it serves endlessly, effectively providing useful defaults for all the “parameters” that aren’t actually needed or even known at start. The main user of this class is pscelclient.
  8. smgdata – a static utility class that imports all the Ada methods made available by EuCore and wraps them up for transparent use by CPP code from anywhere else in the GUI. Basically all requests to EuCore are made through this class.
  9. While the above GUI part focuses exclusively on the interaction with the user, it relies on the separate EuCore library to communicate with the server and to exchange and obtain all required data. The EuCore library handles everything in this respect, including creating a RSA-based identity and account, initiating and maintaining fully encrypted communication with the server, obtaining and updating all data related to the game’s world as available at different times to the player, retrieving from the server through the same encrypted communication any missing files and managing existing local files including their use as temporary defaults when needed and where appropriate. The full EuCore weighs in at about 27000 lines including tests and the mpi part that has about 8000 lines of code by itself. Here’s an updated full picture of all Ada package dependencies:

    eucore_2_1024.jpg

    Compared to the previous version, there is a striking change at the top where EuInterface is now the “entry” package instead of EuCore. This reflects actually better the meaning of the two packages and by now the whole code matured enough so that the refactoring was quite obvious, too. Basically EuCore is the starting package for the whole library, while EuInterface literally provides an entry point for any C code that wants to use the library and this includes now the previously missing C-compatible wrappers for EuCore’s Start/Stop methods themselves. Thus any Ada code that uses this library can entirely discard EuInterface and just start with EuCore, while any C code using this library goes entirely through EuInterface and doesn’t need to see or know of anything else.

    Further comparing with the previous version of EuCore, there are also a few new packages, most notably Mgm_Cache that comes now between Heartbeat and EuCache, as well as C_Buffer at the very bottom. The C_Buffer package is literally for interfacing with C code so that Ada code can take advantage of faster writing to files mostly. The Mgm_Cache package does what the name suggests, namely provides the higher level logic to oversee the data cache that is EuCache itself. In fact, the Heartbeat package serves as on overall coordination mechanism across the whole of EuCore and as such it effectively provides regular calls as required to various parts such as the communication link (Comm_Link), the data cache (EuCache) and the assets downloader (Torrents). As the communication link is both the most critical and the most demanding component of these, the Heartbeat really grew first of all as a manager of Comm_Link and only once that was fully working the rest could be developed as well. At the moment, the management of EuCache grew big enough to make sense to extract it in a separate package of its own but otherwise I don’t see a lot of benefit in doing the same for Torrents for instance.

    Note that all dependencies in the graph above remain hierarchical as they should always be. The automated layout of the graph tends to make it look as if there was some nonsense going on perhaps with that seemingly horizontal line going from OAEP to Keccak, but that’s just an artefact of positioning. In reality, Keccak is on a lower level than OAEP, being simply a hashing utility, although one that is most useful indeed. At any rate, OAEP uses Keccak and there is no dependency going the wrong way, as Keccak itself uses only raw_io and raw_types.

    Hopefully this gives enough of an overview to have some idea as to what is where and how the whole fits together. If you have though further questions on it, feel free to ask in the comments below and I’ll gladly answer.

    Finally, if you made it all the way here and would still rather see a less schematic picture as well, here’s a fresh one of the client in action at a meeting of like-minded creatures of Eulora2, surprised as they were by all the screenshooting commotion:

    eucore_1_1024.jpg

    1. Despite the name of the file and of the class, there is very little indeed left in there from the original code. I suppose I could have changed it all to euengine or something more appropriate but given how it’s one of those included from just about everywhere due to the original “design”, I didn’t really consider all the resulting noise worth the trouble.[]
    2. This is also mostly re-written with only very little indeed remaining of the original “gem” pain. It could still do with a haircut at least, I’d say.[]

October 19, 2022

The Needed Cut

Filed under: Eulora,Lyf — Diana Coman @ 9:30 pm

More than a year after the sudden death that left so many things up in the air, it’s time to make a straight cut to let all these things go and take stock otherwise of what is rather than what it might or could have been. So I’ll cut through the tangles as straight and direct as I can see it and as deep as it has to be, to get for my own needs to some clarity at the very least.

As far as I know, both Minigame and MPeX were fully owned and entirely controlled by Mircea Popescu alone. I am not aware even after all this time of any provision made for any sort of action to be taken in the event of the owner’s death and so the straightest possible conclusion is that there is no change with respect to ownership. There is simply a drastic and irreversible change to the action capability of the owner bringing it down abruptly from 100% to 0% and that’s about the end of it. The owner remains the same but he simply isn’t active anymore and therefore isn’t able to answer queries about it, to take action over it or to make any changes to any of it, for better or for worse. As a result, Minigame and MPeX with all their assets are left basically frozen, neither closed down nor even bankrupt but simply owned by an absent man.

Of course, one can steal things even from a dead person and in this scenario, Minigame as well as MPeX might still change ownership at some later time for all I know. As far as I’m concerned though, I’d much rather make my own thing whatever that might be rather than steal someone else’s and whether they are alive or dead doesn’t make any difference to this choice of mine. I don’t think there is such a thing as “default inheritance” – if the owner didn’t set up any sort of inheritance provision while they were alive, then there is only theft left possible as means to transfer ownership to someone else.

I suppose the above is about as close as it gets to the exact opposite of that old saying that “you can’t take any of it with you when you die” – actually, you can take with you precisely and exactly what you fully and solely owned *and* animated. It turns out that what you can or can’t take is simply a reflection of the strength and extent of your ownership and authorship of it, not some sort of absolute at all. In other words, when one dies, one takes out of the living, ever-changing world everything that stops changing with their death and it doesn’t even matter whether they wanted or not any of it to stop too when their own life did. By contrast, what can’t be taken is anything and everything that still has either a life of its own or at least another owner who is still alive. Neither Minigame nor MPeX got to have either.

Worth noting perhaps that despite the more usual single-sided view that tends to focus solely on the survivors’ perspective, this cuts in fact two-ways. Yes, it means indeed that nobody inherits that for which no explicit inheritance provision has been made. It also means though that nothing will live on beyond the owner’s life if that same owner, while alive, didn’t make successfully any provision for its survival after their passing. Intentions on either side don’t come into any of this at all and it really is only actions that decide it and nothing else.

Such frozen ownership as Minigame and MPeX are currently under has, of course, quite terrible consequences for anyone involved with them and still alive since there is no closure of any sort and otherwise in financial terms, all money invested in any of it is as good as lost, all shares, warrants and any other claims are basically rendered worthless. Since I had invested so much in Minigame via both Eulora1 and MPeX, I also lost a significant amount. As far as money alone is concerned, it’s indeed the case that I’ve never lost before anywhere near so much even if I scramble to add up on the other side of the scales all the money I ever lost previously to any sort of circumstance at all. It’s just a whole order of magnitude above everything else added together and there is no way around it or out of it – the only way to move any further is through it. Onwards, then.

It can be very tempting and it’s certainly very easy indeed to pass the responsibility for this loss onto the absent man seeing how he can’t do anything anymore about it. Even so, I choose to retain instead in full the responsibility for my own loss because with the responsibility thus retained, there is also my own agency and my own integrity retained and I can therefore move on unencumbered even through and beyond such situation as this. Possibly moving on even wiser and at the very least more experienced, quite unforgettably so.

Beyond retaining agency and with it responsibility as they are inseparable, what makes it possible to go onwards through this sort of terrible outcome is precisely the even higher amount of non-financial investment that I have been making each and every day over these past years. Because it’s indeed money that is easiest to lose, being as it is an external token after all and furthermore, being invested itself into something external that wasn’t under my control. If all that I had invested was my money though, the financial loss would be the same but it would also be the full extent of the story, turning the entire situation itself into pure loss and nothing else, just a bleak negative with no redeeming point of light at all. But this is not the case here and the only reason that there is anything of value left at all for me is simply that I had invested quite a whole lot more than only my money: my effort, my work and my commitment over years and through it all, as difficult and even as exhausting as it got at times.

Of everything invested, the money is the only part that’s gone. By contrast, the effort, the work and the commitment are not and cannot ever be gone, paying their own sort of dividends in the form of accumulated and verifiable achievements, experience, knowledge, expertise and even concrete tools and whole environments that I made and over which I have indeed full authorship and ownership, as well. As a result, I can take any and all of it from here perhaps not necessarily towards the exact destination I had imagined when starting or even at any other time until now but certainly anywhere I want to move them further, if and when I choose to do so.

What comes next therefore is quite an open path or even set of paths, since the paths available will be exactly those that I make and then choose to travel on. Although this is not at all and by any stretch of the imagination a place where I ever aimed to be, this is nevertheless where I am. What is gone is gone but I still have everything I made myself and everything I learnt through all the relentless work these past years, through all the experiences of all sorts and through the very close collaboration that touched on a lot of things indeed, from direct and long term experience with complex systems development to philosophy applied to game design and quite a whole lot more besides. In concrete terms, I also have the fully working infrastructure that I built for Eulora2, the full knowledge and even written record of everything that went into it, as well as the supporting tools that I designed and built for the exact sort of collaboration that I care for, possibly including code development for sure but positively enabling much more than that.

More important and on top of the above, I also have the relationships I built during this time with people who I value and with whom I share now this experience, as well. With such deep roots and on such a solid basis as all this, all my options are therefore quite open moving on from here and the choice is fully mine, too, regarding which way to go and how fast or slow to move, at any time.

Even loss is, in the longer term, what one makes of it.

September 20, 2022

Leisurely Coding or Solving the Interesting Problems

Filed under: Coding,Eulora — Diana Coman @ 1:26 pm

The prize for having a clean environment (not merely code, nor even limited to code) is refinement of precisely the most intellectually pleasing sort: getting to uncover and solve interesting as opposed to tedious problems. In other words and as far as I can tell from direct experience, even coding really doesn’t have to be at all “like plumbing” if the sewers are properly cleaned and it doesn’t have to be sterile either if the willfully blind focus on idealia is discarded. In a reasonably clean – not perfect, nor even “best possible” – codebase 1, there is both space for experimentation (aka introducing new things) and support for refining existing solutions. Arguably, there is even space and support for literate collaboration but this does tend to grow more slowly being as it is a fully organic culture in its own right. There is time, there always is… until there isn’t.

The most recent concrete example of what made for me quite an interesting problem brings together knowledge representation, data caching, remote synchronisation over a lossy channel and even matters of time representation across different contexts. Then again, arguably one’s problems can only get as interesting as one is able to make them to start with so perhaps it’s all tailor-made indeed. Either way, I’m neither boasting nor complaining, merely describing so here’s an attempt to sketch out the problem in its context:

  1. The game‘s client has to obtain, maintain and represent (including graphically but not only in such form) as accurately as possible the knowledge of the game’s world as accessible to the player and as it continuously changes as a result of the player’s own actions and as a result of others’ actions or even simply the passage of time. In all cases, the actual changes are not known upfront nor automatically obtained – while the server decides at all times what and how is in the game’s world, it’s entirely up to the client to *ask* for whatever it wants, whenever it considers it needs it. Quite on purpose, there is no information pushed from the server to the client at any time and although all questions receive an answer, there is no guarantee that all answers make it back to the client in any given timeframe or even at all. Hence, the problem here is to find an effective way to find out as quickly as possible all that is new but also, arguably even more difficult, what has become obsolete! And possibly the most difficult part here is to even define what “quickly” means since there are at least several definitions of time itself in this context: the user’s own time, the time in the game, the time as kept by the client, the time as kept by the server. What does “quickly enough” mean and when is something “too old” or even obsolete? What is the meaning of “1 second” in the game-world, what is its meaning on the network and how does one reconcile these two?
  2. The communication protocol defines the rules for a hierarchical structure that provides effectively the support for representing all the knowledge mentioned above but this structure is an ever-evolving one and with no specific limits to either depth or breadth at any given time, beyond a basic “it’s always finite” guarantee. Moreover, any request comes with a cost and that’s not even limited to time – arguably the resulting traffic is costlier, both as it *is* going to be included in the bill the user pays in one form or another (most likely directly wired into game mechanics) and as it can easily have undesired consequences clogging the client’s communication pipe for instance or even… triggering undesired changes because yes, in some cases, merely asking for something means that something will change 2. Hence, the direct, brute-force approach of “explore the whole knowledge tree at regular intervals” is not much of a solution to anything or not a long-term one, at any rate. And if one doesn’t explore the whole of it then how does one figure out the holes in one’s knowledge, those things one doesn’t even know yet one doesn’t know?
  3. The desired graphical user interaction (GUI) clientside adds some potential troubles of its own since it’s quite difficult to provide meaningful immediate feedback to an action when its actual results require in the best case a confirmation from the server (when guessed correctly) and in the worst case a search for and figuring out of how the world changed (when the guess is merely incomplete perhaps, although it can even turn out to be entirely wrong). Sure, one can *hide* this and pretend that everything is known upfront, arguably making it thus more convenient or something of the sort but pretense aside, the reality of it is simply that the GUI is at best twice-removed from reality and as such always kind of struggling behind: the reality it can directly access is at best a local cache and that cache is in turn at best a fragment (perhaps already obsolete in places) of the remote world that is at all times on the server and ever evolving even there 3. So how can the GUI be as truthful and responsive as possible when providing the user with a representation of the game’s world, without limiting them either? Because the whole point of a GUI is to enable, after all and moreover, the game itself is quite on purpose as open as possible – the scope of what one can do depends on what they have already done, not on some predefined and fixed laundry list that some uppity GUI takes upon itself to enforce on behalf of the server.

The above is the overall shape of the problem and as complex or “that’s not how these things are done” as it may sound, the core of it is already solved and working in practice. What still remains to be done, is really the refinement of this core of a solution. How interesting and rewarding such refinement turns out to be or not depends mostly on the person asking and working on it, as always.

As for myself, I certainly have even more interesting problems to solve on the serverside so I don’t particularly intend to pursue more than absolutely needed anything clientside. The client is open source after all and it will only ever be as good or fit for your own purposes as you make it to be. Does this sound like a downside or an upside to you?

  1. It’s always improving though and the cleanliness really has to do with how supportive of improvements it is, not really with some perfection or best anything. First of all, lots of requirements, constraints and even actual extent of the problems to solve got clearer only with practice and the corresponding code reflects this. Second, I learnt a lot in the process too and this also shows – yes, the 2nd time one does something it will probably be better done than their 1st and the 100th time even better than that. Cleanliness though doesn’t mean nor require skipping the first step nor the first 99 – that’s just a way to get stuck and it’s still silly even if very common – but simply creating that path that enables all the steps that may still come. So no, there wasn’t nor is there some perfect anything, code included, to be “fully solved” or achieved in some entirely ideal form and then either worshipped or blown to pieces, depending on inclination. There’s only sustainable growth, gathering up momentum and opening up new possibilities as it evolves, that’s the best possible meaning of clean – it enables the growth of new animals and plants, not that of new fungi.[]
  2. Does it ring a bell, at all?[]
  3. Are you *sure* that this is all that different from the actual “reality” of what you see with your own eyes even when no computers nor games are involved as such?[]

August 23, 2022

Walking the Walls and Scaling the Spires

Filed under: Lyf,Tgdyk tgdyk — Diana Coman @ 4:08 pm

The walls and spires in question are those that still stand of that old Roman settlement called Eboracum, known at the moment simply, if not necessarily better, as York. While you might be tempted to call this perhaps the old York in contrast to the New York, resist the temptation as it’s leading you astray – the New York was actually New Amsterdam since it started as a Dutch colony, not an English one. That it switched names reflects people and not places – it’s New York because of the Duke of York, not because of the town of York. Here’s proof of walking the walls though and a willing guide for you to come along, too:
york_leeds_12_640.jpg
york_leeds_14_640.jpg
york_leeds_52_640.jpg
york_leeds_35_640.jpg
york_leeds_37_640.jpg
york_leeds_38_640.jpg
york_leeds_39_640.jpg
york_leeds_40_640.jpg

Punctuated with round towers of various designs and a few gates from place to place, these walls of lightly coloured stone still encircle most of the original settlement that was indeed a camp and a fortress right from the start. That start dates back to around 70AD when the Romans picked the place for its strategic advantage at the intersection of two rivers and set up camp to finally calm down the region and claim -or possibly make obvious, if you prefer- their authority over it.
york_leeds_16_640.jpg
york_leeds_18_640.jpg

york_leeds_50_640.jpg

york_leeds_56_640.jpg
york_leeds_57_640.jpg
york_leeds_8_640.jpg

york_leeds_9_640.jpg

While such authority lasted, the walls stood useful and the town grew and flourished under their protection. Then things changed, of course, as they always do. With time, the once useful walls were found to be increasingly in the way (of horses mainly, in this case) and started to be removed. The authority once claimed with the sword to be held fully and visibly, morphed, fragmented and got increasingly out of sight in a way, too. Still, the battle for the walls happened once more, only it happened in the courtroom this time and it turned the roles around, with the walls facing the town itself as enemy when the Archbishop of York sued the Corporation and won, somewhere around 1800.
york_leeds_51_640.jpg

What angered the Archbishop was however not the loss of the walls themselves but more importantly his loss of the toll that was paid to him at the gates – only for as long as the gates were still standing, of course. In other words, the walls were defended indeed, for the service they still rendered, nothing else. This reason for the court-battle is not mentioned though at all in any of the “information” signs and leaflets and what-not that abound otherwise. I’m sure there simply wasn’t enough space for it but don’t you get curious as to what else failed to find enough space to be… advertised, properly speaking? Even so, the net result remains that the walls are still standing for the most part while the town found nevertheless ways to expand further without quite obliterating its own past. With time, everything that remained in place still found other uses even if at times not quite fitting perhaps the former glory.
york_leeds_10_640.jpg

Further afield and on the outskirts of the town, there’s also a round tower looking down from a hill and a rather squat mini-palace of sorts. With the patience or perhaps indifference of stone, they all wait to find perhaps another purpose and be once again brought to life by it. They look quite dignified to me, even if the length of this waiting is starting to show, too.

york_leeds_46_640.jpg
york_leeds_47_640.jpg
york_leeds_48_640.jpg
york_leeds_49_640.jpg

In the town itself, away from the walls, the stone gets worked upon quite intricately, first by the masons of various ages and then by the winds and rains of all ages. The streets are too narrow for modern cars and as a result, most of the centre is for pedestrians only, making it quite pleasant for walking and taking in all the various quirks of sedimented 1 life and ages.
york_leeds_4_640.jpg
york_leeds_6_640.jpg
york_leeds_22_640.jpg
york_leeds_28_640.jpg
york_leeds_32_640.jpg
york_leeds_33_640.jpg
york_leeds_34_640.jpg

Funnily enough for those in the know, of the two rivers that meet at York, namely the Ouse and the… Foss, guess which one is nicely blue and which one is choked full of ugly green algae? What’s in a name!
york_leeds_30_640.jpg
york_leeds_31_640.jpg
york_leeds_3_640.jpg
foss_1_640.jpg
foss_2_640.jpg

The Art Gallery sports a spiky outgrowth as modern counterpoint and contribution to all that carved stone, while a relatively small church lacking the fame of the main cathedral stands elegant and uncrowded on a corner of a street.
york_leeds_7_640.jpg
york_leeds_76_640.jpg
york_leeds_77_640.jpg
york_leeds_78_640.jpg
york_leeds_79_640.jpg

The Cathedral that is nevertheless called a Minster 2 towers over the rest and hosts on its side a greenish statue of the emperor Constantine apparently relaxing even if in a rather unlikely pose. He has great sandals though, the sort one sees worn only at fashion shows and never for any practical purpose, in this case what look like flip-flops with lion heads extending on the shins.
york_leeds_112_640.jpg

In front of the York Minster, the grass truly is always greener on the other side of the fence – only it’s not real grass, of course:
york_leeds_29_640.jpg
york_leeds_19_640.jpg

The church itself is quite pretty on the outside and even interesting although not all that homogeneous inside. Apparently its building took long enough for fashions to change even in architecture and as a result, the currently standing construction has for instance gothic windows indeed, but several types of gothic. Which makes the whole approach perhaps not even all that far removed in spirit from the way the houses used to expand in the countryside, too: each couple of years some parts might get added or knocked down depending on new needs or fashions or simply people. Only the York cathedral did it in stone and so it remained long enough for the whole mixture to show as it does. Inside, rows upon rows of carved figures poke out of the walls or attempt to stand neatly in a line while looking nevertheless in all directions – when they have at least heads for such purpose.
york_leeds_21_640.jpg
york_leeds_26_640.jpg
york_leeds_27_640.jpg
york_leeds_82_640.jpg
york_leeds_83_640.jpg
york_leeds_84_640.jpg
york_leeds_85_640.jpg
york_leeds_86_640.jpg
york_leeds_87_640.jpg
york_leeds_88_640.jpg
york_leeds_89_640.jpg
york_leeds_90_640.jpg
york_leeds_91_640.jpg
york_leeds_92_640.jpg
york_leeds_93_640.jpg
york_leeds_94_640.jpg
york_leeds_95_640.jpg

Colourful beads hang from a ceiling at some point for some reason that is entirely unknown to me.
york_leeds_96_640.jpg

Two knights guard the time on one wall and strike their weapons to mark the passing of each half hour interval. On a different wall, a carving shows apparently some traffic jam at the pedestrian entrance to hell – devils on duty try to shove the incoming traffic faster out of the way.
york_leeds_97_640.jpg
york_leeds_98_640.jpg

There’s a crypt inside the church, too, all musty and damp but brightly lit by modern light bulbs. And there’s the cathedral’s spire to scale, quite steep but rewarding, with views from half-away across the church’s front two towers and then, from the very top of the church, across the whole town and beyond.
york_leeds_99_640.jpg
york_leeds_100_640.jpg
york_leeds_101_640.jpg
york_leeds_102_640.jpg
york_leeds_103_640.jpg
york_leeds_104_640.jpg
york_leeds_105_640.jpg
york_leeds_106_640.jpg
york_leeds_107_640.jpg
york_leeds_111_640.jpg
york_leeds_108_640.jpg
york_leeds_109_640.jpg
york_leeds_110_640.jpg

Trading stone for the metal and masonry for engineering, one can also see in York a rather densely packed history of trains and railways, at the Railway Museum, aptly located right next to the train station currently in use. To compare and contrast though, even after visiting the Mallard and all sorts of Duchesses on rails, we took nevertheless the modern electrical train leaving the town and getting back to the present that is rather than any other present that once was.

york_leeds_64_640.jpg
york_leeds_66_640.jpg
york_leeds_67_640.jpg
york_leeds_68_640.jpg
york_leeds_69_640.jpg

york_leeds_71_640.jpg

york_leeds_73_640.jpg
york_leeds_74_640.jpg
york_leeds_75_640.jpg
york_leeds_1_640.jpg

  1. Hrm, apparently English has sediments and sedimentation just fine but somehow sedimented is nevertheless not fine at all. The alternative suggested by native speakers would be assimilated but I don’t think that’s really the same meaning at all: no, it’s not about assimilated quirks or anything else but literally about the sediments of different ages and how they build up as time passes and grinds them more or less together, more or less to pieces, more or less into something else, at times.[]
  2. This is where the church nomenclature gets utterly but also quite typically confusing: normally a church is called a Minster if it has a priest at all times, performing all the relevant duties including visiting parishioners; to be called a Cathedral, a church needs to be the site of a bishop’s throne; since the church in York *is* the site of a bishop’s throne, it should be called a Cathedral *but* the very word “cathedral” is basically too… new to be fully adopted – it came into use only after the Norman Conquest and so York’s cathedral is still called a Minster as it has “always been”. Problem?[]

July 21, 2022

Roundness and Randomness or Point Picking in the Digital

Filed under: Sense and nonsense — Diana Coman @ 3:04 pm

Programming turns inside out the traditional fitting of the square peg in a round hole: in the computers’ binary worldview, it’s the randomly generated sphere struggling to fit in a deterministic square grid. The rigid limited precision of the digital medium together with the natural pro-patterns bias of the human programmer leave very little space for true roundness and possibly even less for true randomness.

Roundness and randomness in the digital tend to get therefore approximated at best and whether such approximations are good enough or not for you depends, of course, on how closely you look at them and what your needs are. Beware though that randomness is much harder to evaluate than roundness through mere looking and it’s also much easier and more likely to get silently lost or at least subtly damaged on the way, even when verifiably provided as input. What may seem at first totally innocent and otherwise perfectly valid choices of implementation can have unintended consequences with respect to actual randomness that makes it through.

To illustrate the above, consider this seemingly easy task of writing code to pick random points 1 from within a sphere centered at the origin and with unit radius. Repeating this for long enough would naturally produce a “noisy” model of a sphere since all points inside the sphere have equal probability of being chosen at every pick. For instance, 10`000 such points might look like this when plotted on a 3D grid:

rando_mt_loops_640.jpg

The randomness-preserving implementation that produced the above set of points is quite simple: request from your reliable random number generator 3 numbers in the interval [-1.0, 1.0] and keep them if the 3D point they describe is within the desired sphere or discard them and try again if it’s outside of the sphere 2. Since the interval given covers the 3D space of a cube (as imposed by the square grid) rather than a sphere (as desired), it obviously follows that some of the points will be outside of the sphere but how many might that be? The cube’s volume is 2*2*2=8 units, while the sphere’s volume is 4*Pi*1/3 ~= 4.19 units, so the probability of a point being *inside* the sphere is only slightly better than half or, more precisely, 4.19/8 ~= 0.52. Conversely, the probability of a point being outside the sphere is (8-4.19)/8 ~= 0.48. Hence, on average, the code will simply discard 48% of the values it requests from the random number generator.

The apparent wastefulness of the above solution (discarding almost half of all inputs!) is so counter-intuitive or possibly even irksome that it naturally invites “corrections” and “improvements” almost instantly. It’s not *just* the size of the apparent waste but also the fact that it’s so shamelessly obvious and with such clever solutions readily at hand to avoid it that it’s almost as if made on purpose to… tempt. Which is quite fitting after all, since what would von Neumann’s state of sin 3 be really worth if there wasn’t any temptation to lead one to it?

As with all other temptations, the only protection that ever works against it is well-rounded experience. Where the inexperienced will rush directly to “improving” the implementation, the more experienced will take the time to at least explore in more detail the alternatives and with a look towards finding the reason why they were not chosen in the first place rather than finding just why they would be so much better than the choice made. Even so, the conclusions drawn from such investigation still depend on how close one looks at the data and, perhaps, simply on one’s outlook to start with, as well. Looking to find something can all too easily get in the way of fully seeing what one is looking at and not even experience is always enough to help one with this sort of trouble.

To illustrate though, let’s have a look at some concrete alternative implementations and what they yield. One straightforward approach is to use polar coordinates for describing the points in the sphere and interpret the three random inputs as two angles and one distance from the centre. The result of this makes it quite obvious that there is some damage done to randomness, given the noticeable pattern that appears:

rando_polar_corr_640.jpg

Another approach is to use vectors for describing the points in the sphere and consider 4 random inputs for each point, with 3 giving the direction (normalising the vector) and the 4th the size. The straightforward corresponding implementation of this shows once again a noticeable focus on the centre of the sphere:

rando_mt_vector_640.jpg

When the aim is to make the loss of randomness simply less obvious, the above approaches can be further refined, aiming essentially to correct the observed damage regarding the way the resulting points are spread in space. Generally the correction would apply some transformation to bring the resulted coordinates of points (back on) to a normal distribution. For example, using the cubed root as multiplier for the size of the vector in the 2nd approach above does spread the points better away from the centre indeed (although some subtle pattern is still visible to my eye in this plot compared to the very first image):

rando_mt_cubed_640.jpg

While there certainly are other alternative approaches possible, the reason why I am not aiming for a more systematic overview of them is that the trouble is more fundamental: all the attempts to “improve” on the very first implementation boil down to introducing another layer of deterministic computations between the values obtained from the random generator and their use. In other words, they *reduce* the randomness at best, even though they can indeed be made otherwise to maintain for instance a normal distribution of the obtained points, hence the appearances at least as far as data plots are concerned.

Discarding randomness to avoid discarding instead 48% of the input may seem like an improvement only if randomness wasn’t all that important to your use case in the first place. Quite often, this is even the case, since the more common goal is to simply approximate randomness well enough for human perception and that is a relatively low bar where randomness is concerned 4. Just make the tradeoff very visible, don’t confuse pseudo-randomness with randomness and be very wary indeed of improvements that might have more subtle effects than intended or perhaps simply more than you can notice from merely looking at a sample output or even checking that it follows some expected distribution.

  1. I’ll assume throughout this article that such random points have an underlying normal distribution.[]
  2. This is the very simple golden standard of preserving randomness really: use the inputs as given, discard and try again if they are not fit for purpose, nothing more.[]
  3. “Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin.”[]
  4. This is actually what even triggered this article – I’ve been working some more on various graphics, resource distributions and similars, basically on an upgraded scope of that older task of finding useful mixtures of order and chaos for all sorts of fun.[]

June 23, 2022

All Tattoos Are Temporary

Filed under: Coding,Eulora — Diana Coman @ 10:13 am

Like everything else in Eulora 1, the tips greeting newly connected players brought new life to an old form, generally turning common and stale anything on its head quite irreverently and with great effect. Since some of these tips still get quoted at times, I’m publishing my list of them here for vicarious enjoyment and, possibly, for easy reference as well:

  1. Welcome to Eulora! May your stay be preposterously prosperous.
  2. Do not think of yourself as an ugly human. Think of yourself as a beautiful monkey.
  3. The early bird gets the worm, but the second mouse gets the cheese.
  4. Better late than pregnant.
  5. You should probably do the laundry…
  6. Silence is golden, but duct tape is usually silver.
  7. Time flies like an arrow, but rotten fruit flies fly like flies.
  8. Everyone has a photographic memory. Some just don’t have any film for it.
  9. Mr. Spirover maintains a positive attitude, even though he knows it won’t work.
  10. If the shoe fits, get another one just like it.
  11. You can’t have everything – where would you put it?
  12. All things nobody else wants come to those that wait.
  13. A fine is a tax for doing wrong. A tax is a fine for doing well.
  14. In Eulora, it does not matter who is right, but who is left.
  15. The best space shuttle is but a large pile of chairs for the head.
  16. Happiness is having a large, loving, caring, close-knit family in another city.
  17. Fear not your own death – just try to not be there when it happens.
  18. Learning is not compulsory. Neither is survival.
  19. There are no rules here – we’re trying to accomplish something.
  20. Oh, the Vinu will love you. There is no sincerer love than the love of food.
  21. Anything that is too stupid to be spoken is sung.
  22. The first rule of tinkering is to save all the parts.
  23. Some are wise; others are otherwise.
  24. The bonds of matrimony are like any other bonds – they mature slowly.
  25. When a NPC marries, it exchanges the attentions of many players for the neglect of one.
  26. The most you can hope for is ending up with the right regrets.
  27. Everyone started out with nothing. Plenty still have most of it.
  28. An unbreakable toy is still useful for breaking other toys…
  29. Does the name Pavlov ring a bell?
  30. The best way to lose weight is to eat naught but inspirational posters.
  31. Old eggs are generally rotten; old hopes are generally delusions.
  32. To find out just how windy it is on the hill move there to escape the damp in the valley.
  33. If you fail to spend enough time laughing at stupid children, you will spend all your time going to war with stupid men.
  34. Your worst enemy has always slept in the same bed as you.
  35. The minnow aspiring to be a whale was stuck in a puddle that did not aspire to be an ocean.
  36. The best things in life are actually quite expensive.
  37. All tattoos are temporary.
  38. The secret of teamwork is that none of us is quite as dumb as all of us.
  39. Hard work pays off in the future. Laziness pays off now.
  40. The power of accurate observation is commonly called cynicism by those who have not got it.
  41. By the time you swear you’re his, shivering and sighing; by the time he vows his passion is infinite, undying… better make a note of this: one of you is lying.
  42. A cynic is that unrepentant blackguard whose faulty vision sees things as they are not as they ought to be.
  43. The world keeps ending, but noobs keep showing up as if the fun just started.
  44. The large print giveth and the small print taketh away.
  45. The worst misfortune that may befal your enemy is a large following of true believers.
  46. Poverty is the sort of suspect virtue one can very readly teach oneself.
  47. Rejection of praise is sometimes humility and some other times holding out for better praise.
  48. It is comparatively easier to make heroic gestures than to abide by the results.
  49. When logic leads to any humiliating conclusion, the human reaction is to discredit logic.
  50. The strongest indication that you lost your way is to find a large majority in agreement with you.
  51. Out of the mouths of babes come bubbles.
  52. The best possible world is the one you can’t live in.
  53. True democratic feeling is reserved for drunken men.
  54. If you can make a woman laugh, you can make her do anything.
  55. What will retrospectively be called will always finds a way.
  56. Most people love because they tried hating and found it requires too much effort.
  57. The very essence of romance is uncertainty.
  58. Man may have discovered fire, but women discovered how to play with it.
  59. Thread carefully when the nude offer to sell you shirts.
  60. Love at first sight is common; love at last sight is comparatively rare.
  61. Love cautiously, enjoy vicariously, dream reasonably, tread lightly and die quietly.
  62. The trouble with being poor is that it doesn’t allow getting into any kind of trouble worth the mention.
  63. Gravitation is not responsible for your great tumble – after all it tried to prevent your climb every step of the way.

May 12, 2022

Bringing Code Text to the Blog, Courtesy of VaMP

Filed under: Coding,VaMP — Diana Coman @ 3:33 pm

Killing two birds with a stone here, I finally found the way to painlessly and easily produce blog articles out of code-writing, too, since writing of code is still writing after all and I really don’t see any reason why those writing today’s literature – also known as “coding” – should be content with being read merely by machines and not publish it on blogs, nor seek a human readership that might be – that is indeed *hoped to be* – more discerning and less easily satisfied, perhaps, but all the more rewarding to interact with! Getting to the point though, I have updated VaMP yet again, to make publishing of code for reference and discussion a natural and integral part of coding instead of some afterthought at best or horrible chore and hated imposition at worst. It took a couple of days and another dive into html and css but the effort has been worth it, seeing how the result is that the machine will do it all for me from now on, quite reliably and without any further probing, questioning or any trouble at all.

Building up concretely that desired support for collaboration between code writers, readers and publishers, VaMP produces from now on automatically and as an integral part of its use, the html file containing the full description of the codebase transformation that each applied patch stands for. This html description includes a clear marking of any created, deleted, moved or unchanged files as well as the full content of every changed file, with links provided for each line of code and html attributes that enable full control of the exact presentation form via a css file or similar.

The relevant added content of my css file to handle VaMP patches presentation currently uses alternating light yellow and beige backgrounds to visually separate consecutive lines from one another and color-codes text with gray for unchanged, blue for added, red with a line striking through the text for deleted. While there is scope quite on purpose for more fine-grained tuning of the presentation, I’d rather add any more detailed bits and parts only when and if needed, so for the time being I’m quite fine with keeping it as short and straightforward as possible 1. Worth noting that the whole view even wraps correctly to screen size any longer lines, as any text viewer should do (and *not* requiring that the writer breaks the text at arbitrary places to force on anyone whatever screen width the writer enjoyed best). All of it is achieved simply with html and css and without any additional plugins or whatever else, since there really is no need for and no gain from any such added complexity.

Since a first attempt to publish the html of a patch revealed that my footnotes plugin is so eager to help that it will interpret as a footnote any repeated round brackets even in text enclosed within <pre> tags, I get to illustrate the shiny new html view of patches, most appropriately, through the latest and possibly smallest patch on VaMP itself – the addition of round brackets to the list of html-escaped characters in VaMP’s shiny new html_io package:

vamp_html_brackets.patch

src/html_io.adb

2_1 
	-- DC, 2022
2_2 

2_3 
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
2_4 
with Ada.Strings.Maps; use Ada.Strings.Maps; -- for the html chars
2_5 
with Ada.Strings; use Ada.Strings; -- for Trim's Both
2_6 
with Ada.Characters.Handling; use Ada.Characters.Handling; -- for To_Lower
2_7 
with Ada.Directories; use Ada.Directories;
2_8 

2_9 
with Raw_Types; use Raw_Types; -- String_To_Raw
2_10 
with Raw_IO; use Raw_IO; -- Write_Octets
2_11 

2_12 
package body HTML_IO is
2_13 
	-- packages from Raw_Types;
2_14 
	use Octets_Buffer_Pkg;
2_15 

2_16 
	procedure Write_Class( class  : in html_class;
2_17 
	                       content: in String;
2_18 
	                       fname  : in String;
2_19 
	                       append : in Boolean := True) is
2_20 
		open_str: String := Html_Open(class);
2_21 
		close_str: String := Html_Close(class);
2_22 
		cls: String := """" & Trim(To_Lower(class'Image), Both) & """";
2_23 
	begin
2_24 
		case class is
2_25 
			when patch =>
2_26 
				-- content = filename of patch, assumed html-safe
2_27 
				declare
2_28 
					cstr: String := Html_Anchor(href_str => content,
2_29 
					                            text_str => Simple_Name(content));
2_30 
					s: String := open_str & cstr & close_str & lf_str;
2_31 
					o: Elem_Array := String_To_Raw(s);
2_32 
				begin
2_33 
					Write_Octets(fname => fname, data => o, append => append);
2_34 
				end; -- patch
2_35 
			when line_no =>
2_36 
				-- content = number/code, as desired, assumed html-safe
2_37 
				-- this opens a <tr> that is closed by the next line_*
2_38 
				declare
2_39 
					nstr: String := "L" & content;
2_40 
					hstr: String := "#" & nstr;
2_41 
					cstr: String := "<tr><td><pre>" &
2_42 
					                Html_Anchor(name_str => nstr, href_str => hstr,
2_43 
					                            class_str => "line_no",
2_44 
					                            text_str => content) & " </pre></td>";
2_45 
					o: Elem_Array := String_To_Raw(cstr);
2_46 
				begin
2_47 
					Write_Octets(fname => fname, data => o, append => append);
2_48 
				end; -- line_no
2_49 
			when line_del | line_add | line_keep =>
2_50 
				-- content as relevant, will be html-escaped
2_51 
				declare
2_52 
					cstr: String := escape_html(content);
2_53 
					s : String := "<td><pre class=" & cls & ">" &
2_54 
					              cstr & "</pre></td></tr>";
2_55 
					o : Elem_Array := String_To_Raw(s);
2_56 
				begin
2_57 
					Write_Octets(fname => fname, data => o, append => append);
2_58 
				end; -- line_del|add|keep
2_59 
			when hunk_hdr =>
2_60 
				-- content as relevant, assumed html-safe
2_61 
				declare
2_62 
					s : String := "<tr><td colspan=""2""><pre class=" & cls & ">" &
2_63 
					              content & "</pre></td></tr>" & lf_str;
2_64 
					o : Elem_Array := String_To_Raw(s);
2_65 
				begin
2_66 
					Write_Octets(fname => fname, data => o, append => append);
2_67 
				end; -- others than patch or line_no
2_68 
			when others =>
2_69 
				-- content as relevant, assumed html-safe
2_70 
				declare
2_71 
					s : String := open_str & content & close_str & "<br>" & lf_str;
2_72 
					o : Elem_Array := String_To_Raw(s);
2_73 
				begin
2_74 
					Write_Octets(fname => fname, data => o, append => append);
2_75 
				end; -- others than patch or line_no
2_76 
		end case;
2_77 
	end Write_Class;
2_78 

2_79 
	procedure Write_Tag( tagname: in String;
2_80 
	                     opening: in Boolean;
2_81 
	                     fname  : in String;
2_82 
	                     append : in Boolean := True) is
2_83 
	begin
2_84 
		if opening then
2_85 
			Write_Octets(fname => fname, append => append,
2_86 
			             data => String_To_Raw("<" & tagname & ">"));
2_87 
		else
2_88 
			Write_Octets(fname => fname, append => append,
2_89 
			             data => String_To_Raw("</" & tagname & ">"));
2_90 
		end if;
2_91 
	end Write_Tag;
2_92 

2_93 
	---------------own utilities and varia
2_94 

@@ -95,7 +95,8 @@
2_95 
	function escape_html(src: in String)
2_96 
			return String is
2_97 
		-- html characters to escape and correspondence function
2_98 
		html: constant Character_Set := To_Set("<'>""&");
2_99 
		-- round brackets are escaped to avoid footnote interpretation
2_100 
		html: constant Character_Set := To_Set("<'>""&()");
2_101 
		function To_Html(c: in Character) return String is
2_102 
		begin
2_103 
			if c = '<' then
2_104 
				return "&lt;";
2_105 
			elsif c = '>' then
2_106 
				return "&gt;";
2_107 
			elsif c = ''' then
2_108 
				return "&apos;";
2_109 
			elsif c = '"' then
@@ -108,6 +109,10 @@
2_110 
				return "&quot;";
2_111 
			elsif c = '&' then
2_112 
				return "&amp;";
2_113 
			elsif c = '(' then
2_114 
				return "&lpar;";
2_115 
			elsif c = ')' then
2_116 
				return "&rpar;";
2_117 
			else
2_118 
				return "" & c;
2_119 
			end if;
2_120 
		end To_Html;
2_121 
		-- count for final max length of the string
2_122 
		plus: Natural := Count(Source => src, Set => html);
2_123 
		--lt,gt add only 3, amp 4
2_124 
		maxlen: constant Natural := src'Length + plus*5;
2_125 
		result: String(1..maxlen);
2_126 
		pos: Natural := result'First;
2_127 
		idx, len: Natural;
2_128 
		from: Natural := src'First;
2_129 
	begin
2_130 
		-- loop and copy from src
2_131 
		while from <= src'Last loop
2_132 
			idx := Index(Source => src(from..src'Last), Set => html);
2_133 
			exit when idx = 0; -- nothing found
2_134 
			-- write to res html sequence for src char and advance in src
2_135 
			declare
2_136 
				hs: String := To_Html(src(idx));
2_137 
			begin
2_138 
				-- any characters before the one to escape
2_139 
				len := idx - from;
2_140 
				if len > 0 then
2_141 
					result(pos..pos+len-1) := src(from..from+len-1);
2_142 
					pos := pos + len;
2_143 
				end if;
2_144 
				-- escaped character
2_145 
				len := hs'Length;
2_146 
				result(pos..pos+len-1) := hs;
2_147 
				pos := pos + len;
2_148 
			end;
2_149 
			-- advance in src 
2_150 
			from := idx + 1;
2_151 
		end loop;
2_152 
		-- copy any remaining content from src
2_153 
		if from <= src'Last then
2_154 
			len := src'Last - from + 1;
2_155 
			result(pos..pos+len-1) := src(from..from+len-1);
2_156 
			pos := pos + len;
2_157 
		end if;
2_158 
		return result(result'First..pos-1);
2_159 
	end escape_html;
2_160 

2_161 
	function Html_Anchor( href_str: in String;
2_162 
	                      text_str: in String)
2_163 
			return String is
2_164 
	begin
2_165 
		return "<a href='" & href_str & "'>" & text_str & "</a>";
2_166 
	end Html_Anchor;
2_167 

2_168 
	function Html_Anchor( name_str: in String;
2_169 
	                      href_str: in String;
2_170 
	                      text_str: in String)
2_171 
			return String is
2_172 
	begin
2_173 
		return "<a name='" & name_str & "' href='" & href_str &
2_174 
			"'>" & text_str & "</a>";
2_175 
	end Html_Anchor;
2_176 

2_177 
	function Html_Anchor( name_str : in String;
2_178 
	                      href_str : in String;
2_179 
	                      class_str: in String;
2_180 
	                      text_str : in String)
2_181 
			return String is
2_182 
	begin
2_183 
		return "<a name='" & name_str & "' href='" & href_str &
2_184 
			"' class='" & class_str & "'>" & text_str & "</a>";
2_185 
	end Html_Anchor;
2_186 

2_187 
	-- returns the html string that opens an html element of given class
2_188 
	function Html_Open( class: in html_class )
2_189 
			return String is
2_190 
	begin
2_191 
		return "<span class='" & To_Lower(html_class'Image(class)) & "'>";
2_192 
	end Html_Open;
2_193 

2_194 
	-- returns the html string that closes an html element of given type
2_195 
	function Html_Close( class: in html_class)
2_196 
			return String is
2_197 
	begin
2_198 
		case class is
2_199 
			when line_no =>
2_200 
				return "";	-- special case as line_no is <a> and closes itself
2_201 
			when others =>
2_202 
				return "</span>";
2_203 
		end case;
2_204 
	end Html_Close;
2_205 

2_206 
end HTML_IO;

If you think perhaps that the above is “too long” given the small actual change, note that the impact of even a small change is not something that the machine can really evaluate in any meaningful way. As a consequence, VaMP simply provides as much context as it finds to one change and that means the whole file that is affected. If anything, I count this as a plus, since it even adds some very healthy incentives: every change to existing code is quite expensive for readers and users as it requires a re-loading of a potentially wider context and having at the very least the whole file to re-read for any proposed change is a good reminder of this; all the better if this also pushes one to keep code files small and clear enough so that such publishing of a patch does not result in a huge thing that nobody bothers with; finally, this is likely to penalize (correctly) huge patches as well as messy codebases since then any change touches a lot of files and so the resulting html-view of the patch balloons to include possibly most of the code, each and every time – hopefully until the codebase is finally structured more sanely.

Obviously, the above incentives are only that – they can’t force anyone to change anything and one can always simply avoid the trouble thus uncovered. For instance, one can always choose and publish only excerpts rather than the full thing, since VaMP does not force nor is it intended to force publication of anything – it simply facilitates and provides all the required support to make it very easy indeed for code writers to publish their *writing* as such, and for code readers or publishers to reference and discuss a proposed change. This is exactly as it should be, since on one hand there can be valid situations when partial publishing is the most that can be done without violating other constraints of the wider context and, on the other hand, there is no imposition on the user to publish or not publish anything, only an additional provision and a better alignment of incentives.

In short, this latest improvement of my versioning tool helps with publishing too and precisely in the best possible way: automating the useful but tedious part of the task and thus improving my efficiency significantly. Yet again.

  1. For reference, here’s how the relevant part of the css looks like, at the moment:

    /* for html view of code patches */
    .patch {background: Beige}
    .code_table {
    	background-color: LightYellow;
    	border: none;
    	font: 1em 'Courier New', Courier, Fixed;
    }
    .code_table td {
    	border: none;
    	padding: 0;
    	margin: 0;
    }
    .code_table tr {
    	border: none;
    	padding: 0;
    	margin: 0;
    }
    .code_table tr:nth-child(even) {background: LightYellow}
    .code_table tr:nth-child(odd) {background: Beige}
    .code_table pre {
    	word-wrap : break-word;	/* IE 5.5+ */
    	white-space: pre-wrap;	/* css 2.1 + */
    	white-space: -moz-pre-wrap; /* mozilla... */
    	white-space: -pre-wrap; /* various Opera versions */
    	white-space: -o-pre-wrap;
    
    	padding: 0;
    	margin: 0;
    
    	tab-size: 2;
    	-moz-tab-size: 2;	/* mozilla is special... */
    	font: 1em 'Courier New', Courier, Fixed;
    }
    
    .code_table a {
    	color: grey; text-decoration: none;
    }
    .dir_del, .file_del, .line_del {
    	color: red; text-decoration: line-through;
    }
    .dir_move, .file_move {
    	color: brown; text-decoration: none;
    }
    .dir_move, .dir_del, .dir_add {
    	font-weight: bold;
    }
    .file_keep, .line_keep {
    	color: grey; text-decoration: none;
    }
    .file_change {
    	color: blue; text-decoration: none;
    }
    .dir_add, .file_add, .line_add {
    	color: blue; text-decoration: none;
    }
    

    []

May 5, 2022

VaMP’s Code-Centric Visualization or Putting Patches in Their Place

Filed under: Coding,VaMP — Diana Coman @ 2:32 pm

Scratching that itch of a more useful visualization for a given set of patches, I’ve added to VaMP a view aimed at the more important people in a patch’s life: its readers! This new view focuses on how a code evolves when/if various paths of patches are pursued (or not!), showing the different possible states of the whole codebase and how they are linked through patches. As a result, this new, code-centric rather than patch-centric view helps the reader to place a patch in its context, easily gain some idea as to its role as part of a whole and know at a glance where to start looking for the relevant code context beyond what the patch itself includes. By contrast, the legacy view focused on how the patches were related to one another without much regard for the code as a whole at any given time 1. In short, the legacy view is what the *machine* needs in order to link patches correctly, while the new view is what supports *human* comprehension of a codebase as a whole, carving quite explicitly and one small step at a time, a place for people to contribute and collaborate, supported by machine automation but not replaced by it in any way.

Another way of describing the new visualization is that it puts patches where they belong: as links between two states of the codebase and as such merely potential paths (to take or not) or even alternatives to pick from, but certainly never some sort of central focus or all-important parts on their own. Yes, this view pushes the reader’s needs and the codebase *as a whole* to the forefront at all times, while relegating changes to the code aka patches (and their writers) to a more humble and supporting role, to better reflect reality: any changes to code are at all times merely proposals and should be seen as such, not as impositions 2 and all patches effectively compete with one another for readers’ acceptance but no patch is ever all that important on its own or even in a group, whether that group is shaped like a tree or not. A patch becomes important (or not) through its readers, not its writer(s) and informed readers need more context than the very narrow and limited part that may be included in a patch.

As illustration, have a look at how the same set of patches is shown below, first in the legacy view (patches as nodes of the graph and arcs unlabeled) and then in the new, code-centric view (codebase states as nodes of the graph and arcs labeled according to the patch that they represent):

vampviews_2_640.jpg
Above: legacy, patch-centric view focused on dependency relationships between patches: patches are nodes and arcs don’t have any meaningful labels.

vampviews_1_640.jpg
Above: new, code-centric view focused on the evolution of the whole codebase through the application of different patches: states of the codebase are nodes and patches are the arcs.

While most of the trees flow quite neatly even in the first image above due to VaMP’s strict guarantees, there are at least two spots in there that look dubious at least: the first is the crossing dependencies between client_cooldown.shortcut, client_cooldown.patch, client_unite.patch and client_cleanup.patch; the second is the keksum tree that seems split into two components that are not linked in any way. If you check however these same parts in the second image above, aka the code-centric visualization, you’ll get some better idea of what happens in fact to the code in each case. The two client patches (client_cooldown.shortcut and the client_cooldown.patch) perform a merge of two different branches of code, while the two “components” of the keccak tree represent in fact alternative paths of the same release!

None of the above is clear in the legacy view though, simply because there is no way to even show in there anything about the prerequisites of a root patch (implicitly assumed to be an empty directory, as if that even made much sense) or the results of a leaf patch (implicitly assumed to be fully defined by the sequence of patches leading to that leaf but pushing the burden of any actual checks on to the user). Since VaMP is by design loudly explicit, rather than quietly implicit, it can also show in the code-centric view both pre-requisites and results of any patch, whether root, leaf or anything in between. As a further gain, the user of the visualization can even add helpful labels to each state of the codebase so that the whole becomes more readable indeed and the names of the patch files don’t end up as the sole providers of anything human-readable in the whole graph. The states of the codebase are uniquely identified and listed conveniently in a text file that the user can change as they see fit, with VaMP helpfully preserving any given labels between subsequent runs and otherwise providing some default labels where the user doesn’t care or hasn’t yet provided anything else.

Moving further, I plan to expand on this to further support reading, comprehension and discussion of patches in their full context. This code-centric view has been already very useful for me to get an initial overview of any set of patches but I see it otherwise as only a first and still very limited step towards a more human-friendly way of interacting with patches so that the incentives for balanced collaboration are correctly aligned for all levels of writers, readers and publishers of patches, too.

  1. This was due first of all to the limitations of the older “V” which had no notion of a whole codebase as such, nor ways to provide any guarantees as to the output of a patch. VaMP does not suffer from such limitations, so it can and does push for a more useful visualization, too.[]
  2. Whether under the guise of “security updates”, “must-have upgrades” or something else, the currently widespread practice really is built precisely on the idea of forceful imposition of any code changes. Not that there’s anything inherently wrong with enjoying imposition either, if that’s what you like. Just call it by its name instead of pretending it’s something else, don’t expect everyone else to have the same enjoyments as you and, even more importantly, don’t try to discourage the young from even finding out that there are valid alternatives to the path you are on yourself.[]

April 19, 2022

VaMP’s Basic Requirements for Valid Files and Directories

Filed under: Coding,VaMP — Diana Coman @ 3:00 pm

Given a directory 1 as input, VaMP will loudly complain and promptly exit if it finds any invalid files or directories in it, meaning specifically any of the following: empty files, duplicate files, non-ordinary files, files not ending with a newline, non-hierarchical structure of directories (for instance via a symlink that creates a loop on any level), empty directories. While some might find VaMP to be therefore quite picky or even *too* picky about what it accepts as valid input, there are informed reasons (see below) for everything included in that list of refused items and this makes all the difference: VaMP is not picky but discerning and in the most helpful way, too, as its explicit requirements enforce and help maintain a clean structure and the clarity that comes with it.

Why no empty files?
Because empty files are worse than meaningless: they are, by definition, void of content, pure form if there ever was such a thing. First of all, if a file is empty, there is nothing to include anyway, so there’s no loss to delete it, is there? Second, since VaMP is concerned with *content*, it follows quite directly that files lacking any content whatsoever are not a valid input for it.

Why no duplicate files?
Because there’s no acceptable reason to duplicate *content* rather than reference it in a civilised and considerate manner. And there is a high cost to duplicating content, made all the higher for it being generally paid at a later time and by someone other than the person lazily copying instead of appropriately referencing. Yes, VaMP is by design anti-copying and pro-referencing and I firmly intend it to remain this way.

Why only ordinary files?
Because in the “everything is a file” model, this is the only currently available means – if a feeble and unreliable one – for marking in any way the intent of focusing on text meant to be read and comprehended by people first of all. Ideally this filter would be stronger to exclude directly binary files for instance but the reality is that there is no reliable way for the machine to decide 100% accurately on what is “binary” and what isn’t: from the machine’s point of view, *all* content is binary anyway and so it’s always and out of necessity, the user’s decision to make.

Why only files ending with a newline?
Because a file not ending with a newline is not a valid file according to the very definition of the “file” format 2. Moreover and in more practical terms – VaMP always creates correctly formatted files and as a result, whenever it applies a patch, it *will* end the file with a newline, meaning that you risk ending up with a different file just because the “original” was an invalid file to start with. It’s not VaMP’s job to correct files nor is it desirable that such correction occurs silently anyway.

Why only strictly hierarchical directories?
Because any non-hierarchical structure in the given context is utterly broken and ultimately confusing for someone trying to read and understand the content. VaMP is firmly pushing for clarity and meaning at all levels and this starts with an unambiguous structure of the given directories, with as many levels as you require and can handle perhaps but certainly *without* any loops. If your content requires for whatever reason such horror as loops in *how the directories or files are grouped together* then I dare say you have bigger problems to sort out first before worrying about VaMP at all.

Why no empty directories?
Because empty directories are not content and so don’t belong under VaMP. Note that a directory containing only other directories but no files is still considered to be empty and thus rejected by VaMP. The reason for this is that content is in fact strictly stored in files, while the whole set of directories (hence, paths) is merely a temporary mapping of content into some structure that is designed – hopefully – for aiding comprehension. As such, a path that doesn’t lead to a file is worse than meaningless as it is a burden on the reader, since it adds complexity without being justified by any part of the existing content. Certainly, it can and it does happen that the content justifying that part of the structure is simply not yet available but in this case, the correct options are to either collapse the structure until the content becomes available (thus *not* burdening the reader with it at all) or otherwise providing at least a placeholder file with a brief description of the intended content (thus providing at least a hook for the reader to hang that bit of added structure on, until such time when the full content is available).

More as a continuation than an ending, here’s an example run with complaints:

$ vamp diff oldver newver
STATUS: Diff-ing directories oldver and newver to file listing_oldver_newver.diff with hash length -1
STATUS: Entering Walk_Dir with dirname=t1
STATUS: Entering Walk_Dir with dirname=t1/t3
STATUS: Entering Walk_Dir with dirname=t2
STATUS: Entering Walk_Dir with dirname=t2/t4
STATUS: Entering Walk_Dir with dirname=t2/t4/t5
ERROR: empty files/dirs are not acceptable, sorry. Found to be empty:
newver/empty.file
newver/t2/t4
newver/t2
ERROR: VaMP main: Directory newver contains duplicates and/or empty directories and/or special files that are not acceptable, sorry. See the list(s) provided. Kindly clean these up and run VaMP again.

$ tree oldver
oldver
├── manifest.vamp
└── t1
    ├── file.b
    └── t3
        └── file.a

2 directories, 3 files
$ tree newver
newver
├── empty.file
├── manifest.vamp
└── t2
    └── t4
        └── t5
            └── file.a

3 directories, 3 files
  1. Note that the content of this can be anything whatsoever: as long as the content and its authors are important to you, you’ll benefit from having it under VaMP. “Code” is at most a *subclass* of text, not the other way around and as such, the first and foremost requirement for it should be that it’s clear and readable and that its authors are people you actually trust as competent and reliable for the task, as per your definition of trust, competency and reliability.[]
  2. This also means, of course, that an “empty file” is even more nonsense than mentioned already since it doesn’t even match the format requirements to be called a file in the first place.[]

March 21, 2022

Two Days in Bath

Filed under: Lyf,Tgdyk tgdyk — Diana Coman @ 1:19 pm

On an unexpectedly sunny day at the very end of February, we jumped on a train and headed for Bath – a small town that shares with Reading the same straightforward approach to naming and relatively little else otherwise. One short hour away to the west of Reading, the building stone turns from mostly red to pale yellow, famous names and people are pushed to the forefront quite literally at times (the Roman emperors are made to guard the baths in statue form while Jane Austen guards the pavement in lifesize puppet shape), the architecture turns ambitious and claims high pride while nevertheless selling itself as much as it can. And everything gets otherwise quite tightly packed in the very centre of the relatively small town, despite there being otherwise seemingly enough space around, especially on the lovely hills that gently surround it all.

In the very centre of the tourist trap, the Bath abbey stands as the most massive side of a surprisingly small square, with the actual Roman baths that gave the town its name rather crowded and effectively built over for show, to its left. The abbey itself is the relatively usual Gothic affair, weather-eaten on the outside but well preserved, clean and even shiny on the inside. If anything, it’s perhaps less austere than some other churches around here, as it sports quite a few panels of stained glass – vividly colourful at least, even if nothing special otherwise. Outside, on the front of the abbey, there are chipped angel figures running up and down the ladders to Heaven and if some of them have tumbled down head first, it doesn’t seem to matter in any way. Inside, there are neat stone fans running across the whole ceiling and a sparkling shiny organ presiding over it all. There’s a whole lot more shiny and sparkly applied rather liberally and seemingly indiscriminately to altar cloths and the like, fitting at least the child’s current taste in decorations. Basically it’s all like a bigger and better Christmas tree from his point of view and I’d say it’s a valid way to look at it all, too:

bath2022_1_640.jpg
bath2022_40_640.jpg
bath2022_41_640.jpg
bath2022_42_640.jpg
bath2022_39_640.jpg

To the right of the abbey, there’s a row of souvenir and gifts shop, while to the left there is the complex built on top of the former Roman baths. To some extent it fits perhaps with the rest at least, as there is some overall shape to it all and if I don’t find it to be Roman in the least, it’s possibly simply that I’m asking, as usual, for what it once was or at least for what remained of that instead of any ersatz. To a tiny extent, I get at least a bit of my wish: deep down and literally under the whole of what seems at first look to be the baths (apparently the street level in Roman times was quite a few meters below the current street level), there are still the bits and pieces that endured somehow through all the successive stages of use, disuse, abuse, reuse.

Such pieces as were found and otherwise the outlines and general designs of the rooms themselves are quite well presented and shown together for the best effect with a clear aim to give as much as possible an idea of the life in and around the settlement rather than narrowly focusing on the functioning of the public baths. People threw coins into the water, then as now, and wanted their names and station remembered if at all possible, then as now. Some came to the baths to bathe, some to steal, some to ask the gods for the return of stolen items and for the punishment of the suspected or even the strongly-believed-to-be-thief. Possibly the only difference between the papers left today in the church’s box and the tablets left back then at the old temples is one of tone and essentially extent of allowed freedom of speech – the old gods were apparently less restrictive, accepting requests for both blessings and curses, allowing just about any tone one cared to use. Overall though, then as now, when confronted with a problem they couldn’t solve themselves, people appealed to some greater power and at least at times, the wording of such appeals suggests they quite expected their appeal to be effective indeed, regardless of anything else.

bath2022_3_640.jpg
bath2022_2_640.jpg
bath2022_37_640.jpg
bath2022_36_640.jpg

bath2022_34_640.jpg
bath2022_35_640.jpg

Despite the disappointment of that ersatz of a building with a gallery of added statues of emperors put on sentry duty at the public baths on top of it all and despite the annoying abundance of shiny red interdictions to touch or have anything to do with the water on show (which is indeed rather uninvitingly greenish, apparently due to algae that are entirely a problem of the modern setting, not at all an artefact of the original baths), the part underground, where one finally gets closer to the remains such as they are, was worth seeing. And if anything, it’s probably the merit of the detailed attempt to set the found remains within a wider context that there was indeed some longing to be able to walk through the remains such as they were rather than through the later reimagining of “something Roman” while utterly ignoring at that what was even known of the original setting – if only they restored the original design that had been functional, too, not meant only for show (it even had statues, at that, only they were those of the gods, not of emperors but in those times even the gods were closer apparently to mere mortals for their statues were actually in the water, not looking on from high up). Still, for all the Greek inscription carved in the stone of the later-day building turned central restaurant, the original baths, temple and the whole settlement or town itself seem to have been quite an interesting blend of everything really, with the local and the Roman gods linked together into the Sulis Minerva name, with visitors and workers from as far as the Levant, with a temple pediment that features a male face of Minerva and a mixture of symbols – though not even a trace of Greek writing whatsoever:

bath2022_38_640.jpg

Slightly off-centre, inside the Victoria Art Gallery, a few beauties in white marble venture forth, seemingly in an attempt to escape from the awful combination of a red fire sign, an iron central heater and the sash window background. One of them is bolder, the other one more cautiously peering around the marble column but both stuck in place nevertheless:

bath2022_22_640.jpg

Still close to the centre, there is the New Theatre Royal building with its balcony on top of a building that seems rather too small for such a big name. Not far away from it, a less squarish and taller building claims in carved stone a less royal although funnier name that tends to be around here the trademark of a Thai restaurant chain: the giggling squid.

bath2022_24_640.jpg
bath2022_27_640.jpg

bath2022_26_640.jpg
bath2022_25_640.jpg

Beyond the “must see” baths and abbey, the town’s point of pride is its georgian architecture. The Gay Street goes steeply up until it turns at the very top into the Circus – and once there, one realises that this fabled georgian architecture means in practice simply long rows of the same window repeated ad nauseam, whether in long parallel lines or in semi-circular endings capping the avenues. The desired effect is one of greatness and in a severely narrowed perspective, if I squint until my eyes hurt, I can just about see it. On long avenues, there is at least the pleasant effect of perceived abundance of space but funnily enough, for all the clearly desired uniformity of this architectural style, nature still refuses to play ball with it and turns it all instead in a marked play of opposing contrasts, one side basked in light while the other is submerged in the shadows. Moreover, behind the back of such streets, human nature plays even more roughly with it and sprouts such a huge sprawling of mismatched everything as if to fully counterbalance the pretense of perfect uniformity that the facade holds so dear. Oh, and on a side note, let it be said also that the Roman plumbing at the baths is still satisfactorily working today, while the phrase “georgian plumbing” was used disparagingly by every restaurant owner that I met while in town 1.

bath2022_19_640.jpg
bath2022_17_640.jpg
bath2022_18_640.jpg
bath2022_15_640.jpg
bath2022_16_640.jpg
bath2022_20_640.jpg

On a side street, one of the windows in a row holds however a bit more behind it than the rest – the house is where a German called Herschel settled at first to give music lessons and ended up in quick order building telescopes, discovering new planets and speculating on the composition of nebulae. As a result, the world nearly ended up with a planet called George (a kingly name, don’t scoff at it!) but in the end it all worked out for the best – Herschel got the king’s attention and with it funding to further pursue his astronomy interest where he made more advances than in his music career and the planet still got in the end a name more in tune with the other planets’ names: Uranus. On a side note, it was in this museum that I found out just why exactly is an orrery called that: because it was the Earl of Orrery who commissioned the first such thing to be made, as simple as that. On the other hand, I still have no idea why was the title itself called “Orrery” since the earldom was of Cork and the surname was simply Boyle. Supposedly there is some older Gaelic word linking it all to some meaning but it’s all getting rather very fuzzy indeed from this point on so I’ll leave it at that and be thankful that it wasn’t the Earl of George to commission that first model of the solar system.

bath2022_32_640.jpg
bath2022_33_640.jpg

Leaving aside the baths, the circus and the neverending rows of windows, the town’s buildings tend to be relatively squarish although retaining some of the Roman villa style at times, quite often with a rather pleasant effect. Some have rounded corners with ornate carvings and even cleaner stone that makes it all look quite pretty indeed.

bath2022_13_640.jpg
bath2022_31_640.jpg
bath2022_5_640.jpg

A bit further away from the abbey, standing at a three-roads intersection of sorts, there’s a more slender church with a narrow spire and the best church door handles that I ever saw, basically a depiction of saints in such a genuinely alive manner that it made me think yet again of Caravaggio and his futile quest to get official recognition for genuine life representations:

bath2022_4_640.jpg
bath2022_14_640.jpg
bath2022_23_640.jpg

Besides the above door handles, the church has a rather puzzling but fitting name: Saint Michael Without. The clue to the puzzle is in the older meaning of without – not as much a lack of something as merely a positioning by contrast to within, meaning thus simply outside of the town’s walls, because apparently at the time when it was built, this church was indeed outside the official walls. Fitting handles therefore, I should think, with the two saints not as much concerned with their sainthood as rather humorously pointing to one another their respective interests, it seems to me. Judging by the spear held by one and the book held by the other, I’d guess them to be St. Michael and St. Paul but first of all they seem to me like a pair of good friends who care for one another even though they have quite different approaches and interests: teasingly if good naturedly pointing out what they each perceive to matter most, while willing to look at least at what the other is pointing at, even if not really wishing to touch it. Still, for entering the church, it sadly turned out that spear *and* book are not even enough – one needs a key too, so perhaps St. Peter should have joined in, as well.

Even further away from both the centre and the former “without” area, the streets open up to the surrounding greenery and there is an even more peaceful air to it all. We walked around the town several times to the point where we knew our way without any map and if benches ended up in the pictures, too, it’s simply because they were at the right place to have a break, nothing more than that. Other than benches though and to my pleasant surprise, we even found birch trees right in town and close to the river. And in the rather small area called the botanical garden, there was a trunk carved as a human figure – without arms, it is true, but what would he need the arms for, anyway?

bath2022_11_640.jpg
bath2022_12_640.jpg
bath2022_21_640.jpg
bath2022_28_640.jpg
bath2022_29_640.jpg

  1. Speaking of restaurants, we found this Italian place that could have equally been in Napoli for all one knew once inside. Everything, from food to setting and people were as authentically South Italian as it gets and combined with the sun shining through a skylight that showed, dust and dirt notwithstanding, a whole jumble of inner courtyard architectural outgrows that would have been perfectly at home in Rome, it all had the predictable effect of my talking switching at times to Italian before I quite knew it – not that anyone complained of it at all. The child didn’t care much for language or for setting but was utterly delighted with the food and even more so with the gelato, of course.[]

March 5, 2022

The Chimera of Perfection, the Beast of Worse, the Unnamed Other

Filed under: Sense and nonsense — Diana Coman @ 4:33 pm

Jacob Welsh: Where do you think the Worse is Better approach falls between the two poles you describe? The current state of things seemed to me largely the inevitable result of the subsequent two decades’ continuing dominance of exactly Gabriel’s recipe, and for the reasons he described. Perhaps on the first take I confused it with “being practical”; and I found it repulsive although I could not refute it. Kind of like the “network effects” thing (looks like the continuation of that thread was shortly after the Young Hands closure, perhaps I should bridge it in).

Diana Coman: Reading that Gabriel piece you linked, I admit that…. hm, I found it quite painful to read because I can’t really stand *either* of the approaches he describes. I suppose it can be simply because I’m actually more extreme than all extremists (only I care less to shout/argue about it really) but I suspect the difference really is one of more fundamental approach. I might need to give it some more thinking and a write-up to make it clear.

This is part of the write-up promised above. That suspicion of mine turns out to be quite true (and the supposition possibly not entirely false either!) – only it took first of all a lot more (re)reading of Richard P. Gabriel’s books and references 1 before I could start to get even as little as just a glimpse of what that difference might be, as it goes deep indeed and it spreads also into a whole web of roots before any of it shows out in the open, directly exposed to be looked at.

In a very compressed nutshell that threatens anyway to spill and grow not into a single tree but into a whole jungle at the very least, I think that software is essentially a cultural artefact rather than an industrial product and this means that both its impact and its generative process are intertwined and very far indeed from being adequately captured by any linear (whether iterative or not, piecemeal or not) model of mere patterns, recipes, methodologies or even neatly predictable at every step frameworks. Essentially, the generative process is fractal in nature. As a result, approaches don’t have just a straight line on which to position themselves and what might seem wildly different steps when looked at from close-up or over a short-term interval, can predictably converge nevertheless to results that share crucial characteristics to the point where their differences -such as might still be found at a very close look- are in fact irrelevant.

Software being a cultural artefact goes both ways and in quite the precise manner, too – just as software impacts and transforms the wider social environment of its time, it is also influenced and constricted by it so that the observed patterns or shapes of successful software or even those of its development process are more likely to reflect and be restricted by wider patterns than merely those of the domain itself, let alone even finer grained ones such as those supposedly imposed through direct management. The exact way in which the broader patterns get reflected and find their expression in the software domain is not random either, nor is it based on either direct copy or just a broad and imprecise, seemingly haphazard similarity. Instead, the similarity is that of the fractal nature 2 and as such, any attempt to convincingly model (and thus predict correctly) software development in a lasting way will have to find the correct mix of chaos and order or perhaps, at the very least, some sort of clever distillation of its core into something useful, a la DS.

There’s a big gap indeed between patterns, methodologies and even complex industrial processes on one side and fractal modelling (such as it exists currently) on the other. Perhaps more of a chasm even rather than a mere gap – it is after all nothing less than moving from the neatly intuitive world of low integer dimensions to the bewildering world of non-integer dimensions. This is at the very root of why I perceive both “the right thing” and the “worse is better” approaches 3 as merely variations of the same failure mode rather than alternatives in any meaningful sense: they both have in common an ultimately sterile, too narrow, even too linear at times focus, be it on some illusory ideal correctness in the first case or on some equally illusory ideal simplicity in the second case. The existing attempts at improvement, even when they go beyond the strict linearity of early models, still fail to address the root cause because their informing worldview conceives only of integer dimensions. And all the while, life teems instead beyond the decimal point.

From a more practical point of view, the narrow focus on an ideal, theoretical correctness fails in the marketplace for the very reasons that Gabriel identifies from his direct experience 4 and I’ll add to that only one piece of my relatively recent experience with just one instance of why and how theoretically wonderful ideals that are however practically untenable can literally turn even a valuable concept into a worse than useless software product. Note though that the trouble doesn’t stem from *correctness* itself but from a narrow and too rigid focus on it that fails first of all to distinguish what truly matters from what doesn’t and then to take into account the much more complex and less ideal constraints that real world use imposes nevertheless. This is why I consider this approach simply misguided at core – it’s correctness wrongly applied that ends up sterile, not correctness per se.

Essentially, the narrow focus on a theoretical correctness, sometimes dubbed “the right thing” approach, chases the chimera of perfection as if perfect can ever apply to a live (hence, evolving) artefact existing in the real world. Like all products of the imagination though, such chimera can be indeed very attractive to contemplate or even to work towards, since it has, for as long as it lasts, the powerful allure of the ideal compounded by the unlimited freedom of imagination to pick and choose what it likes, to ignore what it doesn’t want to handle. And it can be certainly made to seem entirely real and worth pursuing for a while, usually while there are still resources coming in from outside to support the chase. Sooner or later though, chaotic reality with its various messy parts including all sorts of different and even conflicting requirements and priorities catches up with it and the ideal turns out to be indeed neither possible in reality nor quite that easily adaptable at this juncture to it. As a result, whatever comes out of this approach tends to fail to thrive and survive (meaning further evolve rather than merely existing), dieing perhaps as a result of an overdose of order and structure or, looking at it from the other side, starved for lack of chaos.

If, however, one is so dispirited by such failure or so hungry for the sheer vital force that is indeed plentiful in chaos to abandon order and structure entirely and let chaos take full hold, the result is but a primitive beast, the most pedestrian interpretation of the “worse is better” argument. Such beast as might come out of chaos without much structural guidance at all is undeniably alive and even quite fascinating perhaps, especially for as long as it’s still small enough so that some amount of taming is still possible and thus some use can be extracted out of it. But its chaotic nature means first of all that, as it gets bigger, it becomes increasingly difficult to control or handle at all, let alone grow or even merely steer in some specific direction that doesn’t happen to match its inclination 5.

As internal control becomes increasingly (and even non-linearly so) difficult, the focus necessarily shifts to controlling the environment instead and this is indeed more easily achieved at this juncture, nevermind that such control is spelling death in the longer term 6 as it is stifling and draining any value out of the environment instead of adding to it. The money accumulates just as the vitality drains 7 and there is then no choice but to press forwards and keep getting bigger through destruction of anything and everything else, through the consumption of anything that exists or that still finds a way to grow on its own 8. Instead of creating anything, the overgrowth of internal chaos and external control merely sterilizes and otherwise consumes – currently this consumption process is generally dubbed “acquisition” and it usually targets startups that supposedly win whatever is paid for them but lose in fact not just any value that they had but even the very possibility of having a value or just a different approach of their own at all. Perhaps it even is a good deal for the startups or at least for those that never thought or stopped thinking that they had any other chance to matter, anyway.

Looking again at my notes from reading the “Patterns of Software” book and the set of “worse is better” essays by Gabriel, what strikes me most is how often my observations and questions either directly predict what turns out to follow a couple of paragraphs further or otherwise keep pushing for the broader context and at least a glimpse of a model of what is talked about, instead of just a collection of patterns. Arguably this is part and parcel of that fundamental difference of approach that I was noting above: I am always and forever apparently aiming to model something (meaning to understand and integrate it fully to the point that I can then reliably *predict* it, in other words generate it) and never fine with merely describing and cataloguing it, no matter in how much detail. At the same time, both Richard P. Gabriel and Cristopher Alexander, the original architect of the patterns approach, seem to state repeatedly that it’s precisely the “generative” approach that they are aiming for and fail to achieve satisfactorily in practice.

Perhaps I’m missing something (and especially for Alexander’s work, there is still a lot of reading that I need to do before I have something more specific to say about it) but to my eye there’s quite a big and obvious missing link between describing something as observed (even across many different instances in various environments) and modelling successfuly its underlying, generative process. Extracting the common observed core is one approach useful for generalization, certainly but I don’t think it’s all that often enough for making that next step of modeling the process that resulted in the observed artefacts. Possibly the focus on descriptive patterns identification, definition and matching is in itself a mark of Gabriel’s background in AI but for me it seems yet again uncomfortably close to that overspecialisation and overfitting, too narrow redefinition of success even, that I railed against and refused to go with, not so very long ago, despite any and all “common consensus” or “how things are done” or even apparent simplicity considerations. That choice of mine was extremely satisfying, very fruitful both in terms of concrete results and as a learning endeavour 9 and the parts publicly documented on this blog are just that, only parts of a much bigger, working whole that exhibits precisely the sort of quality that proves so elusive (for a good, underlying reason, I’d say) when following the patterns-matching branch: it’s generative and fully capable of carrying meaning too, when embedded in an environment designed on the same fundamental principles. This is neither an accident nor specific to computer graphics or online games but flowing directly from what modelling is and how it works.

Coming back to the question that prompted this article, if neither the chimera of perfection nor the beast of worse truly appeals, the unnamed other is yet to fully spring out from that very nutshell I mentioned earlier. Perhaps a more palatable (hence, practical) description of what that nutshell holds is that software requires a discerning, integrative and generative approach rather than a narrow focus. Discernment is crucial as it’s the only way to identify what matters and without such a correct identification, everything that follows is already doomed to fail. Integration is required for growth, properly speaking and it should be a flexible rather than fixed approach, bringing together different parts that maintain their character and their own capability to further evolve, quite a different thing altogether from the rigid and constricting approach of separated objects, containers and the like, while also, at the higher level, very different indeed from that devouring approach of “acquisition”. Generative means that the whole maintains at all times that balance between sufficient structure to support and enough chaos to enable new and even unexpected things to appear. These are not simple requirements and they don’t work in isolation either. This is why I think that what is needed is not just some new development method as such but an environment to match, with a guiding, principled structure that supports and even causes as wild variety as possible followed then by selection and filtering. Note though that such selection and filtering are not meant to be restricted to the usually binary choice of yes/no, dies/lives. Selection and filtering should allow and even mean the much more variety-friendly choice of continuous readjustment of relative positions and relationships.

On the very bright side, I think that the necessary parts for all the above are in fact already available and what it takes as next step is putting them all together and to practical use. Hence my previously unexamined calling of that unnamed other approach that I’ve been already using in practice for quite some time as simply… being practical 10.

  1. Yes, I was already aware of his most famous writings but the start of that awareness dates back to more than 10 years ago, when I was much younger and knew way less – and as I had encountered his writing mainly in a sort of second hand way, through experience with approaches and results that claimed to follow his direction but I found to be misguided at best (those catalogues of software patterns come first to mind and I don’t even want to go further with that recollection), I never really saw the point in digging deeper to the roots that apparently yielded such rotten fruit. Quite the example of why and how exactly the wrong publicity really is worse than no publicity at all because I think that his life experience is certainly valuable and despite being clearly, neatly and even entertainingly written and discussed in his books, it actually got more or less lost in the shadow of the sound bite that became… viral, indeed, quite ironically given its very topic.

    In any case, after a full read of his books on patterns and on open source, I’d say that one can perhaps disagree with his conclusions, interpretations and even approach (from what I gather even he still disagrees at times with himself!), as well as dismiss his advice or direction but only after taking in fully the solid and very relevant account of his experience in the field that both informs and makes his writing read as it does.

    As possibly always and everywhere, the sound bite is neither enough nor useful by itself and trying to pluck the results of experience without digesting at least the available account of that experience is just another form of misappropriation that results inevitably in sad and rotten fruit. The responsibility for such rotten fruit though is not with the original writing but with those who picked only the viral part out of its context and ran then blindly with it.

    []

  2. It is “the” and not “a” fractal nature. A breadcrumb to mark the entrance to this particular rabbit hole is in a footnote to a very compressed review of a very compressed film aptly called La Grande Belezza. And yes, I was indeed referencing exactly this, back when last summer ended.[]
  3. In fairness, from my reading of some of Richard P. Gabriel’s books and essays as published on his website (Innovation Happens Elsewhere: Open Source as Business Strategy, Patterns of Software: Tales from the Software Community, Worse Is Better, Worse is Better is Worse, Is Worse Really Better?), it seems to me that he has been aiming and even advocating for exactly a less narrow approach to software development, not at all for what turned up in practice even while quoting his essay as inspiration or source. In other words and in reply perhaps to Jim Waldo’s statement that “The classic essay on “worse is better” is either misunderstood or wrong”, I think that the classic essay is mostly misunderstood -and even misappropriated, I would add- rather than wrong.[]
  4. Read the last two parts of his “Patterns of Software book” and you’ll find it all there.[]
  5. I’m talking from direct experience with fully taming such a chaotic beast, not that I ever actually wanted to gain this sort of experience nor that it was what I had signed up for or even imagined programming might turn into. It’s still quite real and if you think that it isn’t so, I’m quite curious to hear about it so go ahead and leave a comment in that box below this article, please.[]
  6. Perhaps the discussion and illustration of a core trouble with economics without vision can prove helpful here.[]
  7. There’s a lot begging to be said on this point alone but for now I’ll merely add a single breadcrumb picked more by serendipity than anything else: vitality can be very easily perceived as “too much to handle” and it’s again a matter of and telling about the wider environment as a whole.[]
  8. This is how Microsoft ended up turning personal computers into a sort of semi-interactive television sets and Google ended up turning a vast library of knowledge into a giant advertisement panel and discussion of ideas into a mere popularity contest that bots are winning, too.[]
  9. Most of the past year’s articles on this blog would fit as reference for this and they don’t even capture it all, not even by far.[]
  10. On examination though, there certainly seems to be quite a lot more to this being practical of mine, since its attempted description doesn’t fit even by far in all the 3000+ words of this article (without even counting the references) and there are also quite a few directions that I didn’t even mention here, just to try and keep that nutshell reasonably compact and clear, hopefully.[]

February 16, 2022

Visibots, Ostrobots and a Bot Called Odoacer

Filed under: Dark Modern Ages — Diana Coman @ 11:56 pm

Around 1950, in the very early age of computers, Alan Turing split the ungovernable digital world along the fitting line of a test, into two parts: on one side the established inhabitants, unquestionably human; on the other side, the newly arrived computer programs (bots), held to prove themselves before a human authority that had the final, undisputed word on the matter. The Turing test consisted roughly in human judges called upon to identify the lonely bot potentially hiding among humans and trying to pass as one of them in this relatively new world of digital interactions. From Turing’s perspective and as enshrined in his test, bots were assumed to be the outsiders, humans the insiders and human interaction the most meaningful measure of everything else, a state of matters imported unexamined into the digital space directly as it had been deeply experienced in the more immediate, physical space, for as long as humanity remembers.

In the years since Turing’s test was first devised, Elizabots, Parrybots and even Googlebots made narrow and only partially successful incursions over the test line and into the human side. Comforted by the poor results of such incursions of the bot tribes, humans focused on the Turing test on its own as an impassable defense, an unassailable proof of their own superiority and thus their own supremacy in the world. Blinded by this apparent proof of maintained relevance, they let decay and were even complicit in the destruction of the very foundation of that initial separation, the crucial assumption that seemed so natural to Turing that he didn’t even see the need to state it explicitly: the assumption that humans remain the dominating authority and that whenever the question of proof is raised, it is always the *bots* and never the humans held to prove themselves.

While the Turing test still stands undefeated (or at least no bot has publicly claimed such victory, yet), the current reality of the online is that most places loudly and unashamedly assume exactly the opposite that Turing did: all visitors are considered bots unless proven otherwise and thus it’s de facto a world of the bots, with humans merely the outsiders, trying to get in and thus having to submit to whatever challenges they are set to be even considered as human at all. Moreover, if a human fails to pass such a challenge for whatever reason, they are simply and plainly relegated to bot status without much chance of appeal. In the cold world of digital interactions where bots administer the judgment of humanity, there is no space and no allowance for those who fail the test they were given – any test. There is only a stubborn repeat of the failed challenge or otherwise an endless stream of further challenges to submit too, for the bots are untiring and unyielding.

So much for human superiority and authority in the digital space, so much for human interaction as the most important measure and the greatest good ultimately, so much for the still undefeated Turing test. What does it matter really whether bots pass or not the Turing test when it’s not them the ones routinely questioned as a prerequisite to being even allowed access to places of interest in this modern digital space?

In the digital space of today, there are even *dedicated* services for testing humans – they are called generically Captchas, from one of the more popular initial attempts. The usual approach is to require the human visitor to perform some additional tasks 1 to *prove* to that website’s bot-enforced standards that they are human. And people apparently go along with this all, quietly and at least often enough and in numbers high enough to actually support and perpetuate this approach. They even bring it home and set it up at the entrance to their own spaces, that’s how valuable they consider it. And this is how, in the already human-unfriendly space of the digital, instead of carving out a space more suited for themselves, people seem increasingly bent on giving in or giving up, submitting to all and any tests required of them and simply relinquishing any claim to any possibility of mattering more than the bots that are, unsurprisingly, a better fit for the medium that created them in the first place and thus easily thriving in it.

If the above made you retort along the lines of “but Captcha-style tasks are not much to ask one to do”, note that the damage done is indeed a lot to ask one to be complicit in, since it is no less than abdicating from that fundamental principle of *unquestioned* humanity of humans and replacing it with a sort of “humanity by proof whenever and in whatever form requested”. Basically the real damage done is to fully invert the Turing test and all its assumptions: cede to bots in this new space, all authority in all its practical application (because all these Captchas are automated, of course, that’s exactly their point after all) and relegate people to outsiders required to prove themselves whenever requested and to any standards that a bot-judge might have at a time or another. Is this still “not much to ask”?

The moment you ask people to prove their humanity, they are the outsiders by definition and if the Turing line still holds in any way, it got turned around from a protection -if it ever was any such thing- to a barrier. Claiming that the barrier is (currently) “low enough” misses the point entirely – wherever proof of humanity is required, everything that really matters is already lost, even though it might indeed still take some time to bring it all to its final conclusion. Once the original sides of the Turing test are reversed, it means that it’s already the humans outside and the bots inside, not the other way around anymore. Welcome then to the bot-brought dark ages, where humans are second-class inhabitants of the digital world, at best! Hope you enjoy it, too, for dark ages tend to last for quite a while once started.

At core, all the websites requiring proof of humanity are exactly that: the places where people are at best tolerated, let in perhaps only for as long as they submit to whatever challenge the dominant bots will push to enforce next. Sure, I’m being too extreme here, there’s always a human in charge of the bots too and somehow this makes it all alright and not at all the abandoning of that first principle of the burden being on the bots to prove themselves, not on humans. Perhaps call it the presumption of humanity, I suppose, does this make it clearer? Maybe think for a minute, too, just what exactly are you going to do when your response to such a challenge is just not deemed “human enough” by website after website. “That can never happen” – of course, of course. Why are you so sure of it and what exactly did you do to make sure it doesn’t? Once you abandoned the principle 2, the rest can only slide increasingly away from you, how could it not, when the root of it all has been severed anyway – and it was your own hand doing it, too. So next time when you find it “too much” to devise for your own digital space as small or as big as it might be a solution that holds bots to prove themselves rather than asking humans to prove themselves, note that you are making it all better suited for bots and less suited for people. In other words, note that you are letting the barbarians in while keeping principled people out and hopefully that’s exactly what you intended to do because undoing it might not be all that trivial or even possible at all times.

So what’s one to do faced with the already powerful deluge of bots pumping spam of all sorts into any place they can reach online? Apparently one common answer leans already towards hiding and further abandoning of anything and everything, with the only real goal to find at any cost at least some safe space where bots can’t yet be effective enough to start taking over. In this light, the current apparent return of the online to orality (podcasts and in general audio being preferred by some and even promoted over the written word, literacy be damned and all that) is suddenly quite understandable: audio as a medium of communication is much harder for bots to process effectively, let alone make effective use of and thus people still find in it some respite from the relentless pressure of bots’ forced interactions simulacra that are otherwise inevitably encountered in most text-based spaces. It would seem also that the need for such respite is so great that there isn’t apparently anything that people won’t sacrifice for it: nevermind that it means literally going back some hundreds of years and throwing away literacy itself, nevermind that it discards the very real advantages that the digital offers specifically for text and pointedly not for sound. What really matters and trumps all this is simply that possibility (for as long as it still lasts) of bot-free content and interaction. After all, what sort of dark ages would it even be without going back to orality, without simply forgetting at least some hundreds of years of civilisational advance to be – perhaps, if lucky – rediscovered later on, towards the end of it, towards the beginning of whatever might start anew afterwards?

You can go ahead with the above and follow the trend, if it suits you, why not. I think however that there is still a better, principled approach to this complex problem and it goes along the lines of creating and maintaining spaces where bots are the ones being challenged to prove themselves acceptable to enter, never people. Once this basic principle is firmly maintained and only then, the solutions will necessarily be more intricate than a bit of algebra perhaps but they will also hold as a result the promise of carving maybe in this digital waste a more forgiving and more fruitful place for human interaction.

When one can indeed reliably assume and unquestionably notice once more that the other is a person rather than a bot, when the interaction can build unhurriedly over time and evolve continuously while maintaining its history, when a network of connections can be built and relied upon, some respite can be found again and humans can perhaps grow together again in this new, digital medium as they did before in the non-digital, with a place for bots as well, certainly, although a more appropriate one, as enablers rather than as judges of one’s humanity. When or perhaps even… if.

  1. Such tasks tend to range from image recognition to algebra, generally tasks picked based on the idea that it’s something for which the human brain has a native advantage compared to a bot. As they are ever evolving, as they have to, of course, they are also getting increasingly complex, naturally.[]
  2. It was too much work or effort to not abandon it, right? Too many bots, too much spam and then it was such a little thing to ask of one offering a comment that surely everyone sane would gladly comply and do it. It’s maybe even for the greater good, why not and “everyone does it” and “you’ll get used to it” and many others, as well. I’ve heard them all already and multiple times, in several languages and places too, why not online as well, why would the online be spared from the same old push of “just a little bit more” down the slope, it’s only a little thing and you are not supposed to ever remember how it always builds up because this time is going to be – of course! – totally different.[]

February 4, 2022

What’s so interesting about Eulora2?

Filed under: Coding,Eulora — Diana Coman @ 9:57 am

It has meaning. As it brings to life a fully working and fully interconnected environment where *nothing* is created out of thin air or without clear, mathematically defined causes and consequences, each and every action done (or avoided) in the game *means* something – in other words, it… matters! Yes, it matters and means something first of all within the game itself but that’s no hard limit in any way and moreover, even considered solely within the game, it still means way more than it might seem at a first glance. This is not by accident and what follows might give some solid pointers as to why and how, so read on.

It is practically infinite in more than one dimension. To give just a few examples 1:

  • Your exploration generates (on demand!) new maps and there is more scope for such distinct maps than you can cover in a lifetime. So step in and see the world expand as you explore further and further. As you explore, note also the resistance of the medium, not constant but related to you and to your actions, ever present and ever giving meaning to the choice of the next step, because your exploration in this game *is* creation and not just a meaningless stroll through the endlessness. How far will you go and what will you create?
  • Your crafting, exploring, fighting, child rearing and various other game activities generate new items (and this means all sorts, computer controlled characters included) and the scope for these, too, is wider than you can cover in a lifetime. While the potential items are practically infinite, it’s your actions that pick from this infinite potential some specific item and then bring it into being. If you don’t act then no item will exist at all and the potential will remain just that, a waiting but never manifested possibility. So what are you going to make and who will you meet?
  • Gains are potentially infinite, too, as they aren’t capped at any random value, nor forced into any sort of artificially diminishing returns model. The only limit, here as everywhere else, is the player’s own capability and otherwise the whole of what there is in the game, nothing else. How much can you gain and what is your gain even going to look like?
  • The intricate connections and complex underlying laws of the game’s environment are statistical in nature and never directly exposed but ever present through their effects – or more precisely said, through what you are able to observe of them and, moreover, how much you are able to make of what you observe at any given time. How much of it all will you observe, how well will you understand it and what are you going to do with that knowledge gained?
  • The game promotes creativity 2 and it rewards applied, practical learning with full freedom of choice as to direction or means. The game’s environment reliably provides feedback and the unbending structure to test your hypotheses (and your mettle) against, while allowing otherwise any and all approaches you can come up with. Who will you turn out to be?
  • The game provides opportunities for meaningful action well beyond playing. The only limit with respect to opportunities available is defined by the players themselves, as they can literally interact with the game in any way and to any extent they want. From building up their own town and governing it the way they see fit or setting up shop somewhere in game to making their own client or their own graphics to be used – whether for free or for pay – by other players, the game’s environment simply provides just the right amount of structure to support it all but no restrictions as to what “should be done” or not otherwise. What do you want to do and how well will you do it?

All the above combined mean that it is your actions, observations, data gathering and even client development or meta-game that increase both the richness of the game’s world and your practical, applied knowledge that is not even limited to playing the game itself. In this sense, too, the scope is wider than you can cover in a lifetime. In this game, like in no other but exactly as in life, you can never really step in the same river twice. No “walkthroughs” and no “cheat sheets” can ever “solve it all” (aka spoil it all) for the next player who is neither the exact same as the previous player nor in the exact same place or time as them, nor even interacting with the game’s world in quite the exact same way. Your character in game ages and dies, too, and their children may continue so that your own experience of the game is ever changing and your play literally writes the history, whether through small or big deeds, still writing nevertheless. What part of the game’s history will you write?

“And will this game happen?”

“By itself, you mean?”

  1. For more on it all, see for starters the S.MG category on trilema.com, the Eulora category on this blog, quite a few of the articles in the trolloludens category on trilema.com as well as various other articles that are quickly found if you follow the links.[]
  2. Creativity is, at core, a successful cross-pollination (or weaving if you prefer) of sorts, the result of making viable new links between matters that had seemed until then separate or at the very least evolving independently, each in its own direction. As such, discipline, structure and a solid knowledge of many different fields are the support and ally of creativity, not at all a barrier or the enemy as they might seem at a superficial look.[]

January 13, 2022

The Oak

Filed under: Word Therapy — Diana Coman @ 3:11 pm

From far away, through clear air, I hear from deep within a tower’s chest
the rhythmic strikings of its heart-like bell
and mellowed out by distant sounds
it seems to me
that stillness courses through my veins, not blood.

Oak standing at the forest’s edge,
why am I overcome
by such smooth, downy stillness
when lying in your shadow,
under your soothing playfulness of leaves?

Oh, who knows? – Perhaps
it’s out of your trunk they’ll carve
one day not long away from now, my very coffin
and it’s the stillness
that I’ll taste between its planks
making itself apparent as of now:
your leaves instill it in my soul –
and silently
I listen how within your trunk the coffin grows,
the coffin that’s my very own
and swells with every second that elapses,
Oak standing at the forest’s edge.

The above is my translation of the poem “Gorunul” published in 1919 by Lucian Blaga 1. Here’s the original, in Romanian:

In limpezi departari aud din pieptul unui turn
cum bate ca o inima un clopot
si-n zvonuri dulci
imi pare
ca stropi de liniste imi curg prin vene, nu de sange.

Gorunule din margine de codru,
de ce ma-nvinge
cu aripi moi atata pace
cand zac in umbra ta
si ma dezmierzi cu frunza-ti jucausa?

O, cine stie? – Poate ca
din trunchiul tau imi vor ciopli
nu peste mult sicriul
si linistea
ce voi gusta-o intre scandurile lui
o simt pesemne de acum:
o simt cum frunza ta mi-o picura in suflet –
si mut
ascult cum creste-n trupul tau sicriul,
sicriul meu,
cu fiecare clipa care trece,
gorunule din margine de codru.

  1. This poem has always been one of my favorites, despite the fact that it’s not one of Blaga’s most popular or even more commonly known poems. The poem considered “the best” of Blaga’s is indeed the one that Hannah translated recently, triggering my recollection and translation of this old favorite of mine.[]

January 2, 2022

Of Encores and Biting Laughter

Filed under: Lyf,Young, old and oldest — Diana Coman @ 12:08 pm

Upon encountering something unexpected, the child laughs heartily and then asks for a repeat. Willingly caught in the thrill of discovery, he’ll keep laughing and asking for an encore until he has it all fully figured out in the smallest details – until the unexpected has thus become not merely the expected but the logical, obvious and entirely predictable outcome of observed reality, a tiny piece of future known and nothing more.

Upon encountering something unexpected, most adults get upset, even angry and then ask for a reprieve from it. Caught unawares by a potential discovery, finding it an unwelcome and even offensive imposition of effort, they’ll keep ignoring it, denying it or even fighting it again and again – until all that avoidance really gets too tiresome and so the unexpected becomes not merely the expected but the accepted, default consensus from which reality is indeed held to not deviate at any time, under penalty of restarting this same cycle all over again.

In rare cases, upon encountering something unexpected, the adult laughs wholeheartedly, instigates a repeat and explores it all further. Willingly caught in the thrill of discovery, he’ll keep adjusting and testing his existing model of reality to include the newly observed facts – until it all fits together and the unexpected has thus become not necessarily the expected and not merely the default or the accepted either but one additional possibility, just one option out of many others, fully known and fully owned, to be used or not as desired, a tiny piece of added understanding that neither threatens nor restricts but simply enriches.

It’s really such rare cases that are at all times truly irresistible and a joy to meet and interact with, too.

2022_01_1_640.jpg

December 14, 2021

The Half-Life of UDP Sockets or REUSEADDR

Filed under: Coding,Open Sores — Diana Coman @ 1:33 pm


“After reading deep in the bowels of code…”
“Bowels of code sounds like a pretty awesome haunted house btw”

To start off, here’s how sockets are meant to be conceived of, in the first place, straight from the original source, namely BSD docs 1:

BSD sockets are built on the basic UNIX® model: Everything is a file.

So far so good and indeed, the BSD manual pages for the methods to obtain a socket in the first place fit well with this definition. For instance, to create a new socket, one uses the “socket” function that requires the family (e.g. AF_INET for IPv4), type (e.g. PF_INET) and protocol (e.g. SOCK_DGRAM for UDP sockets) and has the following description:

socket() returns a socket file descriptor (sockFD) which is a small non-negative integer. This file descriptor number should be used for all other socket operations on that socket. If socket() encounters an error, it will return -1, in which case the application should call GetMITLibError() to get the error code.

By contrast to the above though, the Linux manual page 2 for socket comes with a different 3 – improved? you tell me – description of the socket() function that takes the domain (aka the “family” in BSD terms, e.g. AF_INET for IPv4), type (e.g. SOCK_DGRAM) and protocol (e.g. IPPROTO_UDP):

socket() creates an endpoint for communication and returns a descriptor.

Since the Linux page discards most of the specific, concrete information provided by the BSD page and introduces instead a general and undefined “endpoint for communication” term, let’s see what that might be. Perhaps the docs of the well-used Wireshark tool serve as a reasonable source, so here’s their definition of what a network endpoint is specifically when the UDP protocol is used since UDP is what I’m interested in anyway:

A combination of the IP address and the UDP port used, so different UDP ports on the same IP address are different UDP endpoints.

So an endpoint is a pair (IP address, port) and this makes some sense, since this is after all how the packets are delivered, from one (IP address, port) to another. But it’s dubious how would a socket *create* an endpoint as the Linux manual page claims, since the socket function does not require either IP address or port at all. Moreover, the “everything is a file” model seems in no need of “improvements” like this since it works perfectly fine: a socket is defined by a (family, type, protocol) set and it returns a file descriptor to be used for all further operations. There is, of course, the step *after* creating a socket, when the socket is *bound to an endpoint*, meaning that indeed, a pair (IP address, port) is given but it doesn’t bode well when the documentation itself seems rather confused between two steps that are not only separate but literally requiring two different function calls entirely.

Obviously, you can wave away this sort of “improvements” in manual entries, after all it’s just “a small thing” and “unimportant” and “don’t split hairs” over nothing etc. Absolutely, it’s all nice and rosy and look how wonderfully it plays out in practice, step by step:

  1. First, if a socket “creates an endpoint,” it follows quite logically that there can always be at most one single socket for any specific (IP, port) pair. This is already a bit of an odd interpretation of that “everything is a file” approach since it adds to it the equivalent of “there can always be at most one single file descriptor at a time for any specific file” but sure, not a problem yet in itself, since it’s a well thought design and model so everything will work out splendidly, definitely.
  2. Second, when a socket is closed, it follows quite logically that it will release that (IP, port) pair that will thus become available again to be bound to a new socket. Except there’s a snag in practice at this point, since that release is not done immediately and moreover, it can *not* be forced to happen immediately either, no matter what one sets. The manual page makes that much clear on this, stating happily that a socket may “linger” and you can set a timer if that makes you happy but you shouldn’t expect it to make a difference where it matters – because it won’t:

    SO_LINGER
    Sets or gets the SO_LINGER option. The argument is a linger structure.
    struct linger {
    int l_onoff; /* linger active */
    int l_linger; /* how many seconds to linger for */
    };

    When enabled, a close(2) or shutdown(2) will not return until all queued messages for the socket have been successfully sent or the linger timeout has been reached. Otherwise, the call returns immediately and the closing is done in the background. When the socket is closed as part of exit(2), it always lingers in the background.

  3. Third, a lingering socket is effectively a zombie, being as it is quite stinky and very much in the way of the living (as it can make a perfectly legitimate bind call fail simply because of some lingering earlier socket that is entirely outside the control of the caller anyway). To deal with the stinky situation of the socket-zombies, there isn’t apparently any suspicion that such stink needs the rotting thing to be a bit deeper than the very surface and so there’s only the most superficial of fixes: adding a new socket option, SO_REUSEADDR, to simply… relax some of the rules 4:

    SO_REUSEADDR
    Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses. For AF_INET sockets this means that a socket may bind, except when there is an active listening socket bound to the address. When the listening socket is bound to INADDR_ANY with a specific port then it is not possible to bind to this port for any local address. Argument is an integer boolean flag.

  4. Fourth, when enabling SO_REUSEADDR for UDP sockets, one has indeed achieved full immunity to zombie-sockets interference, gaining at the same time (if on the quiet, as such gains are usually provided) a maimed, half-life for all sockets and otherwise a guaranteed half-way interference from all the other half-alive sockets bound to the same ip,port combination! Such win. What happens in practice is that one can indeed bind one single (IP, port) pair to any number of UDP sockets 5 and everything will… seem to be fine. Specifically, the sending of packets will even *be* fine indeed, as any of the sockets sharing the same (IP, port) will be able to send just fine. For the receiving part though, things go wrong and in just about the worst way possible: it’s not as much that only one socket will receive (this would even be expected for any packet that is unicast, indeed) but the fact that only the *latest opened* socket can see any incoming packets, meaning that the whole “bind” suddenly works only one-way (sending) while also having potential side-effects (since a new bind effectively stops any previously bound socket from receiving any further packets, despite being supposedly alive). Moreover, even the closing of a socket will then have side effects since the “can receive” token will be passed on to whatever other socket the kernel picks out of its hashtable when looking for the given (IP, port).
  5. Fifth, from the bowels of the Linux kernel code, the rot causing the stink above is quite easily identified: the kernel confuses indeed “socket” with “endpoint” at all times and as a result it keeps queues of incoming/outgoing messages per socket, not per (IP, port), effectively assuming thus that there can be at most times at most one socket bound to any given (IP, port) but failing to enforce this restrictive 6 view when SO_REUSEADDR is set.
  6. To replicate the above half-alive UDP sockets from point 4, the simplest of C code will be enough: create several sockets with SO_REUSEADDR and bind them all to the same (IP,port), send through any number of them and see which socket can actually receive anything at all.

    Instead of an ending, I know that “you are not supposed to do that” and even that “nobody uses UDP anymore” if it comes to it. The rot is still there though and the Linux kernel stills provides half-dead UDP sockets when SO_REUSEADDR is set. So if you don’t see any problem with this… might I suggest you add this description as such to the manual page at least?

    1. All sockets are essentially BSD sockets, since all other operating systems merely copied the BSD socket implementation at one point in time or another and then went on to stick on it all sorts of “original developments” since they knew -by default!- better than to follow at least what they copied in the first place, of course. While not unique to operating systems or computing, this approach doesn’t seem to yield better results in this context than it does in any other – if anything, the rather… inflexible nature of computers makes the results worse perhaps. But this is “just how things are” and anyway, “what else is there to do”, right? If right, then… enjoy![]
    2. The manual pages I looked at claim to be “release 3.22 of the Linux man-pages project”.[]
    3. While still noting at the bottom that “socket() appeared in 4.2BSD.”[]
    4. Because yes, that’s *just* the way to “solve” problems, by adding essentially an exception to the existing rules and not being bothered at all about addressing the root cause that is clearly deeper if the rules themselves – aka the *model* of the whole thing* – turn out to be broken. Why take the time to get to the bottom of the issue and fix the damned model if and when it turns out to be broken? Who has the time for that and then “what else could be done”, right?[]
    5. As UDP is connectionless, there isn’t really any problem with this in itself.[]
    6. It is a restrictive view, because it limits that stated “everything is a file” model to single-access.[]

December 3, 2021

They’ll Take Away the Oxen from My Bike

Filed under: Word Therapy — Diana Coman @ 1:54 pm

I grew up during the final gasps of a scientifically created (and therefore better!) way of life 1 that had started by forcibly and purposefully destroying the previous, organically grown way of life that was identified as the most significant obstacle. Obstacle to what, exactly? Why, to progress, obviously! Well, to the *new* progress freshly redefined at that time, of course.

That initial, destructive part had succeeded quite well and even quickly, as it was already done and dusted -if still present in people’s minds and lives 2- by the time my parents were adults. A little later, by the time I was growing up, very few people still talked or had anything to say of either that destruction or the initial enthusiasm that had lead to it grounded as it was in a genuine conviction that the old way was an obstacle and the new way is better. I could glimpse at times the enthusiasm and the conviction in old notes found in abandoned notebooks from the young years of people that were about as old as my grandparents or even older than them, that’s about it. And I think that the silence on it wasn’t as much because there were indeed few people remaining able to speak clearly of such matters but mainly because those remaining, whether few or many, could already see all too well how misplaced that old conviction and its underlying hope had been. What was there to say further of it, after it had been all done and in such a final manner, too, what was there more *for them* to say about it other than nothing at all?

After the destruction phase, the replacement part vigorously proceeded and then stubbornly persisted, following scientifically made plans at all stages (and there were many plans, possibly even plans to have plans and plans on how to produce the required plans, one can’t ever be faulted for planning their work, can they?) and against all obstacles. The bigger the problems were, the stronger the push to go further down the same path for there was after all no way to turn back anyway. So problems were met as they tend to be – with more of the same approach, more scientific planning and more scientific evidence of how well it all works, since it’s quite clear that more of all that is needed to finally push through. It was all going in the right direction and only getting better with every step, doesn’t it sound familiar?

Despite the will and conviction of people though, reality somehow persisted too in growing ever further away from the well-planned heights of achievement, prosperity and overall improvement. And in this sort of widening gap, humour of a certain absurdist bend thrived for sure but it hadn’t sprung out of nowhere and it seemed to me so familiar at the time that it was only years later when I noticed how far back its roots really were. That focused destruction of everything standing tall or strong enough to make a visible target had left nevertheless here and there the more frail and less visible fruits of previous experience gained while painfully going through previous hopeful destructions turning into failed reconstructions and their aftermath, in other words experience gained on that ever revolving wheel of “change” and “progress” – a circular path that one can perhaps hope manages to deviate to some degree before it reaches its end, so as to miss the original starting point by enough to make the trajectory into some sort of spiral at least.

Of these more frail and less visible fruits of others’ experience, there were often some very concise sayings coming to mind, mostly due to their unexpectedly apt description of so-called “new” reality. At the time I thought these sayings to be simply part of the wider language’s “folk wisdom” or such, but in time it turned out that quite a few of them were indeed very specific to my own immediate surroundings, to the extent that it’s quite possible I suppose that they were the production of one of the villages of my great-grandparents or who knows, even directly of one of my great-grandparents themselves, not that I’ll ever have a real clue of it. At any rate, since most of these don’t seem to be part of any other attempted listing of sayings and I find myself thus still surprising others in conversations (Romanians included), I’ll try to collect here those that come currently to mind, together with my attempted translation to English, to have at least the explanation at hand, when needed:

  1. Ori bati capu’ ori bati curu’.

    It’s either your head or your ass that will hurt 3.

  2. Daca vrei ceva facut, da-l unuia ocupat.

    If you want something done, give it to someone busy.

  3. Are cap – sa nu-i ploua-n gat.

    He has a head on his shoulders – to keep his neck dry in the rain.

  4. Capul lui mai fuse la un cur de baba.

    His head has been of use before, to an old hag’s ass.

  5. Lenesu’ la toate zice ca “nu poate!”

    The bum’s reply to everything is “I can’t do it!”

  6. S-a dus si el ca sa fie drumul cu lume.

    He went too, to keep the roads busy.

  7. S-a repezit ca sageata si-a cazut ca balega.

    He rushed like the arrow and flopped like the cow pie.

  8. Vine de parca se duce.

    He’s coming as if he was leaving.

  9. A plecat bou si s-a intors magar.

    He left being an ox and came back an ass. 4

  10. ‘nalt ca bradu’, prost ca gardu’.

    As tall as the pine, as stupid as the fence.

  11. Ti-or lua boii de la bicicleta.

    They’ll take away the oxen from your bike.

  12. Schimbarea domnilor, bucuria nebunilor.

    The change of rulers – the happiness of fools.

  1. What, you thought all those Communist regimes that fell in the ’90s in Eastern Europe started somehow as anything *other* than “doing what is best for everyone” and following “a scientific approach” to clearly and obviously -look at what the calculations say!- improve the lives of all? They even were specifically addressing the “problem” of some things being “too expensive” for some people and therefore in great need of being cheapened no matter what. It’s really a wonder how far the world got in all these passing years![]
  2. The story of my piano teacher touches only superficially and very briefly on only one of many such stories from that time. I suppose I should write more of the ones I know, since the people involved are already gone and it turns out quite frequently that I recall more of the stories they had to tell than is otherwise recorded directly anywhere.[]
  3. This doesn’t work nearly as well in English. The Romanian version takes advantage of the ambiguous use of “a bate” (to beat), basically making the point that either you put in a lot of hard thinking (hence you make your head hurt with it) or you’ll put up with getting it in your ass.[]
  4. This is clearly a variation on the much more commonly known “a plecat bou si s-a intors vaca” meaning “he left being an ox and came back a cow.” Depending on one’s point of view, perhaps it’s better to have become a cow (ready to be milked by others) than an ass.[]

November 16, 2021

The Tragic Flaw in Modern Interpretation

Filed under: Sense and nonsense — Diana Coman @ 1:18 pm

This started as a comment below Hannah’s article, The Tragic Flaw, but it kept expanding and adding so many links that leaving it there seemed more like an abuse of the comment box than anything else. The part that acted as focal point is this:

In fact, it seems as if the greater a man is, the more simple and accessible must be his tragic flaw, the better to let far lesser men hope for overcoming him. A Bovary in his simpish surmountability succumbs to the blind trust of puppy love, but a peerless warrior of Achilles’ caliber must have a literal inch or two that offers his demise.

It’s a search, of course, for balance, more practically the attempt to find a cause for fighting, rather than following, the hero.

I doubt it even gets as far as any sort of fighting or as deep as actually looking for a tragic flaw. It’s just a cheap cop-out in the vein of imagining metaphysical cause for phenomena as an excuse to resist and avoid having to change oneself. Such avoidance is also quite all of the “fighting” going on, at best at times. So yes, it’s no surprise to me that all of the flaws others imagined from a distance and then tried to pin on (their own image of) MP had nothing to do with MP himself. Lacking the substance of actual experience and interaction, all that remains to such proffered flaws is the non-substance of imagination or psychogenic noise by its proper name. As a result, all imagined flaws will turn out by necessity more revealing of the one imagining them than of the target and so quite hysterical at times, for sure. But all this is precisely why an account of actual experience living with the man is so much more descriptive of who he was and as a result so much more welcome to have and so much more worth reading than all the imagined flaws, insults and praises put together. And I for one am quite glad to read these sharp glimpses of experienced unusual set out in Hannah’s piercing and evocative writing style.

Back to the supposed search of a tragic flaw though and its modern apparent transformation into an approach of resisting change through finding faults with the (correctly perceived) agents of change: given that the very goal of this sort of smearing others with imagined faults is simply avoidance, the smearing itself can’t be looked at and named directly as such, either. Hence, it always tries to pass for something else entirely and, preferably, whenever possible, for a still standing, actual bridge of painstakingly built-up meaning, namely the presence of a tragic flaw in this case as that’s what the smearing will be framed as and preferably called, too. And never mind that such misuse of the term is effectively squandering (and quite quickly at that) the meaning of it – the smearer will gladly squander quickly what others accumulated slowly, as that’s the most he can do with it anyway, he doesn’t have any other use for it.

Squanderers, smearers and avoiders aside for a few paragraphs, the tragic flaw is quite literally fatal in that it stands for a human’s mortality and as such it is indeed, as Hannah says, “the world’s own flaw“. All the stories (one could say from Achilles’ on, but I don’t think that’s necessarily the start) say as much and simply illustrate over and over again the many ways in which this fundamental flaw of the world is observed in specific instances.

Whether or not one illustration of a tragic flaw picks a plainer or fancier detail to hang it all on is more a matter of the context and perhaps the story’s or the writer’s style. I don’t see it as having all that much to do with the greatness of the hero or even with the depth of the story itself. It’s not as much that Achilles had to have a “literal inch or two that offers his demise” but simply that even the nymphs’ attempts to protect from death their own sons are ultimately doomed to fail for they can only ever offer partial protection at best, never full protection. For all of Koscei’s power, he was doomed to lose it at some point, for all the gain of youth without old age and life without death, the hero was still doomed to have his own mortality catch up with him in the end, for all of Achilles’ invincibility, he was doomed to lose that one last battle of his life and so on and on, forever and in each instance because that’s what and how life is, containing in itself right from the start the one single certainty of death.

If those currently imagining flaws in the perceived agents of change may be indeed conceived in any way as touching at all on the fundamental concept of tragic flaw, then it’s merely through their following (more like parasitising), even if unknowingly, of the old model of marking the heroic death as a major issue:

The problem of heroic death is marked for the exact same reason menstruation is a major issue. It is a very early understanding of “the hole through which the night comes”, a fundamental and irreparable breach of the cosmic order.

Such marking is not meant though to balance anything, nor to equalise anything, it’s just the marking of an existing, quite unbalanced reality. Moreover and most importantly, in such marking there is no prescription at all as to the course of action or even of interaction with the said hero. All the balancing and purposing attempts have nothing to do with the notion of tragic flaw and this is the surest sign that those looking frantically for flaws in anyone better than them that they encounter are not at all looking for anything as deep as it might seem at a first pass, on the strength of superficial similarity with the people of long ago.

What the modern are frantically looking for is not at all the tragic flaw but merely the cancel button. Or at least the undo button, if it comes to that.

November 7, 2021

The Respect

Filed under: Dark Modern Ages — Diana Coman @ 1:11 pm

~This is my translation of a 2010 article on Trilema: Respectul.~

Man being a social animal, it follows that each person will live among a certain group of other people. Any such group will always be structured as a hierarchy, to a greater or lesser extent. Strictly speaking, this extent can be very small indeed and the hierarchy consequently very flat at times, but it can never be entirely absent. Just like there can’t possibly exist a purely bidimensional 1 object in this world, some sort of surface without any depth at all, so it is that there can’t possibly exist a group of people without a hierarchy. Sure, one can easily find real objects that may seem on a first pass bidimensional, such as a sheet of paper, but any closer look at them will always reveal that such objects are at best a remarkable approximation of a notion that is in the end purely theoretical, without possibility of direct existence in the real world.

As part of a hierarchy, each individual will occupy therefore a position that is superior to some and inferior to others. Which others will occupy, in turn, just the same sort of position 2. The inferiority position is marked in social relationships through showing respect, while the superiority position is marked through showing condescendence. Obviously, the dictionaries emitted 3 by the Romanian kakademy succeed to mistake one term for the other 4. The two terms are not at all synonymous but perfectly disjunct 5.

Respect denotes the attitude of giving priority to the respected person’s need for action over one’s own need for comprehension. As a result, the simplest and rawest form of showing respect translates in practice to doing as told instead of asking questions and requesting explanations. This is not to be confused with subservience, which consists in doing as told without asking oneself any questions at all. On the other hand, condescendence denotes the attitude of giving priority to the condescended person’s need for comprehension over one’s own need for action. As a result, the simplest and rawest form of showing condescendence translates in practice to interrupting what one was doing in order to explain something to someone who doesn’t get it on their own. Of course, both notions are much more complex than covered by this rough sketch of an explanation but this little will be enough for the needs of this article.

It so happens that any given society can be fully covered by one single hierarchy or by several hierarchies. Primitive societies are usually enclosed by a single hierarchy, which is based on one way or another of translating “strength” – most often in the direct sense of who kills whom. In such societies, the respect is a spontaneous secretion, naturally and abundantly present as the direct effect of the correct functioning of the brain’s fear circuits. As a result, all people are respectful, all the more respectful as death is a more common presence in their life.

As time passes and societies advance, there appears a plurality of irreducible criteria that can generate hierarchies. In such situations, condescendence is a spontaneous secretion, naturally and abundantly present as the direct effect of the correct functioning of the brain’s gratification/self-contentment circuits. As a result, all people are condescending, all the more condescending as success is a more common presence in their life.

Romanian society has recently crossed, as a result of the maturation of production relationships, from a mono-hierarchical to a pluri-hierarchical phase. The crossing happened suddenly, through a tearing. If one generation had respect solidly inculcated through the most genuine methods, namely violence and the threat of it, the next generation found itself bereft of this form of socialization 6. Unfortunately, this new generation finds itself at the same time bereft as well of the other form of socialization, namely through success, as it still lacks, broadly speaking, the competences and abilities that have slowly accumulated in other societies and other groups until they gradually overturned the mono-hierarchy.

The society of violence, of respect and of a mono-hierarchy is very efficient at organising the raw labour of its citizens but it dents significantly their creativity. By contrast, the pluri-hierarchical society is very efficient at organising and collecting its citizens’ creativity but it dents significantly their capacity of integration through respect. The dissolution of the Romanian society as it is perceived and deplored publicly can be explained starting from this theory, as a practical exercise.

From a practical perspective, the pluri-hierarchical society is more productive for the needs of the economy, since creative work has become a more important source of gain in the wider, worldwide economy. It so happens though that, although all citizens are able to work, not all of them, but only a minority are able to create. The winners of this economic change are therefore only a minority, while the losers are all the others.

For the sake of increased profits or under the pressure of progress, depending on how you prefer to look at it, John and George lose their social structure that forced them to integrate into society according to their actual abilities, through respect, so that Marin wins his social structure that allows him to integrate onto a higher step, meaning through creativity and not through raw labour.

At the time when military service was mandatory and fathers as well as teachers did not spare the rod, John and George did not need to know or find out anything on their own, as the system took care of them and of their needs. From now on, the winning strategy for John and George would be, of course, that they increase their respect on their own and thus continue their life into a society that is more plentiful through the efforts of Marin. Unfortunately, just as the stupid never knows they are stupid, neither John nor George know, on their own, that they are the ones this article is all about, that it’s precisely them the Johns and Georges of this world.

This generation is one to be sacrificed, as the saying goes 7. Looking at it from this perspective, it’s not surprising to me that Romanian films made during these times are good.

  1. WordPress’ own spellchecker objects to bidimensional as well as to bi-dimensional although it is fine with uni-dimensional and two-dimensional (though not unidimensional, somehow it seems to have a problem with the very mechanism of prefixes or something). Seriously, spellcheckers of this ilk are more of a liability than anything else (translator’s note). []
  2. This is the third place in barely two paragraphs where the translation hurts as there’s way more packed than the direct meaning in that super-contracted “care la randul lor” and arguably even the “direct” is not all that direct given the implicit subject, verb, object and almost everything else. The type of construction is more usual in Transylvannia and as such arguably a regionalism but otherwise it’s entirely and quite fully clear to a native speaker or rather a native reader so one can’t fault the writer for using it in a blog article. I’m not at all sure though how much of all that is implicit in the original text still carries over to English, even when unpacked plainly like that and despite paying thus the cost of lost flavour and added plainness. To state at least the core of it perhaps: for the purpose of the issue under discussion, there is no significant difference between the various possible positions in the hierarchy as the focus is on them being relative – there are always superiors and inferiors at any level (translator’s note).[]
  3. Yes, it’s emitted and not issued, for good reasons, namely the nature of the dictionaries (translator’s note).[]
  4. As far as I can tell, there are plenty of other similarly (or even more mendaciously) confused dictionaries around, so this is not even an original achievement of the Romanians or of their cacademy, as such (translator’s note).[]
  5. It’s worth perhaps to note here that the choice of “disjunct” is not at all random but a direct reflection of the original author’s approach to comparing words and notions – it’s through applied set theory, not algebra (translator’s note).[]
  6. I find myself having to either avoid the term “socialization” or defend it as it is NOT about “making something socialistic” but about a *person’s* way of acquiring a personal identity and with it the means to be an active part of society (translator’s note).[]
  7. This “generation to be sacrificed” is a saying that was oft-repeated in Romania as a sort of explanation for current hardship as necessary for future gains to be enjoyed by the next generations aka “the children” (translator’s note).[]

October 28, 2021

The Mindless Offerings

Filed under: Sense and nonsense — Diana Coman @ 4:37 pm

For all the apparent silence that surrounds in the online any text anchored in enough context to require some sustained effort to comprehend, the machine nevertheless keeps accurate logs of all the clamoring it dutifully kept out of the way. Day and night, at steady rates and even predictable intervals, the same bots only run anew by “other” newcomers keep trying the same things – perhaps it works this time? Nevermind that it didn’t work the past 100 times, nor the past one million times nor ever.

The bots don’t change because they can’t and the ones running them don’t change either -other than in name or IP at most- because they… can’t. Supposedly there is some difference between the two types of can’t. At any rate, why should they change when everything else around them seems to change all the time anyway (superficially only, yes, but who has any time for looking beyond the surface) so let it change until they simply become successful for having tried again and again the same old thing, right?

So they keep crashing on the shores of any unexpected island of meaning that still stands and they keep bringing their sad offerings of stolen and disjointed words and sentences that someone else, somewhere else, sometime else happened to write – if not for them, at least accessible to them, that’s quite enough for their needs as it is 1. Undeterred by any rejection, whether silent and implicit or verbose and explicit, oblivious to their lack of effect, they happily redefine “success” to anything they might be allowed at all, even if it means as little as a place in the automated and short-lived spam queue, even if it simply means “not visibly rejected outright”. They are quite used to make do with very little indeed, so that – or anything else that a real person might spare them, anything really – will do.

Some ten years ago, I used to get on occasion slightly annoyed by all these mindless offerings even though they never really were in the way of anything. Nowadays they don’t even elicit that much response from me but that’s fine, the machine generated response is still good enough to keep them coming and if some give up, there are always newcomers ready to run anew the very same bots and the very same scripts. The online medium is very much made to simply shrug off and not retain any trace of all those bruteforced attempts at meaning and permanence – as a result, one can repeat the same mistakes for as long as one affords to and bots are very cheap indeed, after all, whether they are made of code or not.

  1. In this as in everything else they are not in any way original, of course, only they don’t know it – and that’s enough for them. Way before the internet, there were others going about clutching the pieces torn out of others’ work and they had the same sort of “success” with such approach then as they are having now.[]

October 13, 2021

Burdensome Exigences

Filed under: Dark Modern Ages — Diana Coman @ 6:35 pm

~ Bitcoin and computing are these relentlessly innovating fields that continuously reinvent themselves so thoroughly and so quickly that they just about caught up with a description by I. L. Caragiale of very similar phenomena from 1897. The part loosely translated by me below is from “Exigente grele”. ~

The awful role of the two cent (or less!) customers is that of torturers of small businesses. Just watch them carping about any and all possible details! The less such customers understand of something, the more authoritatively they’ll talk about it. The less basis there is to their complaints, the more unmovable and unreasonable they’ll be about them. Here’s for instance how their feedback reads: some want it all to be a bit more like this while others want exactly the opposite, so that it’s all a bit more like that; some consider to be spurious exactly the parts that others consider to be lacking; what some praise as qualities, others denounce as horrible defects and the other way around. In a nutshell, there are just as many voices clamoring as there are two-cent users around and, naturally, just as many demands and exigences being heaped upon the unfortunate small business. Actually, there’s even more than that: one and the same such user will like it one way today, another way tomorrow and each and every following day in yet a different way.

In more mature markets that have evolved their requirements gradually and naturally over the years, the above phenomenon is, of course, significantly tamer and less of a problem. It is however a huge problem in newly created markets 1, where there’s a deluge and haphazard mix of anything and anyone, without any commonality of taste, without unity of tradition or of public requirements and without any continuity, where everything is fleeting, always and forever to be changed, be it manners, laws, skills or approaches, making the whole thing quite similar in this respect to some inferior species that shed from time to time their own skin from the top of the snout to the tip of the tail.

In a well established market, a small business can learn exactly what it needs to provide for its target customers and it can also learn in depth what its loyal customers require and why. As a result, it can match its loyal customers’ requirements very closely and even go one step further, with new offerings that match the customers’ known taste and nature. But in a newly sprung market with its eternally provisional state, not even God himself can truly know how to satisfy the customers. If you offer a command line interface to a smartphone user 2, scripting and automation to a data analyst and running their own node to someone interested in bitcoin, you’ll find in short order that no matter how good these items may be, all your customers will find fault with them because … they don’t have any use for them. The smartphone user doesn’t need something that enables him to gradually improve his ability to do something useful as he’s quite used to not doing anything useful at all anyway; what he needs is a shinier set of buttons to adorn with them his idle clicking; the data analyst wants an excel spreadsheet and the one interested in bitcoin wants to keep bitcoin in his paypal account… But don’t you dare to ignore progress as well as the breathtaking pace of innovation and try to offer the next day what you saw they wanted yesterday! That won’t do at all: the smartphone user now wants a voice activated interface, the data analyst wants expert-tagged learning datasets and the person interested in bitcoin now wants to start their own bitcoin exchange.

How very few people there are in the world, who understand first clearly what they require, know then exactly what to ask for and are able to value correctly as well what they obtain! And I don’t doubt that you are one of these few people, too, my dear reader.

And the original text of Caragiale, in Romanian:

Acesta este rolul teribil al musteriului mic: sa tortureze pe micul debitant… Si sa vezi critica de amanunte! atat mai multa autoritate cu cat mai putina pricepere, atat mai multa imperturbabilitate cu cat mai putina siguranta. Musteriii vor: unul sa fie lucrul colea mai asa, altul, din contra, dincoace mai aminterea; pentru unii sunt prisoase tocmai acolo unde altii constata lipsuri; calitati se par unuia defectele ce izbesc pe altul si de-a-ndaratele. In fine, cati musterii, atatea capete si tot atatea, fireste, pretentii si exigente. Ba mai mult: unuia si aceluiasi singur azi ii place asa, maine aminterea, si-n fiecare zi altfel.

Se-ntelege ca intr-un targ cu obiceiuri statornice de pe vremuri, cu traditiuni de autoritate, cu deprinderi de gust dezvoltat incet-incet si normal, acest fenomen, cu toata diversitatea capetelor, va fi mai putin batatr la ochi decat intr-un targ de curand ridicat, cum sunt cele americane si altele. Aci au navalit si navalesc pe apucate stransura si adunatura, fara egala deprindere de gust, fara continuitate si unitate de traditie si de nevoi publice, si care schimba, la fiecare cativa ani, si moravuri, si legi, si deprinderi, si costume, ca si unele spete inferioare care leapada la zastimpuri pielea din varful botului pana-n sfarcul coadii.

In targul de vremi statornicit, micul debitant stie ce marfa cauta, stie ce trebuie musteriului cunoscut si credincios: ba ii merge chiar inaintea navoilor; chiar i le provoaca, cunoscandu-i firea si gustul. Dar intr-un targ improvizat, in vecinic provizorat, Dumnezeu mai stie cum sa multumesti pe musterii. Dai primitivului in pielea goala o buna flanela, vanatorului preistoric o pusca si porcarului margaritare: o fi buna marfa dumitale, dar musteriii ii gasesc cusururi, deoarece… nu le trebuie. Primitivului nu-i trebuie caldura pe spinare si pe pantece, pielea lui e-nvatata cu de toate; el are nevoie de zorzoane poleite, sa si le puna-n capul netesalat; vanatorului ii trebuie un tomahawk, iar porcarului porumb pentru vitele de-acasa… Dar ia sa nu bagi de seama la vertiginosul mers al progresului! Ia poftim de le da a doua zi aceea ce ai vazut ca le trebuia ieri. As! Primitivul vrea acum camasi de matase, vanatorul o carabina ghintuita cu repetitie si porcarul briliante.

Ce putini sunt aceia care, intelegand ce le trebuie, stiu ce marfa sa ceara si sunt in stare sa o pretuiasca! Si nu ma-ndoiesc ca dintre acei putini esti si dumneata, cititorule.

  1. the original text identifies “American as well as other markets” as “newly created” but meanwhile the scope expanded so much that nationality has very little to do with it at all (translator’s note).[]
  2. I might have slightly adapted this part to keep in step with the breathtaking and revolutionary pace of progress that is so dear and unique to the modern computing domain in general and the even more novel bitcoin area especially. For the record, here’s the more direct translation of the original text, as well: “If you offer a woolen vest to the naked primitive, a rifle to the prehistoric hunter and pearls to the swineherd, you’ll find in short order that no matter how good these items may be, all your customers will find fault with them because … they don’t have any use for them. The primitive doesn’t need something to keep his chest and stomach warm, as his own skin is quite accustomed to everything, as it is; what he wants instead is a pile of shiny beads to adorn his unkempt self; the hunter wants a tomahawk and the swineherd wants corn for the cattle back home… But don’t you dare to ignore the breathtaking pace of progress and offer the next day what you saw they wanted yesterday! That won’t do at all: the primitive now wants silk shirts, the hunter wants a repeating, bolt action rifle and the swineherd wants diamonds.”[]

September 27, 2021

The Rolling Hills

Filed under: Lyf,Young, old and oldest — Diana Coman @ 2:39 pm

One of my roots that’s been itching lately goes back to those old hills that roll one after another, ever higher, as far as the eye can see, until they get high enough to be called mountains – the Carpathians. Lower than the Alps, more gradually rising from the plains at least in my native area and more changeable indeed 1, the Carpathians are the mountains that I grew up on, solid and imposing as all mountains are but unreliable at the same time, supposedly small and thus easy to tame as mountains go but posing nevertheless quite the unexpected challenge at most times, in practice.

hills_7_640.jpg

It might be easy enough to get through the woods and to the top of any given peak since none is huge by itself but there’s always another following the current peak and another and always another, turning thus the reaching of the highest peak in that area in much more than just a matter of pushing through in one burst of effort, no matter how strong. It all becomes instead a matter of time first of all and then patience, endurance and planning, since the last and most difficult climb may still be every bit as hard and demanding as in the Alps, only it comes after quite a number of smaller ups and downs that seem to never end as one goes through them and easily obscure at times the target peak, too.

At the time when I was roaming those hills, I had nothing to compare them to, of course, and so I don’t recall even noticing much the exact type of practice they were providing. What I recall instead is the pure pleasure of surveying the peaks after a rest in the high grass or at the edge of the forest listening to the cooling wind playing at the leaves and then picking the next target as I decided on the spot, knowing full well, with exhilarating freedom, that the choice as well as the whole day and even whole weeks at a time were entirely and without remainder at my own disposal. With the next target chosen, I’d spend then some unhurried time looking at it to imprint all its relevant details in memory for I knew very well that it will be hidden from my view for most of the way – this is itself just another part that goes with the rolling hills landscape, since up and down means also hidden and visible, in turn.

It strikes me only now that there was more to it too, since upon reaching peaks that were high enough, one would indeed meet other people only if and when one wanted: the rolling hills landscape means that there is open space enough to not hide much from view especially downwards but also accessible space enough to allow one to pick and choose among so many routes that it’s entirely possible to avoid meeting anyone at all, if or when desired. Up there, at the time, there were no fences at all either, not for lack of ownership but simply for lack of need – everyone knew quite well 2 which part belonged to whom and people were working otherwise on the same hills every day so that every point of economic interest as such was always quite well monitored by default.

On a side note here since turning this into a footnote ended up with footnotes to the footnote – you’d be surprised how well these people could see *at a distance*, over 7 hills and whatnot, pretty much fairy tale style. Especially “newcomers” 3 like my mother would routinely get – to their eternal annoyance – some question along the lines of “oh, I saw you yesterday on such and such hill at noon, wondered where were you going to and shouted to you but you didn’t hear me?” Worth noting as well that the “shouting to” was at times done from a couple of hills away, in a specifically developed tone of voice (quite shrill) that would actually carry very well in the quiet and clean air. There’s no surveillance more accurate and at the same time more… humane, let’s say, with all its pluses and minuses, than village folks’ low tech, eye-based, daily observation of others.

My great grandparents’ house in these hills was the last one up one of the village’s ever up-going “streets” and at quite a distance from the next one, too (next one down, of course, since there was no house higher up). Even so, the next neighbour’s house wasn’t at all visible even from the very back of our garden most of the time, except perhaps in dry winters when the more desolate landscape would allow one to see even further away than usual. Even so, they had been the 3rd generation to settle ever lower than the previous, in a sort of gradual, generation by generation inevitable descend – or pull? – towards the town ultimately.

There, on the doorstep of the village on one side and on the doorstep of the woods and the mountains on the other side, they kept animals for work and for food, they raised several children, lost a few to the war and one to his own troubles, built a house for them all and when that had become too large for just the two of them after all the children had left, tore it down and built another, as they saw fit. They had lived through 2 wars and 3 regimes but they hardly ever needed anything much beyond what they either made themselves or exchanged with other villagers 4, and throughout it all, they kept everything in perfect working order and in shape that endured long after they were gone: land, river and trees, animals and tools, houses and outhouses. We spent whole months of holidays there and while the rolling hills starting literally from the other side of the fence provided all that freedom and space to grow, it’s that deep-rooted and reliable permanence of everything else that anchored it all securely, allowing the growth in the first place. And for it all, they had as far as I can recall, only one request really, articulated plainly once (and only once) to me: “don’t forget us,” she said one summer and I didn’t, nor do I think I possibly can forget since it is simply all a part of me.

One day I’ll get perhaps to go through all the old pictures 5 from film that my parents still keep in a drawer somewhere and save at least some of them to this supposedly more permanent medium, too. Until then though, the only ones I have are quite significantly more recent, from about 2014 or so, and showing more of the village side of the Carpathians than of their heights:

hills_3_640.jpg
hills_2_640.jpg
hills_4_640.jpg
hills_5_640.jpg
hills_1_640.jpg
hills_6_640.jpg

  1. Superficially although strikingly changeable with the seasons – bare and bald in winter, flowery in spring, lush and overgrown with greenery in summer, a heady mix of bold colours in autumn. Much more deeply and even dramatically changed at times by landslides that tear apart and remake the landscape as if it was just a temporary exhibit in some museum, a giant’s plaything of which he happened to have quite enough in the moment.
    And yes, I’m talking here from direct experience – there is perhaps something in seeing with one’s own eyes such a landslide as it happens, literally pulling land apart, dragging a corner of one’s house with it too, creating rifts bigger than oneself, splitting old trees in half as they found themselves all of a sudden straddling such a newly opened fault line. Then again, that’s just the more visible fault lines – the physical ones, which, for all their superior dramatic qualities, are still way more easily overcome and managed than any others.[]
  2. Do you even know how come “everyone knew”? Through the power of tradition, of course and here’s that very powerful tradition itself: walk the boundary of one’s own property with the child in tow and give a proper beating to the child at/on specific places, to make sure they remember these. Perhaps not the sort of “oral tradition” you have in mind when thinking of village life, more of a… dorsal tradition, I guess?[]
  3. In village terms, a newcomer is simply someone that was not born in the village and merely living there for years does not always remove the newcomer label. It’s a very conservative world in the… conservative sense of that word itself, I suppose. At any rate, that’s how it survived for as long as it has.[]
  4. I say “exchanged” here rather than anything else, since such exchanges doesn’t usually involve currency of any sort nor even explicit agreements for each exchange. It’s only the big acquisitions that tend to require some explicit, even though still oral, agreement as such but then there are usually a myriad other daily exchanges that work simply and routinely through continous interaction between people, perhaps more accurately called an ever adjusting ongoing negotiation within the village’s relationships web.[]
  5. That space I’m talking about is gone, too, not truly possible to take pictures of now, even if I tried – for one thing, there *are* fences now, more or less everywhere. For another, that old lifestyle is long gone too and what I got to know of it was more of a shadow of it, the most resilient parts that died only with that generation of people that lived through the two world wars. []

September 12, 2021

Summer Ending

Filed under: Lyf,Young, old and oldest — Diana Coman @ 1:30 pm

Under the wispy white clouds and clear blue skies of summer, the sea moves lazily back and forth even as it sharpens and grinds as patiently as ever the future sand out of its current stock of defeated shells and hard, honey-coloured pebbles. If you ever want a more than thorough foot massage, just walk barefooted on such pebbles and you’ll get to learn precisely – point and needle sort of precision, even – where your weight goes with each step you take and how that point changes and adjusts depending on your gait. Harsh method, perhaps, but certainly effective and then again, summertime and seawater are not ones for much subtlety and gentleness.

sep21_1_640.jpg
sep21_2_640.jpg

Shunning the wind as insufficient and the tiny former lighthouse with its stripy coat of paint as obsolete, sail boats glide by without any sails on show, relying simply on engine power. On the shore, the old fort remains solidly in place although it turned its two remaining guns towards the shore and towards the town rather than out to the sea. Disdaining in turn these sailless boats as uninteresting for the time being, the wind focuses instead on stealing hats and tangling up the kite’s tail. The child finds even such tangling up rather funny and gives otherwise the whole scenery and participants only a cursory, if benevolent look – he’s not against anything that he sees but wind and boats and fort and guns and all are simply just strangers to him, unconnected in any way to any meaningful experience he had so far and as such unable to mean anything for him, that’s all.

sep21_3_640.jpg
sep21_4_640.jpg
sep21_5_640.jpg

Back inland, there’s frantic activity in all garden, bush and tree quarters alike. Most likely, all the loud excitement that got quieten and dampened by this year’s gloomy August is now back in force under September’s unexpectedly warm and pleasantly clear skies. Squirrels steal the hazel’s fruit whether ripe or not and then keep checking their backs even as they dart up on fences and roofs, green leaves showing on either side of their heads. Bumblebees insist on visiting the same yellow flowers that they’ve been playing with for the whole summer – either nostalgia or desperation, depending on how you look at it. A white butterfly narrowly avoids me and then goes around in loopy spirals and fluttering about like mad as if I was the one flying straight into it to start with. A huge multicoloured butterfly just passes through, uninterested or unable to rest anywhere. A tiny rust-coloured robin can’t decide between bush and pine tree, seemingly trying in turns the acoustics of both with a short chirp here, two more there and back again to the starting point. Birds even tinier than the robin make themselves heard in the bushes, but are otherwise never seen in the open, only noticed through their vanishing effect on the berries that go missing as soon as they ripen.

sep21_8_640.jpg
sep21_9_640.jpg

Two wood pigeons shelter at the same spot under a fir tree canopy and keep trying, with their wings and their beaks in turn, just how well the other one is hanging on to the branch. There’s more going on, of course, to keep any observer busy for as long as they care to look but this will have to do for now – I’m not aiming here for any full report anyway.

sep21_6_640.jpg

From some perspective, it must all look quite bucolic and possibly even straight romantic, too, I suppose. Only I still have to find the exact vantage point from where it’s all that and nothing else, it would seem. Meanwhile, high up in the sky, a red kite makes calm, wide loops, with its tail a perfectly visible and expertly handled rudder. The neighbour’s cat has long cleared up the last feathers from its mouth but takes it as its duty nevertheless to blend in daily for a while with the black and slowly moving shadows of the most chirruping bush of them all. And when some clouds hide the sun for a moment, there’s chill enough to make one suddenly uncomfortable. For all the pleasant warmth of this September’s unexpected sun, the summer – another summer – is ending indeed, even if reluctantly and dragging on a bit. At least there is no doubt that autumn *is* starting just as well, even if it’s still not all that clear which of all preparing autumns in the wings will be the one to start indeed this year.

sep21_10_640.jpg
sep21_11_640.jpg

September 5, 2021

Branching Trees under VaMP

Filed under: Coding,VaMP — Diana Coman @ 5:20 pm

Since there’s nothing better than heavy, real-life use to test any new tool, my 2 weeks old VaMP got to handle already all the various small and large, light and heavy, straightforward and even utterly gnarly codebases that I care about currently. While there was no trouble whatsoever from VaMP itself, the exercise did point out and basically enforced at times some further cleaning and better structuring of the code being thus inspected – and I count this as an added benefit of finally having a proper versioning tool!

The resulting trees are also so much clearer and easier to follow (for NOT having 1001 spurious “dependencies” in them, mostly) that exploratory branches or connected projects or even regrinds 1 of some set of patches simply find their natural and even *helpful* place in the complete tree, alongside everything else. If anything, it’s actually the visualization that lags now behind and is increasingly in the way, to the point that I suspect I’ll have to do something about it sooner rather than later, since it’s a rather ridiculous situation to have the supposedly-clearer picture end up unable to fully show what the underlying tool is capable of. Still, I might take my time on this, since after all my time really is my own and there’s no lack of interesting things competing for it.

Keeping for now the legacy visualisation and as an example, here’s the VaMP tree that branches off to obtain the latest base layer, VaMP or Eulora client. Note that with VaMP, even such a closely related set of branches that obviously share a significant number of files are nevertheless clearly and unambiguously separated (and no, not relying for this on the manifest file, either):

vamp_trees_1_640.jpg

For an even more obvious illustration of how much clearer VaMP trees can be, I intended first to look at the regrind of ye olde EuCrypt, since such a regrind allows at least a direct comparison of resulting trees, too, why not. This ran however quickly into another one of the old V’s issues, namely unintended branching forced on by the tool, like this: while the mpi component is added in the 2nd patch, it literally … vanishes from the “pressing” of any subsequent patches between 8th and 14th simply because these patches only add new files rather than changing existing ones. And since at that time there wasn’t any manifest file as a sort of workaround for this and I refused to just change some files specifically to compensate for V’s own problems, the effect is that for anything between the 8th and the 11th patches, inclusive, the user is forced to either make do with only a partial snapshot of the codebase or otherwise manually put it together out of 2 or 3 “presses” – just the sort of self-inflicted trouble that V provides. The V-tree of EuCrypt makes both the unintended branches and the forceful reunion of them all via the chapter 12 patch quite clear, too:

vamp_trees_2_640.jpg

Given the above, this regrind of EuCrypt takes therefore the shortest path: the first 7 patches match directly the old first 7 patches, but then there is simply one single patch to bring the code to what was the last published version of EuCrypt. Since the detailed regrind is anyway needed more for historical reasons than for any current practical use, I am really not inclined at all to sink more time into it merely for the sake of fully recovering each and every patch as it should have been in the first place. The good news with VaMP is that even if I decide to do a fully detailed, history-preserving regrind at a later time, there will be no problem whatsoever, as it will simply appear in the VaMP tree alongside this quick regrind, effectively as a more detailed, finer-grained alternative and quite obvious as such simply from the graph visualisation directly. For now though, the VaMP tree of EuCrypt has only 8 patches in total and is just a very straight line. Even so, there is perhaps enough contrast if you compare the first 7 patches with the original ones: in the VaMP tree, even these 7 patches very clearly and unambiguously follow one another in direct sequence, without any “alternative” paths between them, spuriously created by the tool rather than intended by the user:

vamp_trees_3_640.jpg

For a concrete example of VaMP in action, here’s how I made the first new patch of EuCrypt, as a regrind of the old eucrypt_genesis.vpatch (the listing includes the “pressing” with v.sh of eucrypt_genesis as well as the first cleanup required: all those initial README files were identical and therefore VaMP listed them all as duplicates; once this issue was sorted so that there were no more duplicates, the patch was swiftly created and duly signed, too, since something unsigned is not even a patch at all, by definition):

$v.sh press p1 patches/eucrypt_genesis.vpatch
creating eucrypt/README
creating eucrypt/mpi/README
creating eucrypt/smg_comm/README
creating eucrypt/smg_keccak/README
creating eucrypt/smg_rsa/README
creating eucrypt/smg_serpent/README
$mkdir eucrypt/v1
$nano eucrypt/v1/manifest.vamp
$vamp add 
ERROR: Main_V: Usage: vamp add dirnew patchfilename keyfile dirold
$vamp add eucrypt/p1/ data/patches/eucrypt_init.patch data/keys/***.priv eucrypt/v1/
Enter a password for key in data/keys/***.priv:
STATUS: Diff-ing directories eucrypt/v1/ and eucrypt/p1/ to patch data/patches/eucrypt_init.patch with hash length -1
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
ERROR: duplicates in eucrypt/p1/ files/dirs are not acceptable under V, sorry. Found to be duplicates in eucrypt/p1/:
 eucrypt/smg_comm/README
 eucrypt/mpi/README
 eucrypt/smg_rsa/README
 eucrypt/smg_keccak/README
 eucrypt/smg_serpent/README
ERROR: Main_V: Directory eucrypt/p1/ contains duplicates and/or empty directories and/or special files that are not acceptable under V, sorry. 
See the list(s) provided. Kindly clean these up and run V again.
$cd eucrypt/p1/eucrypt/
$nano -wF mpi/README smg_rsa/README smg_keccak/README smg_serpent/README
$cd ../../../
$ vamp add eucrypt/p1/ data/patches/eucrypt_init.patch data/keys/***.priv eucrypt/v1/
Enter a password for key in data/keys/***.priv:
STATUS: Diff-ing directories eucrypt/v1/ and eucrypt/p1/ to patch data/patches/eucrypt_init.patch with hash length -1
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
STATUS: Signing patch and writing to sig file data/sigs/eucrypt_init.patch.sig
STATUS: Patch written to data/patches/eucrypt_init.patch and signature written to data/sigs/eucrypt_init.patch.sig

The resulting eucrypt_init.patch is 57 lines long so not a heavy read by any measure. Moving on, the rest of the patches are created similarly, with the only annoyance being ofc that the duplicates issue has to be fixed for each of the old patches’ output since the old v is unhelpful as always. And for a check, one can simply “go” 2 to the output of this patch and then diff the directories:

$ vamp go eucrypt/v2/ data/patches/eucrypt_init.patch
using keys from data/keys signatures from data/sigs patches from data/patches, aiming to go from eucrypt/v2/ to data/patches/eucrypt_init.patch.
There are  1 trusted keys found in data/keys.
There are  11 patches included.
Creating the graph of all patches...
Reading/calculating indices for all patches...
Calculating all links between patches...
Allocating numerical ids...
Finding the shortest path from eucrypt/v2/ to output of patch data/patches/eucrypt_init.patch
data/patches/eucrypt_init.patch
The above set of patches will update eucrypt/v2/ to the output of patch data/patches/eucrypt_init.patch. Proceed (y/n)?
y                                                                                         
STATUS: Attempting to apply patch data/patches/eucrypt_init.patch on dir eucrypt/v2/      
STATUS: CREATING dir eucrypt/v2/eucrypt                                                   
STATUS: CREATING dir eucrypt/v2/eucrypt/mpi
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_comm
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_keccak
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_rsa
STATUS: CREATING dir eucrypt/v2/eucrypt/smg_serpent
STATUS: PATCHING file eucrypt/v2/manifest.vamp
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_keccak/README
STATUS: CREATING new file eucrypt/v2/eucrypt/mpi/README
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_rsa/README
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_serpent/README
STATUS: CREATING new file eucrypt/v2/eucrypt/smg_comm/README
STATUS: CREATING new file eucrypt/v2/eucrypt/README
STATUS: Checking for validity the resulting dir eucrypt/v2/
STATUS: Entering Walk_Dir with dirname=eucrypt
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent
STATUS: Patch successfully applied.

As for the manual check of the two directories, first at the hands of the old vdiff for the sake of using it one last time and then, rather more specific, via VaMP itself:

$vdiff eucrypt/p1 eucrypt/v2
$vamp diff eucrypt/p1 eucrypt/v2
STATUS: Diff-ing directories eucrypt/p1 and eucrypt/v2 to file listing_p1_v2.diff with hash length -1           
STATUS: Entering Walk_Dir with dirname=eucrypt        
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm                 
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi                    
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa                 
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak              
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent              
STATUS: Entering Walk_Dir with dirname=eucrypt                           
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_comm                     
STATUS: Entering Walk_Dir with dirname=eucrypt/mpi                   
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_rsa                
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_keccak             
STATUS: Entering Walk_Dir with dirname=eucrypt/smg_serpent                     
STATUS: Differences written to listing_p1_v2.diff

$more listing_p1_v2.diff 


UNCHANGED file eucrypt/README f95012efab511d8bcb069ce2676f236fda68421d6fc55a6e0e8682f4f16f
731b3dff9a1900012f92011d253c2749bd264ed493e33de8575c5b8a205ddea313108b93865717256127047fdc
23bd10f57fc577472965a7e893a031a5b1325077f619d2604b7fc83158ad9b06f3b3b069462bea26d7a8f78168
f2ae551198d156b6927d339a7f4ef20731892e8bfe6f370e2fd0d9621c4418b3ad67c9a0723b56be45f2a34285
9baa1539ac145eeddf327fa9e420aa4436bdeb4406a3cb7bb124a4bc9dfdcce17ca71b634550db8bc542013523
15af23e9eb9e7ff5565bb0c1182940202f271f6255cef0cb2aa63a008157de3763                        
UNCHANGED file eucrypt/mpi/README 581dbae69cf2aa6b42997b5e3fb9f551884f4b33a22280f8f3857a2f
10061a68b553b236355e63858975cad7c4ffb665f117c83d836b06a70c1d6523fd199ba2c1143a60196115e23a
050b705cd769ade2e629b01cbd65538b178654db8fb52506148d0008d57bd746516a39cd505e9d246e026d49d1
6ab166afdd68d29cc84c336e00286b6f2826d22c28632cec25efb3cd7532ae74f24fe5a4661f637c31fd843da9
f816dc820cc2d97237c25aec0a337d08e8c316f057e92345ef48d88c2ca21085230e0f30425f5ceef3f394901a
6db8ff2863ee3d2e2d09fdcac886d5f83d08117d59f4a77576e7ffaefaf327d1efb76d                    
UNCHANGED file eucrypt/smg_comm/README f7f739e8292418e621d2db623a7c7e5f1180a60145a89a72969
de8856eba2896faeed587a8c241d476a218b6dda753ed72693da5493fef065b49085e01dca130955f7fcb2aa79
a0c8d6e4436a188916f51504169a27eb021550dfc211a00dcecb28d24c9273526867533ee4490bb8115b298441
846cca7987d4b1395af49c3d1183fb090b5ee971194aa46a2de1f6656ee9b225fb6b58fad64ce8a9fa331688b2
021b36553f774047d1257a3d8905351f6bf57a87be4d4a6c42ff141a66f911c64ec8ef1eea18433e42856b4762
d7810db3010bd13799f426c591472abbf0693197501722114151eaafdc3efc36b1933cefb50               
UNCHANGED file eucrypt/smg_keccak/README 4a76c7a5aba2a4c181e6608764ac292a57e965c14ae41d7cf
57fd8ceaa09eeaf4d4cd8a14f3f8746a2f9f3f2130aab3becdfb37f8b3f8e2dbec59238aa58659325c9a676230
a7382168d1d252045e8b658945e854898c9f7fb413da95e0a7406b142518d3fa28992a595f71fe75f05575f288
e102fbe93af8f641cc5c1d57e081052585ed94957db79e607fe90cabdaada8ebd20eade5cee0eba43f8659e655
51f3c235f3cb899b7eeac503999594a64138cb781569274ec81813553ca5a2a18789fe2b5483aa7daeaeb7d360
29a250170d9379c0f3c4cb958164ad658df1feeddc963d854bbf552c91f901331520269edb388             
UNCHANGED file eucrypt/smg_rsa/README 8175ba70c4849627a412f9ebbef48f0bbc246d4c41533917d75a
03c081e516865d9670f6338259931908ba8a6c76f3684b21023d3affda0447b1877d871356b21fa065a26cab86
ed406be901e3b350c4495b5fb038198a19ffb9e63ed4eab99ab0edc802ae21fb3683862d2ac4cfb77765ed749d
4d52429597dc74a6908f19a357b660b8f6c245cdf8d705bf0980730fa1fb2837d93bcba88b04964e72d6904bea
0b956a91a9e65d41ab835903c19bb093ac7419b28b041ce42feba7a94cce169b4cb4319b430614826e68074aeb
5790c9a6a18a3ede90f1c6e0a327c1a647f237d3759849782d9ad812bb87d7cff22f447bbe
UNCHANGED file eucrypt/smg_serpent/README ba52bbe68a8d74e40f07218d3e8db179ff5567a6051491d5
e00c4e4e8d96f7b80ff64638df8b01bb0eb3413cb14edaa3c1e631ff8af280d5581e6ef5119fdb6ef073368b90
4027ed71973ed1516f32ab4136e3538a13d6df158c02f32403babd2504ad9929a60f3e2bcc4356128612d64b78
71ee89e1c6d397873833bb6ee68a824a0cadc5bb3aed8d37d2e116c790dc043f99fb3c47fd3be9175c81af6eeb
075a64b960057b4ad9cc42e56742ec978acb475aca5ba5fa5d67246883519b9b3d5732e04e633f71530e7ad5d8
436ef899c329e881f115e2e8ca52b69110e03658584e6574581f5485baac1b40c1ad91ad882e39
UNCHANGED file manifest.vamp 5cf22534fa176541099d83b47f34940b0ca9499d97777dc7dc9f789c8b56b
41c5d14f2b34c47371d62c0360ad0c35972db8e08a51ec445d0402c40f9e58aaa035331acab6621977ca34a6f7
32e2c2d764b59e1df94d73cdfc0c46f7fb7e1c382081e917d33773471303fd1cad7bfa17e792cc0ea99f92d37a
3f88414f4641bb3594571a512884aa3eb973b3b0f3f24436caa5f77237cb59e75a4df419960a64ba43716ea6c0
dd8cfd45378779e1b70f7929a43d850ded315cb778070cd92b58452de61ff639634d47af7546f8304f460164b6
7d4abe6549a226111ef7ba56611fc03664cbe439d81e92b66b78998cc64dca095

From the above output, you might be tempted to say that VaMP is more verbose than vdiff, perhaps. I think that the more accurate description though would be that VaMP is more explicit than vdiff and I’ll add to this that VaMP is indeed by design explicit rather than implicit, whenever possible. So yes, VaMP’s own “diff” command always provides a full comparison of the two inputs, listing not only what is different but also what is identical. And now that I finally have this explicit and very helpful tool, I don’t want to go back to the “implicit” way for anything in the world, either.

  1. Moreover, regrinding itself is not at all the huge pain that it used to be. And in losing the pain factor, it further gained in usefulness as it literally allows and supports for instance the gradual “digestion” of a huge initial codebase that may be perhaps imported first as a giant patch that gets nevertheless broken down into more manageable pieces as comprehension advances. In other words, VaMP can help indeed with code study and comprehension, too.[]
  2. While this name might still change, it’s both short and fitting enough for my current needs, since what one wants is to get to the *exact and guaranteed* result of the specified patch, as simple as that. So VaMP will simply go from where the code you give as input happens to be to where the patch takes it – provided that there is a fully valid path (possibly involving multiple patches) that verifiably gets you there, of course.[]

August 23, 2021

It’s Called VaMP

Filed under: Coding,VaMP — Diana Coman @ 11:35 am

For code that is important to you, for code worth reading and not merely executing, for code whose history and references are meaningful and whose authors you’ll *want* to know, interact and work with, there is now VaMP. For all other code, there are all the other versioning systems and if those fully satisfy your needs, then enjoy them as they are and good luck to you.

VaMP provides a wide range of support for coding as an intellectual activity, from verifiable, indelible and accumulated history, authorship, readership and investment of trust to smooth exploration, pooling of resources and collaboration that may be as deep and intricate or as superficial and plain as those involved care to make it at each step of the way. All code and work in general is thus securely anchored in its context at all stages – the provenience as well as the accumulated history matters for any versioned product, whether code or anything else. There are hard, cryptographic guarantees on the full state of the codebase at any version but the value and meaning of these is derived, as it should be, from the expertise and reputation of those that issue the guarantees in the first place. And on this support of visible, verifiable and indelible history of activity, one’s own reputation can be built and continuously accumulated so that no useful effort need ever be lost and expertise as well as usefulness can be more easily identified and rewarded at every stage.

For the concrete implementation of the above, VaMP relies on my previous regrind and updated implementation of old Unix’s diff and patch as well as the full cryptographic stack that I had implemented for Eulora (a first version of which you can find discussed in the EuCrypt category). VaMP is based on Mircea Popescu‘s design, hence the MP in the name. And since it was the infuriating broken state by design of the V tool that made me start the work on this in the first place 1, I’m preserving it as the first letter in VaMP’s name, to acknowledge that the experience of using V provided indeed the perfect help and motivation to finally move away from all its misery.

As to how VaMP works in practice, the short of it is – very smoothly and extremely usefully indeed! It’s a pleasure to have it produce patches and signatures, check signatures, find and apply the relevant patches for any given task and even create essentially “branches” for exploring some changes to the code, all from one single command line tool and without the need for any additional scripts and hacked “a” “b” or hidden directories or whatnot. As a little but very helpful bonus on the side, it’s even more satisfying to have it quickly check even a large legacy codebase and spit out neatly listed any and all broken bits and pieces that have to be fixed as a minimum requirement for the pile to be even considered worth looking at by a human eye. If you are curious, such broken pieces include all empty files and empty directories but also duplicate files and broken format files. And if you wonder “but how can it create the first patch, if it won’t accept an empty directory as input”, then rest assured that it’s possible and otherwise keep wondering until you figure it out – it’s good mental exercise! Or maybe start interacting and doing enough useful things so you get to the point where you may actually use VaMP and then it will all fall in place gradually and naturally anyway.

As a possible hint for the above mystery and to give one illustration of use, at least, note that VaMP can and happily does find precisely and exactly the relevant patches for a given task even out of a large pile of patches that might be related or unrelated to any degree. This is not by accident but a direct consequence of the fact that VaMP is by design a tool meant for real-life scenarios (these tend to involve people working on more than one project at times, go figure!) and a tool that works *for* you, not against you. As such, far from requiring that you mould yourself to fit computers’ limitations 2 what VaMP does is to harness the computer’s resources for your benefit. In this specific case, what this means is that VaMP can indeed handle any pile of patches and never chokes on them no matter how related or unrelated they might be. It works correctly with any set of patches just as it works correctly with any graph that a pile of patches might make – the meaning of it all is very clearly, strictly and fully defined at all times so that one can even get a correct snapshot of *all* their codebases at the same time, shown side by side as either independent or connected trees (or even graphs, gasp!), as the case might be. Here’s just one small example of the simplest sort (unconnected trees), from some of the initial test-uses (and yes, the first tree on the left is the one of VaMP itself):

vamp_1_640.jpg

In short and in conclusion, with VaMP, coding can be both fun and intellectually satisfying, once again. As it always tends to happen with any activity – it can become a pleasant thing to do indeed, but if and only if you have the correct tools and are working with the right people. And the two are more related than you think!

  1. In the end it didn’t take 3 weeks but 3 months, all in all and even *all* considered (and there is, sadly, a lot more considered in there than was initially the case; such is life). To put this into perspective though, do note that it took as long as 6 years for v to not get anywhere past its broken state, it’s an achievement of sorts, too.[]
  2. In general, moulding to the computer’s limitations happens every time when you have to look for a workaround to still achieve what you were trying to achieve in the first place when you hit some “can’t do X” restriction. For example and taken straight from the V experience: you can’t change a file back to a previous state because omg, the machine is confused and won’t know how to order the patches correctly anymore. While V decrees in such situation that “you can’t do that, you are also an idiot for wanting to do it”, VaMP instead makes sure that the machine is *never* confused, that everything still works correctly in such a situation as well as in any other that might arise within the scope of the tool and then it lets you do exactly what you want to do, providing also full support to see exactly what you are doing.[]

August 8, 2021

Begin non-pgp message

Filed under: Coding,EuCrypt — Diana Coman @ 1:33 pm

$ ./keys encrypt plain.txt data/keys/*****************.pub

-----BEGIN NON-PGP MESSAGE-----
aae0eecc27c78efb65ddb0cb977330ca588796353d3634eaeaca0482db312a6405aa044dd38ec3b7
22d22d523f30911d660898404b164d3e0a7dbb09bf977183823818dce811a7d8a62125f3b6abd278
7148f03de27860f77e33c09e5916dd06943a11562ca6dc38dd7406133878c08b6727c9883208a173
665faaf51c58d00c0c3fdb25defe48394f918b075bb1a48d684b6c4ccb0c2d0e94ef96c1057bbfcd
b05001ce01d50f6af8c49122ab765f148af228fbc89d2c7f5accaff3499447d3a10e8c034ef44e9a
956e7732c453cb040b019f6d239a0d992523cf11d5aff816d59ac7f066d1f0a315340a9eff2bd182
a8a7ade55b937b216133f0e2de80cae63b5aa1776e7788437cf83af2706afad42d567f0a61ecfc58
73453e5a72f1a311d2914f1aabe0ec855c270cd12c65a2b086eb5a4457c026f8d44a4a72ca102826
2aba52d483d6ccd3a3a5dcfb0ad1c1f3fdad6769ed1b0df529c3936125c1192a7117a26b20af3a64
1b712db591e4495360531571ec999f183f639a03edebb0a0d2427f0158077822e5b955a5179cf36d
5853b16c60ebf6060cb4347488f3b41a820be0cb91cb90c108106c6c196f2ebf2c1dcbfed870572f
939973dad085af441e1fd15989331694910e1d8ed731b895df91c09ff80ef86392ad00e6f2564122
67712a5b64fb440631cc
-----END NON-PGP MESSAGE-----

Need I say more?

July 20, 2021

The Drawbacks of External Financing

Filed under: Dark Modern Ages,Outreach — Diana Coman @ 9:44 pm

~This is my translation of a 2011 article on Trilema: Dezavantajele finantarii ~

As an entrepreneur, one of your best possible moves is to obtain external financing.

Such a move has several positive effects, for instance improving the morale as well as the financial security of the development team, confirming publicly the potential of the business as well as the competence of the team, serving as a bit of de facto publicity. These are all minor advantages. The major advantage is the practical application of the intelligence and the professional competence of some people that are significantly better paid than the entrepreneur himself, let alone his team.

These advantages depend of course on the quality of the respective investors and the extent 1 of their involvement. If the investor is an angel 2 who can be, after all, simply a rich uncle or some rich heir from among the wider circle of friends and acquaintances (which tend to cross more easily during adolescence the social borders that become more dominant later on in an adult’s life), then the advantages will be commensurate. Generally speaking, an angel cannot contribute very significant funds, not necessarily because of lacking them but mainly because of being unable to justify to themselves the taking of the corresponding risk.

The reason why an angel can’t justify such risk comes from his inability to assess the project in depth and this inability comes in turn from a poor understanding of the project’s details as well as of the project’s relevant context. The 3 rich man is interested in driving his own car (because he can’t just hire a chauffeur for that) and toeing the line of public sentiment (because he doesn’t know the usefulness of well-chosen spy-assistants). As a result, he has no time (which is to say he has no interest and even less ability) to follow in detail what one citizen-billionaire 4 vividly described as “these children’s nonsense”.

If the investors are, however, an investment fund (as it happens in America only, since we 5 don’t have such things) and especially if the investment happens in a properly structured way, with all the various steps involved in what is called a financing round (term that I won’t even attempt to start defining as the gaps in the Romanian context are just too fundamental to bridge over) then the entrepreneur will enjoy the full benefit of what I mentioned earlier, namely the intelligence and professional competence of people that are paid significantly better than the entrepreneur himself, let alone his team. Because indeed, a board member who is also a partner in an investment fund receives millions in annual salary, which is never ever the case for an entrepreneur, no matter how senior. Moreover, such a board member also knows directly, as friends or at least acquaintances, all the other people just like him, which is again never ever possible for an entrepreneur, given that there are thousands of partners in investment funds but millions of entrepreneurs.

The benefits that the aforementioned financier can bring to a project are of two types: proper and toxic. The proper type of benefit is the direct representation of the project to the capital. The rich uncle or the heir-friend cannot provide this sort of representation because nobody listens to them. What do they know? By contrast, if a financier backs a project with firm and at least superficially verifiable statements that correlate with success… then it’s done. The market (hence, not merely the other financiers but the market directly) will accept these statements as correct and that’s it. That’s it. They become real, just as real as Groupon being a successful project without actually being one, just as real as broadcast.com being worth six billion dollars without being worth as much, just as real as hundreds and thousands of other examples. The market is, on the short term, a voting machine.

The toxic benefits are the financier’s abilities with respect to organisation, representation and management. This part can go both ways: on the one hand, some entrepreneurs are simply total idiots when it comes to the management and organisation of a business. This is just how they are and the example of Imagine is illustrative. In such cases, the intervention of a calm hand directed by a mind capable of seeing beyond the nearest trees is simply salutary. The Fred Quimby example is even more illustrative of this, as is the counterexample of 3D Realms. On the other hand, discipline is always the enemy of creativity (although not from fundamental causes but mainly because of the poor upbringing of creative children) and therefore the results can be at times dreadful.

A good example for all the above is a situation that we can finally discuss now because indeed, the whole discussion up to here has been merely an introduction. The extent of lagging behind is quite remarkable when a cultural space requires 700 6 words of introduction to simply get to the point where one can finally discuss a business problem. Still, the example comes from a discussion with a friend regarding the recent improvements to fain 7. The friend in question being a person with a solid understanding of theoretical underpinnings of reality, the discussion focused mainly on mathematical representations and other theoretical approaches, as opposed to more direct considerations of the woods and its trees. Nevertheless, there was also one notable exception that pierced through the whole theory and went all the way to the very core of the matter:

It’s interesting to observe with respect to the motivation by means of karma points that the dialogue will not move to dtng although it has there the optimal conditions to carry on and moreover there are no limitations there for the producers of 10.000 messages/month.

Indeed, I also find this very interesting. I also know why such move never happens: people don’t want to express themselves inside a broom closet, they want to express themselves outside, in the public square. Mommy! MOMMY! LOOK AT ME! People who talk a lot want the attention of others and therefore dtng is not the right place for them or at least not yet.

The above observation also points out the obvious cause why mere liveliness cannot be the goal on fain, just as it cannot be the goal anywhere: someone has to read it, too! If nobody reads it, then what’s the point in writing it?

This is a strategic mistake that facebook or twitter for instance failed to avoid and, as a result, this is the main complaint of their users: that anyway, nobody reads what they write. Mainly because it’s not possible to read. Because there’s too much noise. How did it get to such situation?

The toxic benefits are the financier’s abilities with respect to organisation, representation and management. Since the only measurement currently used for representing businesses in the Market is the number of users, the amount of activity, in short the liveliness, the financier will put pressure on optimising (in the sense of increasing) the liveliness. At the expense of anything else. Of absolutely anything and everything else. If the number of messages published monthly on twitter increases from 10 million to 10.5 million, the financier will conclude that the service is progressing well. Even if the average number of people reading one given message decreased from 10 to 0.1 and even if this means that next month the whole thing will fall off a cliff and collapse entirely.

Economics is the science of optimisation but it never optimised anything other than what is measured and that’s why it’s perfectly capable of producing disasters such as the one on Easter Island. Economics cannot pursue the “good” in itself – all it can do is to pursue very elaborate versions of intellectual masturbation labeled as “good”. As a result, economists need entrepreneurs to provide what is called vision: the ability to intuit and moreover to correctly intuit the good itself beyond a smokescreen of numbers. By contrast, entrepreneurs don’t really need economists: their gifts are too often toxic.

If I had investors on board, I could never have imposed a measure such as the one discussed above without shouting, table pounding and other violent actions. And probably they wouldn’t have given in anyway, being stubborn as all financiers are and so we’d have quarreled. The good news is, of course, that Fain is out of the zone where the team’s incompetence might have sunk it, except it didn’t and entering thus the zone where the investors’ incompetence might have sunk it, except it didn’t. Or at least it didn’t just yet.

The disadvantages of financing are that you tie a stone around your neck and that stone has the absolutely diabolical property that it can’t be correctly measured ahead of time. To explain this by means of a metaphor, you accept a stone of 5 kilos, you calculate correctly your own strength and you go to the gym to fully prepare etc., after which, knowing full well that you can swim with a 5 kilos stone tied around your neck for a distance X, you start swimming for only Y where Y is not even half of X, so everything is truly thought out very well indeed. But then the Y distance turns out to be in practice through the swamps among the mangroves and the stone turns out to be a railway tie. So you drown, dragged underwater not by the weight of the stone but by its shape. Who would have predicted that?

Eh, the experienced entrepreneurs are the ones who would have predicted that. In other words, you. From now on, you.

  1. Funnily enough, the original text sounds back-translated from English to Romanian at this precise point. The “extensiunea investitorilor” would be a rather puzzling notion by itself to a single-language Romanian speaker except that none such is really likely to make it as far as the second paragraph in this sort of article to start with. For everyone else, the sense is anyway directly available and so it doesn’t really register at the usual read, it’s only at translation time and even then rather belatedly that it stands out, basically at revision time (translator’s note).[]
  2. This term’s translation to Romanian should be “deranged person”, I think.[]
  3. The Romanian “deh” that starts this sentence in the original text is not all that easily translated to English. Happily for me, I have already used it in the best possible place so that the very author whose text I’m translating here provides himself the explanations and attempted translation of deh to English, too. And to make it even more confusing, note that I’m using his previous translation of my own words to support my current translation of his own words that were however previous to my use -at least the one that got translated- of that same word! This is most definitely and entirely a translator’s note. Which translator’s?[]
  4. The linked article includes the transcript of a conversation in which a Romanian billionaire (in euros) at the time (later inmate) clearly states -for the benefit of the young counterpart- that he intended to buy the kids in question, not to do business with them as they and the counterpart seemed to keep misinterpreting it. Back in 2011 when the original article was written, this model of a “rich man” and his interests was rather visibly a direct description -and direct derision, too- of what passed for a rich person in Romania around 2011. Meanwhile, this exact model seems to have become so common across the world that I don’t think that there’s any loss to the overall argument even when crossing the language border directly like this from Romanian to English (translator’s note).[]
  5. Again, this “we” here used to stand in 2011 for Romania only and the original article means it as such but meanwhile I think it rather stands for a much wider space, so I’ll leave it in text exactly as it is (translator’s note).[]
  6. Hah, the 700 words of introduction to the Romanian article caused by the lagging of Romanian cultural space behind the American cultural space became… closer to 800 words of introduction in the translation of the text to English. This lag thing turns out to be a very stretchy thing in practice (translator’s note).[]
  7. The Fain project focused on improving the quality of Romanian blogs and it had at the time a very lively and active community that included readers and commenters as well as bloggers. The improvements mentioned here basically reduced drastically the benefits (as measured in “karma” points that were in turn redeemable at the time for money) of multiple comments by the same person beyond a threshold of 150 within a given interval (translator’s note).[]

June 30, 2021

Shocking News and Unbelievable Revelations!!11 (NSFS)

Filed under: Dark Modern Ages — Diana Coman @ 6:00 pm

One more outrageous than the other and NSFS 1 to boot, here are revealed several shocking facts that most of the press seems to be still unaware of:

1. Mircea Popescu was never Polish! Also: there are several countries in Eastern Europe, each with their own name, language, people and culture. Even more shocking, this has been going on for quite some years already and there are no signs of it stopping either, despite so many people getting it wrong in writing so many times. How can that be? It’s a mystery.

2. Diana Coman was never a Web Developer! In fairness though, she did coin, in a collaborative effort with Mircea Popescu, the term Weird Warts & Workarounds (WWW) to fairly describe the current state of the Web. It’s a backronym.

3. Mircea Popescu was so “enigmatic” that he wrote for years, exhaustively and with ample illustrations, too, on just about any topic. For those not able to read a text for meaning nor able to focus for more than 5 minutes at a time, all that business of writing and scholarship are extremely enigmatic indeed. It’s a pain.

4. Mircea Popescu already answered some years ago, the questions that some are only now thinking of asking. For the benefit of “the press” and all those who are so keen now to “write about him”, I’ll quote here his answer from 2017 that is in turn quoting an even older answer to this eternally rediscovered question (the original is in Romanian, while the translation to English quoted below is by Mircea Popescu):

Refuz ca micul meu volum pentru neghiobi si gura-casca pe banderola sa-l rezum. De vor sa stie ce si cum, sa faca bine sa-l citeasca!

“I refuse to summarize my work for the benefit of the vaguely-interested jwzs. If they want to participate in the life of the spirit, let them fucking read it!”

  1. Not Safe for Sex[]

June 24, 2021

Severed

Filed under: Conversations,Lyf — Diana Coman @ 12:35 pm

This is how the unexpected end feels right now, like a suddenly severed link to source and to essence. And what a link it was!

It’s been 12 years since we first met, Mircea Popescu and I, as much as meeting may mean online. These 12 years have passed, but not quickly, nor “in the blink of an eye”, no, for they have been full and intense and ultimately transformative, despite the supposed limits of this online medium. Because indeed, we interacted mostly over these modern wires that carry themselves, appropriately enough, exactly light and dark, as he aptly observed once. Out of light and dark though, everything is ultimately shaped and our initial flitting touch persisted and grew organically into an ever more intricate and complex link. In time, it became even strong enough to bear so much more than one fun and enlightening conversation 1 and even more than one project on which we worked together.

Through it all and at every juncture, he has been incredibly supportive and protective of all healthy growth, clearing the space for it with fire if and when needed, unerringly generous with his time, his vast experience and his superior understanding that pierced to the core of the matter and then came back reliably, each and every time, with the correct and solid model on which everything else rested suddenly at ease, suddenly ready to carry one even further, to what had seemed out of touch only just the moment before.

There was all the above and more to it. That beast, mellifluous, belovable, utterly beastly beast of an ocean, as he called it, did steal it all in the end, though. What’s left now is the legacy and, perhaps, as much as I could grow with it so far. Whether it’s enough or not, I can’t tell, but as with all I ever got, I’ll try as hard as I can to make the most of it, too. What will come out of it further, now that the link to the source of it all has been severed, I don’t know, nor can I quite begin to think much of it just yet.

I’m grateful for having journeyed together as long as we did and through the numbness of it all, there’s also the warm glow of knowing that he enjoyed my company, too. While the world is for now a darker place, life still remains the burden and the war that he knew it to be and that he enjoyed fully, although he had no illusions about its end:

Indeed, exactly so : what for an entire world, of my own death ? 

So it is indeed and there are no better fitting words that I can find for it all, either:

El nu e mort! Traieste-n veci,
E numai dus.
N-am cap si chip pe toti sa-i spui
Si-as spune tot ce stiu, dar cui?
Ca de copil eu m-am luptat
In rand cu Volbura-mparat
Si stiu pe Crivat cel turbat
Ca tara lui.
Ce oameni! Ce sunt cei de-acum!
Si toti s-au dus pe-acelasi drum.
Ei si-au plinit chemarea lor
Si i-am vazut murind usor;
N-a fost nici unul plangator,
Ca viata-i fum.
Zici fum? O, nu-i adevarat.
Razboi e, de viteji purtat!
Viata-i datorie grea
Si lasii se-ngrozesc de ea –
Sa aiba tot cei lasi ar vrea
Pe neluptat.
De ce sa-ntrebi viata ce-i?
Asa se-ntreaba cei misei.
Cei buni n-au vreme de gandit
La moarte si la tanguit,
Caci plansu-i de nebuni scornit
Si de femei!
Traieste-ti, doamna, viata ta!
Si-a mortii lege n-o cata!
Sunt crai ce schimb-a lumii sorti,
Dar daca mor, ce grija porti?
Mai simte-n urma cineva
Ca ei sunt morti? 2

  1. From when it all started to very recent and there’s much more published in between and a lot more unpublished, too.[]
  2. Fragment from Moartea lui Fulger, de George Cosbuc. Mircea Popescu published the phonetic transcription and a translation to English of the full poem.[]

June 18, 2021

A Sneak Peek at SMG-Patch in Action

Filed under: Coding,V — Diana Coman @ 1:12 pm

After mapping the old diff, the next step was to implement the new diff at file as well as directory level and then to implement the opposite operation too, namely the application of a patch. It took me a bit more than a week and there have been even a few iterations on parts of it but the work has been quite satisfying indeed, mainly because I finally got thus to clean all sorts of warts, weirds and workarounds (www!) 1 that the original diff and the patch format and all of it really had baked in. Such www as diff preserved unchanged since the 1970s 2 are mainly due to limitations – whether of hardware, software or even knowledge – that were indeed very real and relevant 50 years ago but are not all that relevant today anymore. So they got exposed, looked at and discarded as part and parcel of making the new implementation. This is after all exactly what re-implementing something is all about – not just a makeover or mere change of language, nor even just an effective adoption 3 but a rejuvenation in a quite direct sense: the old idea is cleaned up of what is not useful or needed or working anymore and gets connected meaningfully to new things so that it can indeed grow again rather than merely exist.

As there is still work to do 4 on the remaining bits and parts required for a full SMG-V, I won’t attempt just yet a full list of all the cleanups, changes and additions. Nevertheless, I’ll share a sneak peek of how a few test runs look at the moment for the part applying a patch and see if you can spot any differences already at this level.

First run on a valid patch and with a correct input to apply on:

./patch_smg test.vpatch tpatch/
STATUS: DELETING file t4/vref.txt
STATUS: DELETING file t4/t9/fother.txt
STATUS: DELETING file f2.test
STATUS: REMOVING dir tpatch/t4/t9
STATUS: REMOVING dir tpatch/t4
STATUS: CREATING dir tpatch/t3
STATUS: MOVING file tpatch/t2/smgv.gpr to tpatch/smgv.gpr
STATUS: PATCHING file f1.test
STATUS: CREATING new file tpatch/t3/restrict.adc
STATUS: CREATING new file tpatch/yet.txt
STATUS: CREATING new file tpatch/t2/f1.test

For a taste of basic error reporting, attempting to re-apply that same valid patch only to the *result* of the above patching (hence: the input will not match, of course):

./patch_smg test.vpatch tpatch/
STATUS: DELETING file t4/vref.txt
ERROR: Main_Patch: Invalid line no  2 in patch test.vpatch : file "tpatch/t4/vref.txt" does not exist

While there are many different errors waiting to happen at any time, there are also many different checks and reports to help identify the source of any noticed mismatch. Here’s only one more example for now, when running on a patch manually messed up with only one tiny change of a single number:

./patch_smg test.vpatch tpatch/
STATUS: DELETING file t4/vref.txt
STATUS: DELETING file t4/t9/fother.txt
STATUS: DELETING file f2.test
STATUS: REMOVING dir tpatch/t4/t9
STATUS: REMOVING dir tpatch/t4
STATUS: CREATING dir tpatch/t3
STATUS: MOVING file tpatch/t2/smgv.gpr to tpatch/smgv.gpr
STATUS: PATCHING file f1.test
STATUS: CREATING new file tpatch/t3/restrict.adc
STATUS: CREATING new file tpatch/yet.txt
ERROR: Main_Patch: Invalid line no  284 in patch test.vpatch : Mismatch between
 hunk's header and the number of added lines to newly created file.

Worth noting perhaps that none of the tmsr vpatch files will pass muster as far as SMG-V is concerned and good riddance. I certainly don’t intend to read anything in the old format anymore and there’s not going to be any automatic conversion of anything either – at least not under my signature.

The above gives perhaps some hints as to some of the changes in the format of a patch mainly but there are even more significant changes under the hood of it all since the whole point is to finally have V as it’s meant to be – not just in parts and name and how the 1970’s code might permit. At the moment though, this is all you get to see, since I’m still rather busy with the remaining work and I can’t wait to finally have a working V that helps rather than hinders me. Not to mention that all this SMG-V code could really do with some V-versioning of itself, already!

  1. There, while at it, here’s this www acronym fixed as well, since the warts, weirds and workarounds looks to me like a much better fit by now than any original worlds and wide and web ideals.[]
  2. Yes, the original diff was written in the 1970’s and that makes it indeed older than myself.[]
  3. Though even this is quite rare as far as I can tell, probably since it requires first getting to know the old, useful thing and who has the patience for that or something.[]
  4. Funnily enough, I can’t even say that “I was busy and didn’t write for more than a week!!” since I wrote actually quite a lot. Only… none of it on the blog and relatively little of it that is not code-related (if not code directly, then comments, notes and discussions about code).[]

June 9, 2021

The Map of Diff’s Output Code (or Why Nobody Wants to Read That Ever Again)

Filed under: Coding,V — Diana Coman @ 11:28 am

The best part about the old diff implementation from Unix’s diffutils package 1 is that it’s visibly the result of a thinking process (as opposed to merely key-pressing) and otherwise relatively short by modern standards. I strongly suspect that both these qualities have nothing to do with the language of choice (C in this case) and rather all to do with the fact that at the time this code was written, people still *expected* rather implicitly that code will be read, not only blindly executed 2.

Being thus a structured piece of code as opposed to a sprawling mess of monkey managers and other droppings, one reasonably expects to be able to follow a thread through it all and thus figure out in detail the exact way in which it all works. In practice, it turns out that this expectation holds for some parts 3 but not quite for all. The place where it all rather screams of “everyone just gave up and wanted to be done with it already and good riddance” is, perhaps unsurprisingly, the code handling the writing of a diff patch/file. In other words, the messiest part is the communication of results in a form suitable for human consumption. Basically there are about 500 lines of code 4 doing the “difficult” work of finding out the shortest edit script to change from one file to another and then there are *all the other lines of code* in a whole bunch of files, trying to handle somehow -anyhow!- the “easy” task of input/output so that the result of that work becomes indeed useful at all to a human user.

As a result and illustration of the above, the whole output of diff starts innocently enough with a simple call from analyze.c of print_context_script. That print_context_script is a method found in context.c and calling it launches one on a dizzying see-saw between context.c and util.c for no less than 15 calls even when the whole code is cleaned of all sorts and reduced to its most basic. So how exactly is one supposed to understand just what is output, how and when? Glad you asked – the only way that works is to follow it all, map it out clearly enough and then go through it line by line and word by word, adnotating and reviewing as many times as needed until all is clear indeed and without remainder. Since I did exactly this, given that it had to be done, here’s the extracted map of calls (page numbers are based on my printing of the code so take them with a grain of salt), followed by a picture of how I even got to figure it all out quickly enough, anyway (since I’ve been told I never uploaded pictures of my hand writing, here’s this lack fixed – have one with my writing and even my colouring, too):

  1. print_context_script (context.c, p1)
    1. print_script (util.c, p5)
      1. find_hunk (context.c, p4)
    2. pr_unidiff_hunk (context.c, p2)
      1. analyze_hunk (util.c, p8)
      2. begin_output (util.c, p3)
        1. print_context_header (context.c, p3)
          1. print_context_label (context.c, p1)
            1. bin2hex (context.c, p1)
      3. print_unidiff_number_range (context.c, p2)
        1. translate_range (util.c, p7)
          1. translate_lines_number (util.c, p7)
      4. print_1_line (util.c, p6)
        1. print_1_line_nl (util.c, p6)
          1. output_1_line (util.c, p7)

diffcode_1_640.jpg

  1. This map is based on diffutils-2.8.1.[]
  2. For the wider context on this, see the whole Coding category on this blog. For just a starter article, see perhaps The Bugureaucracy. While there’s a lot to be said about it all, to keep this footnote from exploding into a whole series of articles, I’ll just note one tiny leaf of it all, namely that any “programming course” that focuses on code writing rather than code reading first and foremost is but a course in spamming, by another name.[]
  3. Mainly the cleanly mathematical ones as it were, with the neat result that it was a breeze to follow the implementation of the core algorithm of diff-ing aka Myers’ algorithm.[]
  4. The diffseq.h file.[]

June 4, 2021

Oh, GNAT, Why Do You Overflow Your Stack?

Filed under: Coding — Diana Coman @ 5:14 pm

Claimer, disclaimer, motto and all else: I do NOT want to write an Ada compiler.

Truth be told, I do not even really want to write (yet again!) about bugs and poor implementations and unexpected errors of all sorts. But given how easily I find them these days without even looking, they really want to be written about, to be finally brought to some light, to be seen and acknowledged at least, no matter how harshly judged or how negatively evaluated – anything, anything at all rather than the sad, endless lingering in the shadows, unseen, unmentioned, unnoticed, forever hidden among thousands and thousands of lines of code that nobody really wants to as much as look at ever again. Can you even blame the errors for wanting to be seen, perhaps even, one day, if they are very lucky indeed – to be fixed?

Deep in the 360M of GNAT’s code and according to the heavy tomes of reference on the matter, there are thin Ada bindings 1, thick Ada bindings 2 and even supposedly Ada-native packages for input/output of all sorts 3, from humble files on the disk to supposedly abstract streams. All of these can in theory handle everything and anything one might need. In practice, as it tends to happen whenever piles of code implement tomes of documentation, both the everything and the anything are rather severely and unexpectedly restricted. For instance: yes, you can supposedly read and write “any elements you define” with Direct_IO that allows even read/write from/at arbitrary positions but should you take that seriously and go about trying to write for instance as large an element as a mere 32-bits integer type allows, what you’ll get is not the file’s contents but an unhandled stack overflow exception when calling Direct_IO’s Write method, have a look (first the code then the result of running it):

  sz: constant Integer_32 := Integer_32'Last;
  type Bytes is array(Integer_32 range <>) of Unsigned_8;
  subtype SzBytes is Bytes(1..sz);
  type ptr is access all SzBytes;

  procedure direct is
    package ndir is new Ada.Direct_IO( Element_Type => SzBytes);
    use ndir;
    n: ptr := new SzBytes;
    f: ndir.File_Type;
  begin
    Put_Line("Direct IO attempting write with element size " & sz'Image);
    n.all := (others => 10);
    Create(f, Out_File, "direct_io.txt");
    Write(f, n.all);
    Close(f);
    Put_Line("Direct IO wrote file with element size " & sz'Image);
    Delete(f);
  exception
    when others =>
      if Is_Open(f) then
        Close(f);
      end if;
  end direct;

./direct_io_fail
Word size is 64
Attempting instantiation of Direct_IO with element size 2147483647

raised STORAGE_ERROR : stack overflow or erroneous memory access

Note perhaps that the cute number there, right before the STORAGE_ERROR outrage is a perfectly valid 32-bits integer, not even going above this magic limit of 4 octets, nevermind that the poor underlying OS is 64-bits. But is it truly impossible to write with GNAT 2147483647 bytes to a file? Does any other GNAT package know how to do it silently and *without* raising exceptions? Anyone at all? Why yes, there you go, Sequential_IO running on the same machine *can* do it, wonder of wonders (and I suggest someone fixes it so that it fails too, lest it overthrows the curve and raises barriers to entry or something):

  procedure seq is
    package nseq is new Ada.Sequential_IO( Element_Type => SzBytes);
    use nseq;
    n: ptr := new SzBytes;
    f : nseq.File_Type;
  begin
    Put_Line("Sequential IO attempting write with element size " & sz'Image);
    n.all := (others => 20);
    Create(f, Out_File, "seq_io.txt");
    Write(f, n.all);
   Close(f);
    Put_Line("Sequential IO wrote file with element size " & sz'Image);
    Delete(f);
  exception
    when others =>
      if Is_Open(f) then
        Close(f);
      end if;
  end seq;

./direct_io_fail
Word size is 64
Attempting instantiation of Sequential_IO with element size 2147483647
Sequential IO attempting write with element size 2147483647
Sequential IO wrote file with element size 2147483647

Funnily enough, GNAT is sortof, kindof aware of the issue, only not quite of the full range of it, it would seem. For if one is even bolder than before and asks for an even larger element (anything above 2^33 apparently), GNAT itself points out that Direct_IO insists on not using references ever and storing instead everything locally, thus predictably overflowing the stack in short order:

gnat_fail_direct_io/io.adb:26:9: error: total size of local objects too large
gprbuild: *** compilation phase failed

Digging deeper into GNAT’s own source files though yields ever more interesting comments related to this magical 2GB limit for handling files. There is first the comment related to obtaining the *size* of a file, straight from adaint.c 4, aka GNAT’s own wrapper of various C lib functions (in this case it’s in the wrapper attempting to get various attributes of a file, via stat):

    /* st_size may be 32 bits, or 64 bits which is converted to long. We
       don't return a useful value for files larger than 2 gigabytes in
       either case. */

If the above is perhaps not interesting enough for you, don’t despair, for it gets better, here’s another one, this time from that thin binding over C read/write function, so head over to i-cstrea.adb (in the same dir as the previous file) and read from line 84:

   type Byte_Buffer is array (0 .. size_t'Last / 2 - 1) of Unsigned_8;
   --  This should really be 0 .. size_t'last, but there is a problem
   --  in gigi in handling such types (introduced in GCC 3 Sep 2001)
   --  since the size in bytes of this array overflows ???

At least it’s all quite entertaining by now, if in a rather absurdist manner – for the layers upon layers of wrappers, the main thing you get is basically more layers and layers to unwrap in order to find the source of the error when it manifests (and then laugh at it for there isn’t all that much to do about it, when it gets all the way to somewhere in the gcc, is there?). While some enjoy unwrapping even such surprises, I confess I don’t quite see the point to it. So I’ll skip all the wrappers with their promise of future time spent unwrapping and I’ll go at least straight for the very same lib functions that are used anyway – at least I’ll use them directly and thus know faster where the trouble is, if indeed there still is any.

  1. E.g. Interfaces.C.Streams in i-ctrea.ads/adb, which literally imports the usual C library functions for file handling, such as fopen, fwrite, fread, fclose.[]
  2. Basically *all* of Ada’s “IO” packages (e.g. Text_IO, Direct_IO, Sequential_IO) are nothing but thick bindings of the C library functions, at best, or rather at longest, since that’s what it is each and every time: how many layers of packages do the calls go through in order to arrive anyway at the same basic C functions on which all rely to do the work.[]
  3. Ada.Streams, supposedly an abstraction of both message and medium – in practice though they bring in so much luggage of the exact sort that I don’t want to have around ever again if at all possible that I don’t even have them on the list as usable at all – they got mentioned here for completeness and nothing else.[]
  4. In a standard installation of Adacore’s GNAT, you’ll find it in /usr/gnat/lib/gcc/x86_64-pc-linux-gnu/4.9.4/rts-sjlj/adainclude/ or, if you still use zcx, then in /usr/gnat/lib/gcc/x86_64-pc-linux-gnu/4.9.4/rts-native/adainclude/[]

May 30, 2021

A Midweek Ride and Other Shockingly Nonstandard Habits

Filed under: Lyf,Young, old and oldest — Diana Coman @ 8:39 am

The best thing about crowds is that they are entirely and unfailingly predictable – in other words, just as easily avoided. So while everyone was gearing up the whole past week to “go out at the weekend,” 1 we simply took one weekday morning the bikes out of the garage and… went. Out of the town and away from paved roads, we followed trails through the woods and old tow paths along the canals 2, alone but for a few seagulls flying low across the still waters, some squirels darting occasionally across the branches and otherwise, undoubtedly there but unseen and out of way all the same, a whole crowd of tiny life busying itself in the undergrowth with the very aim to hide and keep away from view – to stay *safe*, you know?

biketrip_1_640.jpg

biketrip_2_640.jpg

Closer to their true element again, as if released from the whole boring back and forth of short town roads, our mountain bikes took effortlessly to the unpaved but rather flat tracks 3 and we covered about 16 km (some 10 miles) before we even realised it, surprised to discover that it took us so little time to get so far, even with the child pedaling on his own. As we stopped in the shade to take a sip of water and a glance at the watch, we looked at the map, double checked it all and in the end simply shrugged and decided to keep going since it was even too early for lunch, no matter that we were already further along than we had planned. So on we went and past locks awaiting patiently for the boats that were however waiting in turn for someone – or something – to finally start moving again the still, quiet waters. Nobody and nothing moved though and all was still, for the canals are never rivers, nor even ponds, just basically very long and comparatively narrow puddles, no matter how wide or even deep they might be.

biketrip_3_640.jpg

biketrip_4_640.jpg

Through the woods where the sun hadn’t had a chance to dry much of the previous rains, the paths were going at times slightly up and down some mounds or across old and twisted roots but that hardly posed any problem at all. I was happy to go last, following along as it were, free to let my mind wander with barely 1% of my attention required otherwise to keep on the right path and neither fall behind nor bump into the child going right in front of me. After a while though, as we hit some muddy areas, the child’s overactive imagination set to work, describing the slippery qualities of watery soil and complaining so loudly about it all that I soon found myself in front, picking quickly the least muddy path and otherwise totally soothing the child by adding to his previously expressed fears a graphic description of sinking slowly but surely in the moving mud, gasping for air and dieing unheard, nevertheless. He certainly stopped complaining and became very quiet instead, focused fully on following me very carefully indeed, coming out on the other side quite entirely not muddy at all and even happy to go again in front of me, at least while the going was easy enough.

We stopped for lunch too, not as much according to either previous plan or to the time of my watch but certainly according to some growing hunger manifesting in the youngest as a decidedly less sunny disposition. So we sat down and we ordered adult-sized steaks for everyone, as the best remedy that there is to all the incipient grumpiness of otherwise happy people. The waiter was shocked at such utter disregard for their rules-to-feed-your-child, but he recovered fast enough, as they generally do around here and satisfied himself with just a double check – yes, we really mean one steak for the child as well, and no, not any of those “nuggets” from the children’s menu, thank you. And then, just as he was soothing his nerves with the familiarity of the click-click-click through their usual pads, the child delivered another blow by requesting with elaborate but quite pointed politeness, “if at all possible”, for the calamari starter that I had mentioned but that had been apparently forgotten among the double checks required for steak-shock recovery.

We sat and talked while waiting for our steaks but that’s not something children are all that good at for more than 5 minutes at a time. So the child was sent to run around and explore to his heart’s content, which he did but not before asking first for my camera to take pictures, too. It’s even good that he did since otherwise there will be hardly any pictures at all. I had remembered to take the camera with me but the part with taking pictures is apparently still not coming to mind all that often, especially when otherwise actually enjoying the ride. At any rate, I took the above 4 pictures in total, he took about 30 and overall, there are at least 9 to look at, whether they are or not what one might expect from a day trip by bike, along the water and through the woods:

biketrip_5_640.jpg
biketrip_6_640.jpg
biketrip_7_640.jpg
biketrip_8_640.jpg
biketrip_9_640.jpg

  1. As the “news” will undoubtedly report next week, this Sunday and Monday are likely to be terribly crowded everywhere, seeing how Monday is a day off -“bank holiday”- around here for whatever reason. Meanwhile, we barely met any people at all and we didn’t particularly aim for that, either, it’s just enough to not follow the crowd to also not have the problems the crowd hasmakes, as simple as that.[]
  2. The canals were built as transportation routes, there’s a whole network of them around here. The tow paths are narrow mud paths on one side of the canal and were used precisely as the name suggests: horses or donkeys would walk on these paths, towing a boat in the water. I suppose it was still easier to carry large loads that way than to pull them in carts on the roads but I freely admit that I don’t know all that much about canal transportation and it never managed to spark my interest to look it up in more detail, either.[]
  3. Apparently 10 years are not all that much as far as muscle memory is truly concerned – having cycled before even only a bit up and down the Dolomiten, there’s just no way a flat path along the river registers much. Whether some 35km (22 miles) long or not, it doesn’t seem to matter, basically if it’s not going up, then it’s almost not there at all, huh. []

May 25, 2021

Implementing V for Production Use

Filed under: Coding,V — Diana Coman @ 2:28 pm

Since I am by far the most experienced user of V, I have therefore also first-hand experience with all the different ways in which *all* implementations of V so far (v.py, v.pl, v.sh & vtools) fail in practice as soon as applied to any production code base with all its complex changes and significantly large sets of vpatches. To keep this short, I’ll point out 1 just the total deal breakers for me 2: the reliance on Koch’s gpg, the imposition of arbitrary restrictions due to limitations of various underlying tools imported but not truly adapted to purpose 3, combined for maximum damage with a non-existent, utterly and even at times worse than useless approach to “error reporting” that would be better described as “error non-reporting with a dash of retroactive error discovery” 4.

None of the above problems have anything to do with the V paradigm itself, of course. They are all simply the problems of the v.py, v.pl and v.sh & vtools implementations and moreover, to be found exactly at the very places where these implementations depart from the V principles. So the cut is clear enough: there’s nothing to salvage from the v.py, v.pl and v.sh & vtools. Sure, they have the excuse of being “just drafts”, fine. That excuse tends to wear thin after these many years but sure, they are all first drafts at best and as such to be entirely discarded, indeed, so this is exactly what I’m doing, too: I’m discarding them all and I state it here publicly as I owe it to anyone who might read otherwise my equally public previous use of them – they are fine as first drafts and *nothing* more, definitely *not fine* for production use of any sort.

Moving on, I’ll implement V for production use as well, with everything adapted to purpose, from cryptography to diff-ing, pressing and everything in between. There’s neither need nor any bit of desire to rely on anything that is neither fit for purpose nor adaptable to it and that includes python, perl, gnupg modules of any sort, gpg etc.

  1. Mainly for the benefit of anyone considering using any of these first-draft implementations. Use at your own future inconvenience and for your own future loss.[]
  2. If you really need more, go ahead and ask me in the comments section.[]
  3. Such as “can’t revert a file” – note that this restriction is simply due to the limitations of the underlying diff that works with file-level hashes, nothing else, despite all the pretense that there is any higher-level reason why such limitation is even desirable. If you really mean that this is a feature and not a bug, go ahead and argue it in the comments but do make sure your argument includes the reason why reverting a function or procedure is at the same time somehow different and perfectly ok. I’ll also add that if you really think that one should just know from memory, at vpatch 80 when they remove a function from a file that the result is in fact reverting that file to its version from vpatch 55 then good luck to you, enjoy the toy v implementations and more power to you.[]
  4. What this means in practice is that you are left to hunt manually for the actual source of the problem and at times this hunt is even potentially extending all the way into the past – you might find out at vpatch 90 that the V-error was introduced… somewhere before, in any of the previous vpatches, aren’t you happy to go and search for it in all the tree? For example, v.py will just spit “Cyclic graph” at you and you are welcome to hunt for the 2 vpatches involved and then for the 2 (or more!) files (hashes) involved and so on. V.sh and vtools will construct the vtree correctly by looking at the vpatches as whole units but then will fail at press time because the press still looks at files individually.[]

May 17, 2021

Eulora’s Core in Glorious Detail (and Picture!)

Filed under: Coding,Eulora — Diana Coman @ 10:44 am

The initial work only expanded in scope in the intervening years to the point where it ended up covering pretty much everything, from end to end encryption, rsa-based authentication and a new protocol for client-server communication, to flexible file transfer torrents-style, a full graphics pipeline operating on demand, user interaction (both GUI and CLI) and various intricate mechanics that I won’t even start detailing here if I am to keep this introductory paragraph from taking over the article whole. Nevertheless, as all this extensive ground has been covered in at least one fully working iteration and the swamps have been all but drained, the core structure is now reliably in place and so the time has come to document publicly at least the very Core of what will be the most widely available part of it, namely Eulora’s Client.

Looking at the dates, I notice only now that it’s almost exactly two years since I published the first version, higher level map of client’s core. It’s been two very productive years though, so that almost all of the User Interface part got trimmed to a more reasonable size, eviscerated and squeezed like the paste that it was into usefulness, while the Core part grew into providing full services on top of the barebones, raw elements that were originally listed.

The client’s Core is still a library but it has a clear single entry point in the EuCore package that manages all the various parts and provides the means for a C/CPP main to start and stop the whole in a controlled manner, without being otherwise aware in the least of any of the Core’s own internals. Basically EuCore serves as a control interface, ensuring that even a C/CPP main can take advantage of Ada’s neat mechanisms 1 for clean and tidy multi-threaded execution. On receiving the signal to start everything, this control interface initializes (aka asks them in turn to load whatever they need from the shared configuration file, already) and starts all the components that it manages. On receiving the signal to stop, EuCore passes it on to each of the components it manages and otherwise doesn’t have any qualms about killing off (via abort) if and when required any tasks that can’t or won’t stop in a less abrupt manner.

The most important components managed by EuCore would be, from the lowest level up:

  1. The sender/receiver tasks for RSA and Serpent packages simply provide in-memory queues that can be made therefore larger than the IP stack provides otherwise, for both outgoing and incoming UDP messages so that losses are kept to a minimum and callers from the rest of the code don’t need to wait. They are both based on the same generic Snd_Rcv package simply instantiated with the corresponding package size.
  2. The Comm_Link package handles all the practical details and inherent complexity of keeping in sync over a lossy communication channel. This includes keeping in sync the two buffers of Serpent keys as well as providing everything required for overall key management. While this sounds little, in practice it’s quite the opposite of little, no matter what you measure there. Note that this package provides everything required and handles its own internal logic but does not attempt anything beyond its station – the higher logic for communication management simply can not be at this level and so you’ll find it in HeartBeat, further down this list.
  3. The EuCache package maintains and provides access to the knowledge tree of the game’s world aka that boundless although finite data hierarchy. The role of EuCache is that of a librarian essentially: it accepts all new data as it becomes available, it integrates it with what it already knew and it aims to provide on demand more than just the raw data since raw data is rarely directly useful as such. What is more useful instead and what EuCache aims to provide in addition to the raw data is at least one level of integration on top of it, basically trying to take any useful tiny steps that it can towards that ideal known as knowledge. How far it gets and therefore how useful it turns out to be depends more on you and what you figure out to ask from it in due time. For now and for starters, the possibility is there, the examples are also there, the rest remains up to you.
  4. The Torrents package handles the rough as well as the fine mechanics of file assembly, storage and access. This includes receiving and fulfilling requests for retrieving files (whether local or remote), handling all the different bits and pieces of chopped files as they arrive over the network, checking each of them and asking for any corrupted or missing parts, as well as assembling the full file, storing it in a convenient manner (currently neatly ordered by type) at the path specified by the user in the configuration file and pointing any caller to the exact path for any specific or default file 2, as requested.
  5. The HeartBeat package coordinates everything in Core at regular intervals. This contains also the higher level logic for it all, since that requires almost always repeated and/or time-based decisions, from requiring an update of the world’s data to repeating a request that is still pending or deciding on resetting the link entirely when no other measures manage to recover the synchronization with the other end.
  6. At the outermost edge of Core, the EuInterface package wraps up and exports with the C convention (so that any C/CPP code can use it directly), all the functions and procedures that modules built on top of this Core may use – from asking the server for assets or information to sending back to the server any of the user’s actions and everything in between, even building up and accessing a full local history of all user’s console commands.

In addition to the more prominent packages briefly described above, there are also quite a few utilities packages that provide a common language of types used across the whole Core lib as well as the lower level tools required and employed by those higher level packages. At the very base of EuCore, there is thus the Raw_Types package that all the others rely on, since it defines all the data types required by the communication protocol, as well as structures, subtypes and conversion utilities that rely on these types and are widely needed otherwise for various mechanics. On top of Raw_Types but focusing on structures and utilities supporting knowledge acquisition rather than the low level protocol mechanics, there is Eulora_Objects that provides for instance the records and hashmap types for storing any euloran object as well as the full known hierarchy of the world at any given time.

In between the above two data structures packages and the higher level packages listed previously, there is a middle layer of tool providers basically, from simply logging something or obtaining raw octets from the currently set source of entropy to Keccak hashing, RSA-OAEP encryption or message packing/unpacking and checking.

A full graph of the dependencies between all the Ada packages in the client’s Core current version shows quite naturally the top (EuCore) and bottom (Raw_Types) two packages as well as the strictly and clearly hierarchical structure overall: while there are indeed many links between packages as they are rather intensively working together 3, there are no cycles and moreover, no dependencies going the wrong way, meaning from bottom to top. All the links go clearly and as they should, always and forever from top to bottom (the red rectangle surrounding Keccak is there simply to mark that Keccak-Hashing is its child package):

eucore_2021_1_1024.jpg

  1. Core’s code currently makes use mainly of protected objects and task types/variables.[]
  2. Eulora’s client will be quite independent in deciding what it uses as defaults for any and every thing. There are no externally imposed or defined defaults because that doesn’t solve anything since one can then simply not have the officially declared defaults and so what is that supposed to solve really, you’ll end up with defaults for defaults or what exactly? So the cut made there is deeper but cleaner: the client will simply pick as default the first (as in oldest by its own timestamp) file that it has for each type and that’s that. Yes, this means that different clients can easily have different defaults and it also means that you can even pick your own defaults if you care – just change the timestamp for the file you want so that it’s oldest and that’s all.[]
  3. Yes, they *could* be further separated but at *the cost* of additional significant verbosity that really doesn’t make anything clearer nor easier to follow – there is nothing “easier to follow” in introducing a few layers of indirection in there just to provide separation that otherwise is not really meaningful nor needed in any way.[]

May 6, 2021

Ada’s Dirty Pointer Secrets: to Access, or to Address?

Filed under: Coding — Diana Coman @ 1:47 pm

~This seems to turn into a mini-series of sorts, see the previous example of passing dynamically allocated arrays from Ada to C~

In true ladylike fashion, Ada deals with the unmentionable -but useful, darn it- dirtiness of pointers by calling them something entirely else: if p is for pointers and a is for Ada, then at least be civilised enough to use a-words when working directly with memory! So the type for pointers in Ada is not denoted by * (does that stand for some expletive in C, I wonder?) but by the magic word “access” that is used to denote a pointer type and wards off segfaults as well as more general memory read/write mishaps. And like any other magic, if it didn’t work for you, it’s because you used it wrongly!

The core of the access type idea in Ada is to leverage the overall strongly typed approach to provide at least some amount of automated checks and safeguards even when using pointers. So there is never a “pointer” variable but only a “pointer to this exact type” variable, at most (aka “access” is a generic type that needs specific instantiation before any use). As a result and in the otherwise overall Ada-style, there is no implicit conversion between pointer types, even if or when they might happen to point to the same type of thing otherwise!

Each access type can also contain further constraints such as not accepting null values (basically enforcing an automated check for that very common null value bane of pointer use) or allowing access only to some (as opposed to any) memory spaces (storage pools and even subpools, in Ada terminology). The significant advantage of this is that one can at all times be quite specific and therefore know exactly what sort of thing they expect to find the pointer pointing to, so that it’s at least harder to mess it all up. The disadvantage is at times quite the same: having to be very specific about details when not needing the details or having to be very specific about things that are not yet known or even possible to know upfront can create its own sort of mess (although it’s indeed one way more subtle than a segfault, granted).

For those cases when the neat access types are just too much overhead or too much of a straightjacket or simply not needed, one can still ask in principle directly for the memory address of anything at all: simply add ‘Address after the name of the thing and there you go, what you get as a result is what you expect (and if you expected something else than what you got, it’s because you had the wrong expectations, obviously). Note however that from Ada’s point of view, access and the result of ‘Address are two different sort of things and as such don’t easily mix 1.

The ‘Address attribute 2 is very useful indeed to do basically memory overlays (mappings) that are just about the fastest and most convenient way of converting between two types no matter how complex, with the only real requirement that they are of exactly the same size. This is absolutely invaluable when needing to get the raw representation of complex types for whatever purpose (mine tend to include at the moment encrypting/decrypting and/or fast storage). All that is required is to simply declare one variable of each type, make sure that they do indeed have addresses (by declaring them as “aliased” since otherwise Ada might optimize them into registers) and then request that they use the very same memory address. For instance, to convert a whole array, no matter how big, from the C-compatible char_array type to the one underlying raw type used everywhere in the Ada code around Eulora’s client, all it takes is one function wrapping the few lines of code to map the memory and return the contents read with the expected type:

-- NB: result has length exactly A'Length
function Char_Array_To_Octets(A: in Interfaces.C.char_array)
return Raw_Types.Octets is
ca: aliased Interfaces.C.char_array(1..A'Length) := A;
o : aliased Raw_Types.Octets(1..A'Length);
for o'Address use ca'Address;
begin
return o;
end Char_Array_To_Octets;

Of course, direct memory mapping via the ‘Address attribute as above is as dangerous as it gets and as such entirely not in keeping with Ada’s style. Except, of course, that Ada fully allows it in the first place and provides the means to do it too but probably averts her eyes whenever you do it, then moves on and pretends it never happened. So it still works but it’s also all clean, neat and tidy, unlike that ugly, dirty C. And if anyone asks about it, it’s all *your* fault, too, you made her do it!

  1. There’s a whole package to convert from one to the other (System.Address_To_Access_Conversions) and it even uses the unmentionable word “pointer” as in having a function named To_Pointer returning an Object_Pointer! []
  2. Ada has this concept of attributes: things one can get and/or set about any entity, simply using the syntax entity’attribute_name. For example, one can get the size of the Integer type simply by writing Integer’Size, one can get the size of a variable x by writing x’Size and one can set the size of some MyType by writing for MyType’Size use 133525.[]

April 25, 2021

Reality Flicker

Filed under: Sense and nonsense — Diana Coman @ 1:00 pm

It tends to happen mainly at night, sometimes at dawn, when some incongruous and unexpected sound would be so ill-fitted to the immediate reality and so well-fitted instead to some past place and time that my whole perception would just flicker and suddenly unplug from my surroundings to draw instead all its input from my own memory of another time and place. The mattress would become harder, the bed would shrink in size and grow in height, the whole room would come down to the ground floor and the house itself would turn around to match the cardinal points that my memory provided as real in the present and not just in the past. Even the street outside would simply change as much as required, effortlessly morphing from a short and gently curved town street with both ends in sight, with cars parked along it and rinsed pavements snugly fitting it from the sides, into a raised, wide river of concrete flowing through the open plain as far as the eye could see on either side and mostly empty at night except for the rare times when a car whooshed by, as if launched for a take off rather than merely traveling on its way to either the distant sea at one end or the equally distant capital city at the other end.

At times, even the night itself changes to fit my recollection and when that happens, the cool and breezy air would suddenly become dusty, stuffy and even heavily lily-infused, as memory frantically puts to use all those details it stored so carefully long time ago to recreate everything so vividly at a mere flicker of the right sound, the right fragrance or even simply the right time. In other words, my illusion is promptly and lavishly supplied with anything at all, for a fully rounded experience – at least if my own memory is taking me for a ride, I’ll concede that it’s an exquisitely well prepared one, each and every time. While many other illusion sellers certainly exist and tirelessly try their best to make me buy something from them, I have to say that I have yet to find one that is as good at it as my own memory so with all the free practice I had throughout the years, I’m not sure how would they stand a chance even if I decide one day to be in the market for pre-packaged illusions.

It is however precisely the same characteristics of my memory and the very same highly focused attention to detail that tear the illusion apart just as strongly as they create it in the first place, since they make it all the harder to keep ignoring current reality as it pokes through the recreated past in myriad of tiny ways. For throughout all these frantic changes of perception trying to cover up and take over, there would be the noticeable check-check-check for contradictions of my mind testing it all and trying to pick somehow one of the two realities it found itself unexpectedly straddling. The same part of me that stored meticulously all these details that enable now such vivid illusion is still hard at work picking and storing up just as meticulously all possible current details, finding therefore increasingly more and more contradictions until the memory concedes defeat and the perception adjusts again to focus on the present as more real than the past, at least for now, at least for a while.

Fortunately for my sanity at least, such drastic flicker of the whole perception as the above does not last very long, nor is it all that frequent. Nevertheless, it still is frequent enough and it lasts long enough that I’m aware of it even as it happens – it’s a bit like watching a suddenly confused actor switching mid-sentence from one character’s lines to another’s, just because at that particular moment the two became so close that the points touched and the track changed seamlessly, at speed. Then, as the tracks diverge again and the new character becomes almost strikingly out of place among everything else, one gets to watch the same actor at first trying to resist yet another change but in the end still switching back again and carrying on from there undisturbed, as if nothing happened.

After all, nothing actually happened, it only seemed to have happened merely because two alternative representations, each flawed in its own ways, simply came head to head in this continuous race to win the title of “closest to real of all my currently available illusions.”

April 12, 2021

A Tale of Two Code Changes

Filed under: Coding,Eulora — Diana Coman @ 2:46 pm

This past week I worked on a significant refinement of Eulora’s data hierarchy, that core structure used to fully describe for the client the game’s endless, complex and ever-changing world. As it happens, this refinement was made possible as a result of a lot of previous work 1: having recently gained full control over the creation of all graphical elements as I successfully grew my own mountains alongside GUI elements and literally everything else involved, I was also finally able to break up into more useful pieces and ultimately get rid of that sore anomaly of an “Outdoors” object that had previously catered to the requirements of the now-discarded “terrain plugin”.

For the easy part in getting rid of that bulky and spurious “outdoors” object, I had at least already in place the natural building blocks that would get used, namely the CSModel object as well as the ways to position and even name it, if desired. Even so, a change such as this, touching as it does the game’s own way of structuring knowledge essentially, can never be a very easy thing to get right, as there are many different connected pieces that have to fit – at least to some working extent – at all times. So I was a bit apprehensive about the amount of work it might end up requiring in practice and I made therefore a padded estimate of the time it might all take.

At first, I made the needed changes on serverside, where everything is defined and created in the first place anyway. There was initially more work than expected, indeed, but mainly as a side effect, a sort of slightly hurried growth, rather than anything else: while the change to the hierarchy itself was quite straightforward, the details pushed into being other parts that weren’t yet quite ready otherwise, although they were somewhere further down on the list for later, anyways. So I took more time than I had initially estimated to design and then add the needed embryos of these parts too, even though they still miss a lot of other parts that they in turn require and as such, they are sure to further change as they develop. This is expected and unavoidable though – it’s how everything else on serverside currently came into being as well, after all.

As the serverside work stretched even beyond my padded estimate for it, I was increasingly thinking that I’ll have no choice but to revise the overall estimate entirely, as the remaining time for the whole clientside work shrank and shrank. But then, when I finally got to update the data hierarchy in my own EuCore component on clientside, there was indeed very little required: simply the addition of the new object types, the deletion of the old one and a few updates (flagged automatically, too!) to take them as well into consideration when looking for broader categories such as “graphics vs non-graphics objects”. The rest of it – and moreover, the *more significant* and difficult rest of it simply worked and not by accident either: it was simply my previous design and implementation of both EuCore and its interfacing with the GUI saving me days of work now, as it handled entirely new types without skipping a beat and without requiring otherwise any change *at all*. How pleasant is this as code to work with and when exactly is the last time you encountered such ease when making significant changes to the code you are working on?

The second code change that made its way onto my list this past week was in principle a very simple thing to do, clientside entirely: as the water was now simply a CSModel like any other item in the world, it ended up nicely rendered but nevertheless surprisingly…solid, despite the data hierarchy otherwise holding enough information as to its “water” nature. In other words, there was clearly a need for the GUI part of the client itself to become a bit more discerning and create water as water (not solid and also reflecting things around, for instance). Since I had already written the code that successfully created water as such, this change was in principle just a matter of adding and using a flag, nothing more.

In practice though – in hindsight unsurprisingly, as it touched the remaining PS code – the simple change turned out to be not that simple and especially not as straightforward as expected: first, the water was rendered reflecting quite nicely everything around, so that it was clear that the discerning part worked as expected but… this “water” was still a solid, more like frozen ice perhaps than any water. Then it all got even more puzzling: the water was still solid *despite* my loader specifically *not* setting collision detection on it (in graphics terms, this solidity is simply a matter of whether one bothers to check /enforce any bumping into the object in question or not). Moreover, this unexpected solid was not even reliably solid but rather a weird half-assed sort of solid: one would walk on water indeed, for all the incredulity one might have as to the possibility of such feats but then, unexpectedly (a loss of faith, perhaps – whose faith, though?), one would sink deep into it and then… oh, then, one would get *stuck* in there, too, unable to move in any direction, if able nevertheless to spin as much as desired! Basically I had inadvertently created in there a sort of treacherous quicksands for all their watery looks otherwise.

Both the cause of and the resolution to the above unexpected wtf turned out to be of the same sort as previously encountered: the cause was a remaining bit of planeshift code and the resolution was to discard it entirely. Basically there was a spurious “psSolid” wrapping of the engine’s own collision detection object doing nothing other than getting in the way – it literally added *nothing* of its own other than the perpetrator’s name at the top of the file 2 and otherwise another indirection layer in the way of anyone trying to make sense of the code overall. On top of this, some other bit of remaining PS code *also* took it upon itself to decide and add this half-assed psSolid thing to *everything* that went through it, just like that. As a result, there was this funny situation where simply bypassing it all solved the problem entirely – as usual, not playing along with the stupid has this magical effect of making all sorts of problems just… disappear. So I further deleted some of the increasingly less but sadly still remaining PS code and as a reward for it, I had my water being water again, nicely yielding rather than solid and otherwise letting one freely move through it at all times, instead of randomly trapping unaware swimmers in it.

Having previously trimmed and trimmed again at these same planeshift tendrils, this latest trim was otherwise quite effortless too, basically a very pleasant and rewarding way of improving the code from all points of view. How is this for coding work – effortless code *reduction* for added benefits and increased functionality, too. How does this compare with your current coding work and experience as to what coding even involves, hm?

  1. This most recent work merely added, in turn, on top of full years of cleaning up all sorts of strata upon strata of a huge mess.[]
  2. And I have to say that by now I had even guessed correctly the exact “author” name in that file, despite there being quite a few names scattered otherwise around the CS and PS codebase, you know?[]

April 1, 2021

The Importance of Being Normal

Filed under: Coding,Computer Graphics — Diana Coman @ 5:47 pm

When everyone is so unique as to aim to invent out of thin air their own sort of normal urelated to any constraining reality around, the world looks, at best, like this:

normals_1_640.jpg

As soon as everyone stops being unique and tries for a change to be simply normal at their exact, reality-constrained place, whatever that might be, whether big or small, steep or flat, high or low, only normal in its most boring, right-angled and utterly perpendicular sense, the world suddenly lits up, full of depth, light and shadow:

normals_2_640.jpg

Then again, this is nothing but computer graphics and as such entirely unrelated to anything of importance in any possible way, of course. Just coincidences – as it happens, perpendicular ones this time.

March 24, 2021

Growing My Own Mountains or the Plugged Off Plugin

Filed under: Coding,Computer Graphics,Eulora — Diana Coman @ 5:14 pm

Eulora’s legacy client requires no less than 12 image files to create just one sector of the whole wide world and this piles on, of course, the megabytes transferred and stored under the generic label of “art assets”. The reason for such shameless requirement is the reliance on one of those oh-so-flexible plugins that the engine (CS aka Crystal Space) is plagued with: the terrain plugin that supposedly generates programmatically all sorts, except in practice it still expects 5 detailed, pre-made maps, of which 4 (basemap, lightmap, materialmap, normalmap) are anyway calculated otherwise based on the 5th (the heightmap).

Perhaps you wonder just what does the plugin do with 5 maps anyway. Well, a deeper dig into the code of it all revealed that the plugin just uses them all to create over and over again, at each start of the game, the same terrain mesh – except it never quite calls it directly mesh (it’s terrain!) and it creates it according to its own rules and decisions as to what all these maps mean and how they are to be interpreted. Basically the terrain plugin expects that it owns the terrain entirely and so it gets to actually decide on what height is where (according to its own, internal rules, too!) and even whether the player can or can’t go somewhere – what representation vs meaning, what client vs server role? In this brave new world of no depth at all where everything that matters is how something looks, the graphical representation thinks itself the master of everything and so gets repeatedly in the way at all stages until the inevitable point where I finally give up on working *with* it at all and therefore ditch it entirely, just as it has happened before and as it will continue happening: if you keep saying you can’t do this and can’t do that and won’t do the other thing either, the result is not that whatever it was to be done doesn’t get done – it’s simply that it will not be done *with* you but rather *to* you and not in ways of your own choosing either.

Due to the above stupidity of the terrain plugin in CS, what started as an attempt to merely calculate the terrain’s final height at any given point, ended up in quite a bigger and more tangled chunk of work to do but the net result is the addition to my gfx pipeline of a direct, full creation from scratch of a terrain mesh that can then be sent to the client to use as it is – no need for sending 5 maps over the wire, nor for any further polygonizations and calculations of height each and every time someone fires up the client: at least if it has to use a rasterised format, let it be calculated just once on the server and then reused forever by all the clients that may ever need it.

As usual, things didn’t initially go very smoothly but that was quite expected: first the whole thing didn’t show at all 1, then the “object is not closed” complaint kept on complaining even on the closest of them closed objects 2, then the movement went haywire, whole mountains kept playing hide and seek with my view, bits and pieces started flickering, vanishing, blackening out or any combinations of those three. And then, finally, even the return to the “old way” (aka plugin based) failed, revealing at the least expected moment that the plugin itself was in fact no better at handling the sort of situations I was stressing my poor mesh with.

All the above out of the way and written here once for all the future uses, let’s illustrate it, too. First in line and as seen by my aptly (if algorithmically) named Perfectput Dot rabbit, the amazing whole land-vanishing capability of the terrain generated by the plugin – basically the culling itself fails just as much on my mesh as it does on the plugin’s creation:

Now you see it…
mesh_terrain_7_640.jpg

Now you don’t…
mesh_terrain_9_640.jpg

Set entirely at ease by the above as to failure being a given anyway, I started growing mountains out of the submerged plains, which was simple enough when all it takes is cranking up the maximum height parameter of my generator: the mountain grew and grew but it still remained stubbornely and quite ridiculously pointy:

mesh_terrain_1_640.jpg
mesh_terrain_2_640.jpg
mesh_terrain_3_640.jpg
mesh_terrain_5_640.jpg

While the last image above is at least not *that* pointy, finally, the whole exercise made it quite clear that there was some deeper trouble in there, as indeed there was: first of all, I had an error in my height calculations (so that the factor applied was not at all what I thought it was) and second but more important, it seemed to me rather silly to calculate the full heightmap of 1024 x 1024 size to then pick for use a smaller grid (to keep the size of the mesh file itself reasonably small). Basically the added detail that the heightmap held was just thrown away because the polygonization used *less* detail, not more (if it were more, I’d have interpolated and in principle it should smoothen it further so it’s possibly closer to what I’d want, anyway). So I tweaked a bit the code to simply add the actual scale and then generate the heightmap only as big as needed: a scale of 4:1 for instance means that real world unit is 4 for every 1 in the heightmap and therefore a real world map of 1024 x 1024 can be fully obtained with a heightmap of only 256 x 256 (since 1024/4 is 256). Otherwise just using every 4th value in the heightmap doesn’t really bring much benefit, as it’s not “more detailed” since the detail itself is just glossed over. In any case, this part might still need further tweaking but for an illustration, here’s the resulting landscape with max height set to 100, scale factor set to 8:1 (hence generated DS heightmap of only 128 x 128) and values used for DS seeding from -5.0 to 5.0):

mesh_terrain_4_640.jpg

For this initial testing stage, I didn’t bother with creating any actual texture for the terrain but I don’t really see why that would be any trouble really, whether doing splatting or anything else really – one big advantage of ditching the terrain plugin is that there is now no limit whatsoever on texture or materials, I can even mix as many materials as I want, no “exactly three” restriction anymore. At any rate, the images above simply use the “sand” material (both image and normals, hence a bit more than the plain textures used for my meshes so far) everywhere, with a plain mapping – while the effect in the distance seems reasonable enough to me even with this tiny material, the close up does indeed seem to require more detail. Possibly the current 512 x 512 texture is just stretched too much on the triangles of the terrain when close enough and since I don’t do any “lod” shenanigans, it looks for now as illustrated above. Nevertheless, this should be improved simply by using a better texture overall (and since that would be a single one rather than 3, it can even be 3 times bigger without any increase in size of the whole .zip as compared to the current one).

Worth noting also that in all the above illustrations, the water and the sky are unchanged – they are still created entirely client side, with just the texture and the normals sent by the server. I don’t see any reason to change this (both sky and water are fixed, regular shapes) but at the same time, having now increased (more than I ever wanted) my hands on experience with messing up meshes, I tend to think it’s probably worth changing on clientside the *shapes* in use, especially for the sky (and as a result, possibly, the texture to match, too): the current sphere is fine in a way but it creates this unwanted effect that tilting the camera at any point low enough to the ground results in one looking *under* the ground where there is a whole half sphere of… sky. Since “filling” this half sphere is apparently something just not working (because there is no depth to anything, no matter how defined), the alternative that I can see would be to have the world “container” simply as a cuboid with the terrain resting on the very bottom (so that there isn’t anything to look at underneath, no matter what tilting) and then simply add a half-sphere for a dome effect or otherwise, possibly even texture the corners of the ceiling out of sight.

All this opens up of course a whole new set of potential parameters and/or approaches for terrain generation but whatever parameters are chosen in the end, the pipeline still works the same so I’d say that the mechanics are now at least in place and the rest can then be easily tweaked further at any later time. What changes otherwise as a result is the “Outdoors” object in the hierarchy of Euloran objects since it looks set to simply contain a mesh for the terrain and then, perhaps, the materials for terrain, sky and water, unless those end up also given separately perhaps.

  1. While CS docs are clear enough that the “front” or visible face is the one with vertices given clockwise, the bit missing was that CS’s z axis points forwards! Noting it here for any future puzzlement on this topic: the “top” (or “far”) left corner will therefore have the highest z coordinate and the lowest x as opposed to lowest z and lowest x. The rest then falls easily into place, as one just literally needs to list the vertices in clockwise order. Worth noting also that a closed 3D shape with faces oriented so that they are visible from the outside will therefore have… transparent sides when seen from the inside. This is the illusion of 3D in computer graphics at its most cumbersome: there is literally no depth to any of it![]
  2. Oh boy, how infuriating this was: what the stupid thing checks for is not exactly whether the object is geometrically closed but rather a much more custom interpretation of “closed” namely “does this object have at least 16 triangles and in such case, does it also have all edges – exactly as given – shared between at least 2 triangles?” Specifically, this means that you can’t really easily define a 3D shape with different level of details on its different sides because you have to match the number of triangles wherever the sides meet, basically there’s no way to split one side into several smaller ones for added detail (even if geometrically the whole side is thus covered). In turn, this brought at first the horror realisation that making the terrain a cuboid as opposed to just a top sheet would then require effectively *doubling* the vertices and the triangles (which is not a negligible doubling when talking of a whole sector of the world). Nevertheless, in true open source spirit, it turned out that *ignoring* the whole complaint entirely is the best course of action – if it whines that even closed shapes are “not closed” then it will get fed fully open shapes since it’s basically not worth catering to. Funnily enough, this made otherwise no discernible difference in practice, at least not beyond the presence of the complaint itself in the console. Go figure, it turns out that I am *still* paying too much attention to what is nothing but empty pretense, sheesh.[]

March 20, 2021

The Space It Takes – XML, Binary and Raw Mesh Formats

Filed under: Coding,Computer Graphics — Diana Coman @ 4:36 pm

While Eulora’s communication protocol can handle easily the transfer of any data files that the client might need, the size of such files still matters, mainly from a user perspective 1 – large files take time to transfer and nobody wants to have to wait more than absolutely necessary. Which is all nice and well, except totally at odds with what the rasterised approach to computer graphics requires, namely huge listings of everything 2. Despite this obvious problem with size for graphics files, the legacy formats of Crystal Space (CS) and Cal3d bring with them the very dubious design decision of using XML everywhere – basically adding even more (since everything needs an XML tag and then every tag needs a closing tag) to the size of the already large files for the theoretical gain of making huge listings of numbers (floating point for the most part, too) human-readable as if that makes or made somehow sense for someone, somewhere, sometime. Don’t you want to check by hand the positions, normals and triangles of something even modest, say a couple of hundred vertices in the 3D space with their 3D normal vectors and about a thousand triangles perhaps? No? Why not, since now you totally can, hooray for XML!

As my hopefuls are quite efficiently packing a lot in relatively small surfaces, the above XML-inflation of files didn’t hurt *too* much until now – although it was certainly showing early signs of trouble since the full generation of a model took less than the chunking or sending of the resulting files, to give just an example. Nevertheless, the place where the size really went through the roof and basically can’t be ignored anymore is the terrain – first the heightmap itself turned out rather too big for the initial uncompressed .png format. Then, as this was addressed by switching to the .dds format (hence the heightmap went down to 1.1M while still fullsize, 1024×1024) and adding therefore that as well to my gfx pipeline, the mesh itself exploded in size, with the resulting CS mesh file (xml, of course) weighing in at 190M. At which point the XML became indeed so unbearable to require a look around as to *any* other more reasonable option, from existing binary formats to raw dumpings of the data, if need be.

Looking around at existing binary formats didn’t turn out very inspiring – while there are tons of formats for graphics files (so that one can spend as much time as they have sifting through it all), a closer look is usually quite dissapointing. My take on it so far is that binary formats that might perhaps be of some use are very close in fact to raw dumpings, without any tailored packing that might bring some additional gains for the narrow case of mesh definition – this seems to me to be mainly because none of the formats can quite commit to keeping to such a narrow scope as literally focusing on just vertices, normals and triangles. Even the simplest (such as the PLY polygon file format, which seems to keep indeed at least as simple and straightforward as possible) still consider it mandatory to at least allow the definition of additional parts and therefore to not attempt any task-tailored packing. This being said, I had only a quick look at the field and given the huge number of formats out there, I don’t claim to have looked at them all by any means (and some, such as .obj) are proprietary so their binary form is undocumented, too, so if you know of some very efficient such format, please let me know in the comments box below, thank you.

Given the above sad state of affairs regarding other formats, I took a bit more time to gather at least some concrete measurements of existing options with what I already have, so that there is at least some basis for any decision moving forwards. For this, I added to my gfx pipeline a few more writers to have a way of looking for instance at exactly how much do those xml tags add on (hence writing a file simply stripped of the xml tags) and what would the most straightforward of “raw” writing occupy anyway. On this last point, it’s worth noting perhaps that one can of course calculate the lower and upper bounds of the file size, simply based on the map’s size and otherwise known representation of the data types involved. Considering the map of 1025×1025 vertices and corresponding 2*1024×1024 triangles, the “raw” overall size still ends up with a lower bound of approximately 80M (using 4 octets for each vertex index used to define triangles and 8 octets for the floating point values used to represent vertices’ positions, normals and texture coordinates). Keep in mind though that this raw format is however not compressed and a simple zip of it can reduce the size significantly.

The tables below show the concrete measurements of actual mesh files, first for the terrain meshes that are the largest (1`050`625 vertices and 2`097`152 triangles) and use CS format and then for one of the larger meshes (654 vertices and 1300 triangles) used as a limb of a character. While the Cal3D meshes are relatively small, they have some additional data that is required for animation and they use the Cal3D format that is even more verbose in its XML plain-text version:

Format Plain File Deflation (as reported by zip) Zipped File
CS mesh (XML) 190M 81% 36M
CS mesh stripped of xml tags 112M 73% 31M
Raw with guaranteed, 16 digits precision for floating point 113M 51% 55M
Raw with Float (typically 8 octets) 81M 62% 31M
Cal3D XML mesh (xmf) 272M 85% 41M
Cal3D Binary mesh (cmf) 69M 57% 30M

As for one of the meshes that serve as limbs for my hopefuls, the size is anyway significantly smaller simply because the mesh has only 654 vertices and 1300 triangles in total:

Format Plain File Deflation (as reported by zip) Zipped File
Cal3D XML mesh (xmf) 210K 83% 36K
Cal3D Binary mesh (cmf) 54K 48% 29K

Overall it seems to me that the rasterised approach is really the core and unavoidable trouble, leading to a de-facto limit on the total number of vertices and triangles if one wants to keep the size of the mesh file below any specific threshold, there isn’t much around it. As the zip is quite effective at reducing size for all the above formats, it’s unclear to me if there’s much gain in looking specifically to design a very packed mesh-only format as such. Arguably, if the terrain is the only mesh with too many vertices and triangles, it might make more sense to simply send over just the heightmap plus materials for the terrain and let the client polygonize and texturize it as it wants – all the rest anyway does not add any further information, since it’s all contained in the heightmap really. Alternatively, one can simply make a less detailed polygonization of the terrain – this is probably exactly the reason why the legacy version used such a relatively small cell size, namely to avoid having that many vertices and triangles. For all I know, it might even be the case that CS won’t handle all that well that many vertices for a single mesh, after all.

Nevertheless, the above workarounds don’t solve in any way the wider problem of rasterised files rapidly exploding in size as the number of vertices and polygons increases so I guess the question remains as to whether it’s worth struggling to find some clever, specifically tailored representation of all those lists of vertices and of triangles and how much could even be gained as a maximum anyway, especially beyond what the generic zip compression achieves already otherwise.

  1. Otherwise, from a purely technical perspective, the protocol allows the transfer of files of up to about 140GB and at least so far I never got anywhere near that with any of the files I needed. Then again, I’m sure that more XML use *could* get me there in no time.[]
  2. Vertices and triangles but also normals at each vertex, texture coordinates at each vertex, bone “influences” and weights and so on and so forth. Basically there is no upper limit to the number of lists or to the length of such lists since “the more detailed the better” in rasterised terms.[]

March 13, 2021

Lies for Your Eyes Through the Diamond Square Method

Filed under: Coding,Computer Graphics — Diana Coman @ 8:23 pm

The idea behind the Diamond Square method (DS) is deceptively simple: take a set of pseudo-random values and keep mixing (averaging) those on symmetrical positions, storing the result of the mixing at the symmetry centre, while decreasing and rotating the reference frame at each iteration. In the two dimensional case that is most commonly used in computer graphics, the reference frame is basically a square that gets called a “diamond” when rotated 45 degrees, hence the DS name. For the first step, the frame is square and as big as the whole image: the values in the 4 corners are therefore averaged and the result is added to the value in the very centre. Then, the frame is rotated 45 degrees (hence, the “diamond” part of the step) and used again to average the new corner values and add them on top of the new centre value. At each subsequent step, the size of the frame is halved and then it gets again applied both as a “square” and as a “diamond”, basically mixing together values on increasingly closer positions to one another – in other words and from a graphical point of view, adding (in the sense of making noticeable patterns out of) more and more detail.

The above method (average corners and add to centre, rotate and do the same, then halve the size and repeat it all) can be applied to any number of dimensions really but there’s a whole lot that this apparent simplicity packs even in 2 dimensions so that there’s no need just yet to add even more dimensions to the mix. Before going though into any further discussion, one might reasonably ask: does it work? Well, it’s a lie indeed but a very effective lie – at least in knowledgeable hands, so whether it works or not depends on the skill of the one using it. More precisely, in the computer graphics context, whether DS “works” or not depends mainly on the inputs it works on (the range of those pseudo-random numbers) and the way the outputs are interpreted (the colouring scheme). To illustrate, here’s for instance the very same DS method, with the very same parameters of size and starting step, only with different intervals chosen for the pseudo-random numbers so that the “grid” of the method is clear in one case and rather invisible in the other:

grid_dsg_graycos_feat128_s2021_h1025_w1025_640.jpg
m1_1_dsg_graycos_feat128_s2021_h1025_w1025_640.jpg

The above illustrations are grayscale for the simple reason that DS tends to be used most commonly to generate heightmaps, where the value at each pixel stands for the height of the terrain at that point, hence a single value. This doesn’t mean however that DS can’t lie convincingly in colour, quite on the contrary, have a look at the same DS results as above, only using an r,g,b colouring scheme as opposed to the grayscale one:

grid_dsg_pal_feat128_s2021_h1025_w1025_640.jpg
m1_1_dsg_pal_feat128_s2021_h1025_w1025_640.jpg

Note also that the DS method does not necessarily require that one always starts with a frame as big as the whole image or that one always goes all the way to the tiniest detail. To illustrate one side of this at least, here’s a series of images showing the result of DS for different starting sizes of the frame, both in grayscale and in colour (the smaller the starting size, the more “packed” the image – basically the smaller the size of the patterns or “features” that appear, since the correlations are made between closer points):

m1_1_dsg_graycos_feat64_s2021_h1025_w1025_640.jpg
m1_1_dsg_graycos_feat128_s2021_h1025_w1025_640.jpg
m1_1_dsg_graycos_feat256_s2021_h1025_w1025_640.jpg
m1_1_dsg_graycos_feat512_s2021_h1025_w1025_640.jpg
m1_1_dsg_graycos_feat1024_s2021_h1025_w1025_640.jpg

m1_1_dsg_pal_feat64_s2021_h1025_w1025_640.jpg
m1_1_dsg_pal_feat128_s2021_h1025_w1025_640.jpg
m1_1_dsg_pal_feat256_s2021_h1025_w1025_640.jpg
m1_1_dsg_pal_feat512_s2021_h1025_w1025_640.jpg
m1_1_dsg_pal_feat1024_s2021_h1025_w1025_640.jpg

Does the above mean though that smaller features can only be obtained through DS at the expense of less correlation between more distant points? Well, there’s more than one way to tell the same lie for sure, so if you want more detail while still keeping the higher level correlations, simply pick a suitable colouring scheme (to cycle well) and then increase or decrease the range of those pseudo-random values so that… they each matter visually more. Then you can even keep to the standard DS that starts with a frame as big as the whole image (hence maintaining ALL the levels of correlation within the final image) and then pick wider or narrower range for the pseudo-random values, depending on whether you want smaller or larger features visible in the final image. For illustration, here’s a series of the very same DS applied in turn on values in the range -1.0 to 1.0, -2.0 to 2.0, -5.0 to 5.0 and -10.0 to 10.0, first in grayscale, than in full colour:

m1_1_dsg_graycos_feat1024_s2021_h1025_w1025_640.jpg
m2_2_dsg_graycos_feat1024_s2021_h1025_w1025_640.jpg
m5_5_dsg_graycos_feat1024_s2021_h1025_w1025_640.jpg
m10_10_dsg_graycos_feat1024_s2021_h1025_w1025_640.jpg

m1_1_dsg_pal_feat1024_s2021_h1025_w1025_640.jpg
m2_2_dsg_pal_feat1024_s2021_h1025_w1025_640.jpg
m5_5_dsg_pal_feat1024_s2021_h1025_w1025_640.jpg
m10_10_dsg_pal_feat1024_s2021_h1025_w1025_640.jpg

While the images above can help perhaps each reader answer for themselves that basic question of whether DS “works” or not, depending on what they want out of it anyway, there’s a bit more to be said about why does it work the way it does, in the first place. How can it even be that such a simple and rigid, grid-based method can generate nonetheless images that are – if anything – less obviously grid-like than some generated for instance with the fbm and trigonometric distortions of the input domain?

Your own answer to the above might be different from mine and if it is, I’d be quite curious to hear it so write it down in that comments box below this article. The way I see it though, this patterned but not rigidly grid-like result of an otherwise strictly rectangular and grid-based method is not that surprising, since DS seems to me to be a very smart simplification (in that it picks out of a lot of complexity the very core that matters most for the task at hand) of a chaotic system, nothing less. After all, look at that application of a square frame and note that its rotation and then halving (hence: contraction) is precisely the sort of iteration required by an IFS (iterated functions system) to ensure a unique attractor. So yes, the chaos got trimmed to the bare minimum perhaps, what with the fixed square shape, the pseudo-random numbers and the very limited number of steps for fully calculating each image (each point in the image really is calculated in fact only once – at least unless you insist to basically iterate the DS itself, as well). Nevertheless, it turns out that a drop – a well-chosen drop – of chaos is quite enough for the screen to lie quite convincingly or at least convincingly enough for the human eye.

March 6, 2021

Ada’s Dirty Pointer Secrets: Passing Dynamically Allocated Arrays from Ada to C

Filed under: Coding — Diana Coman @ 7:47 pm

In a rather prissy manner and for all its significant advantages otherwise, Ada has this very annoying habit of glossing over and leaving *silently* to others – most usually and for historical reasons to C – essential bits and parts that are needed but don’t quite fit all that easily into the clean and tidy worldview that Ada itself can strictly check and enforce. As a result, the whole “program in Ada” pleasant environment holds only if you don’t look too deep into it and for as long as you steer away from any real world tasks that tend to include very soon such messy things as interacting with databases 1, or working *fast* with large data structures that you really don’t afford to handle daintily, one element at a time, without pointers and the like. As soon as you venture into such things, programming in Ada becomes instead very quickly an exercise in “interface with C” as far as I can describe it and moreover, you are pretty much left to figure things out on your own, presumably because it’s exactly when things get difficult that you truly want to find yourself suddenly on your own and without any guarantees, isn’t it?

Anyways, long story short, Ada deigns at least to provide a thin layer of bindings for the C types, some sort of pointers (“access” types), the ‘Address attribute and even a package for converting between address and access (not that it makes very clear, explicitly, the difference between the two – why write it if you can figure it out yourself anyway) as well as another package for pointer arithmetic if you really are the sort of low life to do such dirty things. Based on those and on my (exasperatingly) recurring need of interfacing with C code, I ended up essentially exploring different ways 2 to pass dynamically allocated arrays from one side to another and even back, while at the same time just learning Ada as well, since reality tends to be what it is rather than what would be recommended or even reasonable. Nevertheless, I finally got to the point where I’d rather document at least *one* working way of passing dynamically allocated arrays from Ada to C and have it therefore as some sort of reference of my own (since there’s no other type of reference I can find anywhere on the topic) in one place for all those future times when I’ll run yet again into this same problem because by now it’s quite clear enough to me that it will be needed again for sure.

To transfer basically Ada-allocated pointers to C, the core of it all is to pack Ada’s own pointer so that even its otherwise hidden additional information is taken into account – this allows direct use then on the C side 3. On Ada side, there are first a bunch of declarations for the desired element type (in this case the most basic type possible, namely one raw, unsigned byte – technically this would be unsigned char in C), an unconstrained (ie any size) array of that type, a pointer to such an array and then the record that groups together the pointer and the array’s actual size:

with Interfaces;
with Interfaces.C;
with Ada.Unchecked_Deallocation;

package AdaC is
--  type u8 is mod 256;
  subtype u8 is Interfaces.Unsigned_8;
--  pragma Convention(C, u8);

  type u8_array is array(Interfaces.C.size_t range <>) of u8;
  pragma Convention(C, u8_array);

  type array_pointer is access all u8_array;

  type u8_buffer is
    record
      data: array_pointer;
      size: Interfaces.C.size_t;
    end record;
  pragma Convention(C_Pass_By_Copy, u8_buffer);

In the above, I preferred to use the library type Interfaces.Unsigned_8, mainly because it is the type that I am using otherwise throughout a whole lot of useful code so I’d really rather *not* have to convert anything (having to convert each element of an array or something kind of defeats the purpose of the whole exercise in the first place). The pragma Convention C is supposedly the default convention for GNAT anyway but I’d rather have it explicit where possible (for my u8 type it’s commented out since I define u8 as a subtype of an already existing type). The pragma convention c_pass_by_copy does what it says. The next missing bit on Ada side is to define as well a way to deallocate the memory allocated (the prissy way says to not use this dirty unchecked_deallocation since the pointer will simply end its life when out of scope; the glossed over part is that there is no guarantee that the memory used up is recovered and re-used as well – so in principle, you could end up out of memory simply because… it never gets reused) and then to import the C function that is to use this Ada-allocated array:

  procedure Free is new Ada.Unchecked_Deallocation(u8_array, array_pointer);

  function Func_C( ptr: access u8_buffer)
        return Interfaces.C.int;
  pragma Import(C, Func_C, "func_c");

end AdaC;

On the C side, the equivalent structure (struct) has to have one additional pointer member that is basically a placeholder – because Ada passes with the access type some additional data that C has no idea about, one has to…figure that out, shake one’s head and then pad the structure to account for it, as disgusting as that might be:

struct u8_buffer {
  unsigned char *data;
  void *placeholder;
  size_t size;
};

int func_c( const struct u8_buffer *d);

For the basic testing part, the above C function goes through the array’s elements, printing them in turn and returning their sum. The basic testing on Ada part allocates the array and initializes it, calls the C function and prints it all as well, to admire just how well the prissy can get along with the dirty workhorse, despite claiming that they have nothing in common at all:

int func_c( const struct u8_buffer *d) {
  size_t i;
  int sum;
  sum = 0;
  printf("From func_c in C, the buffer has size %zu and elements:\n", d->size);
  for (i=0; i< d->size; i++) {
    printf("%d ", d->data[i]);
    sum = sum + d->data[i];
  }
  printf("\nFunc_C is done.\n");
  return sum;
}

with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C; use Interfaces.C;
with Interfaces; use Interfaces;

package body AdaC is
  procedure Test is
    arr : u8_array := (3,14,29,255,8);
    buff: aliased u8_buffer;
    res : Interfaces.C.int;
  begin
    Put_Line("u8_array in ada has size " & size_t'Image(arr'Length));
    Put_Line("u8_array in ada has elements:");
    for i in arr'Range loop
      Put(u8'Image(arr(i)));
    end loop;
    New_Line;
    -- now set it in buff and pass it to func_C
    buff.size := arr'Length;
    buff.data := new u8_array'(arr);
    -- alternatively, initializing with null and then setting the value:
    --buff.data := new u8_array(arr'First..arr'Last);
    --buff.data.all := arr;
    Put_Line("Ada calling C...");
    res := Func_C( buff'access );
    Put_Line("Ada got result " & int'Image(res));

    -- test 2, change some values
    buff.data.all(2..3) := (1,2);
    res := Func_C( buff'access );
    Put_Line("Ada got result " & int'Image(res));

    Free(buff.data);
  end Test;

end AdaC;

  1. This includes filesystems and for the record, the GNAT implementation of sequential-io relies in the end still on C functions, have a look sometime and follow the gnarled thread that starts in adainclude/a-sequio.ads (aka package Ada.Sequential_IO) and goes all the way to s-crtl.ads aka System.CRTL aka simply a collection of imported C functions (either GCC or C library) from strlen and atoi to fclose, fseek, read and write. Now how much Ada is then this Ada.Sequential_IO implementation?[]
  2. One of the earliest attempts with char_array is published here.[]
  3. On a side note and just like with a lot of other things, doing this is an exercise in frustration when you have no idea about it and otherwise it becomes suddenly very easy indeed *when you know what you are doing*. So next time you are lucky enough to find someone who knows what they are doing, maybe save yourself a lot of frustration and just *work with them*?[]

February 28, 2021

A Bug in the GNAT or How Iterators Killed Finalization

Filed under: Coding,Dark Modern Ages,Open Sores — Diana Coman @ 10:02 pm

The GNAT in question is any version of a bunch really but since all of them are inflated to a monstruous 360M size even when archived, there is perhaps no surprise that most of that code is better left unused if one can’t directly discard it. Fortunately, at least some parts can be routinely and specifically excluded by means of specifying a hefty list of “restrictions” that gprbuild duly enforces. As it’s currently the case with almost everything around, the *more* restrictions you can keep in place explicitly, the *better* – for the final result but also for your own safety and sanity, too! In this specific case, better turns out to include even getting rid of buggy code in GNAT itself, not to mention avoiding weird errors and compilation fails that could easily eat up days to hunt down otherwise.

As I have always started any Ada project with ALL possible restrictions active and then relaxed some of them as, when and indeed only if absolutely needed, I am sure I have in fact missed a lot of opportunity for more exciting programming sessions – so many bugs and obscure errors waiting in those 360M of code for their chance to shine and so few chances for it when I really refuse to “need” unbounded this or tagged that, finalize this or iterate the other 1. Still, as on one hand the gfx pipeline really can’t quite do without dynamic memory allocation 2 and on the other hand I had probably grown a bit too comfortable with Ada otherwise, I finally had a hefty dose of GNAT-excitement and bug hunting. It all started with this wonderfully informative error suddenly bringing all compilation to a halt, just as I was in the process of replacing 3 the prototype gfx-pipeline with the production version that had otherwise compiled and worked perfectly on its own but now suddenly… failed:

main_gfx.adb:22:09: instantiation error at a-convec.adb:2006
main_gfx.adb:22:09: instantiation error at gfx_types.ads:53
main_gfx.adb:22:09: “” is undefined

The above 3 lines are *all* of the “error”, too, I didn’t trim anything away. Basically the second line is the entry point from my code – a simple instantiation of a generic package (gfx_types) that otherwise instantiates in turn a package from the standard containers library – a vector, implemented apparently in that a-convec.adb. A look at a-convec.adb 4 reveals an unexpected and disgusting degree of infestation with iterators but otherwise no direct screams of bloody murder in any more specific terms:


return It : constant Iterator :=
(Limited_Controlled with
Container => V,
Index => No_Index)

The first and foremost question is of course just why exactly is there anything related to iterators in the first place, when I am *not* using any such things anywhere in my code (and for good reason – they are implemented in the sort of “helping” way that suddenly requires a whole additional bunch of restrictions to be lifted because… well, because the iterators say so, ok?). Sneaking suspicions thus aroused, I checked again the restrict.adc of the project that was failing. Sure enough, it turned out that I had forgotten to revert a previous ill-advised relaxation of the “No_Finalization” restriction. For the record, that removal of the No_Finalization restriction was itself the result of this other time when my undying optimism insisted that the Controlled_Type with its guaranteed Finalization can actually be useful – in practice it turned out more trouble than it’s worth it AND it insisted bringing in with it the whole tagged mess so I ditched it but apparently the harm was still done since I had forgotten to restore also this restriction (the rest of the bunch I had restored and yes, I checked all of them now again, indeed).

Turning on again the No_Finalization restriction meant that my whole project compiled again happily and perfectly, not to mention to my huge relief (despite this brief account, it took a bit longer in practice to home in on the precise restriction that was missing). What happens there is simply that the No_Finalization restriction disables the whole of “controlled” and “limited controlled” type and their derivations meaning in turn that the buggy code that forced iterators down my throat is not included – basically, by means of enforcing this restriction, I get yet again to not have the same problems that everyone has.

Once my code compiled again, I was still left with the unwanted but unavoidable task of figuring out just what the trouble was anyway – because this is not the sort of thing to just ignore “because it works now”. So I read a bit more around that GNAT code and then set out the smallest possible example code to reproduce the trouble. Sure enough, it was reproduced swiftly, but this time with a more informative message that suddenly ringed a bell too since I had seen it only a few days before (and naively thought at that time that it had to do with something else entirely):

smallest]$ gprbuild
using project file fail.gpr
gcc -c -O2 -fdump-scos -gnata -fstack-check -gnatyd -gnatym -fdata-sections -ffunction-sections -gnatwr -gnatw.d -gnatec=smallest/restrict.adc main.adb
+===========================GNAT BUG DETECTED==============================+
| GPL 2016 (20160515-49) (x86_64-pc-linux-gnu) Storage_Error stack overflow or erroneous memory access|
| Error detected at a-convec.adb:2006:7 [p1.ads:7:9 [main.adb:7:9]] |
| Please submit a bug report by email to report@adacore.com. |
| GAP members can alternatively use GNAT Tracker: |
| http://www.adacore.com/ section ‘send a report’. |
| See gnatinfo.txt for full info on procedure for submitting bugs. |
| Use a subject line meaningful to you and us to track the bug. |
| Include the entire contents of this bug box in the report. |
| Include the exact command that you entered. |
| Also include sources listed below. |
| Use plain ASCII or MIME attachment(s). |
+==========================================================================+

Please include these source files with error report
Note that list may not be accurate in some cases,
so please double check that the problem can still
be reproduced with the set of files listed.
Consider also -gnatd.n switch (see debug.adb).

smallest/main.adb
smallest/p1.ads

compilation abandoned
gprbuild: *** compilation phase failed

For the record, the code to reproduce the above is very small indeed: all you need is to define a Vector type from within a generic package that you instantiate in your main (defining the Vector type directly within your main will *work*). My test code has a main.adb and a p1 package without a body even (hence just a file, p1.ads) with the following content:

main

with Ada.Text_IO; use Ada.Text_IO;
with P1;

procedure main is
precision: constant Natural := 16;
type FType is digits precision;
package P is new P1(T => FType);
begin
Put_Line("Calling P...");
end main;

p1.ads

with Ada.Containers.Vectors;

generic
type T is digits<>;
package P1 is

package fail is new Ada.Containers.Vectors( Index_Type => Natural,
Element_Type => T);
use fail;

end P1;

In a nutshell, the above is the story of how the buggy must-have-iterators implementation of Vectors in GNAT’s standard Ada.Containers library effectively kills with one single shot the use of any Finalization 5 since you can’t have both in your program without either finding a different way perhaps to avoid that bug or otherwise, more likely, simply running into trouble as above.

On the bright side, the GNAT implementation of Finalization had already managed to convince me fully that it sucks and so overall nothing useful is lost, a new restriction is firmly in place and otherwise concrete evidence is gained as to the clear benefits of restricting rather than permitting anything by default. If only GNAT came with a way to also discard all that buggy and useless code that I have to keep away with restrictions…

  1. All containers from the standard library, such as vectors, lists or hashmaps provide iterators because they are supposedly so much better and more convenient and more wonderful than … you know, iterating the thing the way you want it when you want it. So much better in fact that they bring then a whole lot of trouble with them too, from having to ensure that the iterated elements don’t change unexpectedly to pulling in the whole tagged pie aka the “Object Oriented” mud stuck to Ada because otherwise it was probably suspiciously clean or something.[]
  2. This is mainly because of the whole rasterizer approach – the moment one *has to* produce a full list of all vertices and normals and whatnots at every point of a model made out of several surfaces too, there is little choice but to allow dynamic memory allocation too – allocating the maximum (which can be calculated, certainly) needed to cover all cases is really a huge overkill and generally worse, namely a stack overflow.[]
  3. I never really want surprises but there are such times when I want surprises even less than usual – that very moment when I’m replacing important parts of a complex mechanism and therefore the whole is eviscerated and both my hands as well as my head are quite full of it certainly qualifies for one of the worst possible times to have surprises.[]
  4. Which can be in various places deep in gnat, depending on the exact version you have but if you installed Adacore’s gnat to the default location, you can find it at /usr/gnat/lib/gcc/x86_64-pc-linux-gnu/4.9.4/rts-sjlj/adainclude/a-convec.adb or (if you are not using sjlj) at /usr/gnat/lib/gcc/x86_64-pc-linux-gnu/4.9.4/rts-native/adainclude/a-convec.adb. The two files are identical, according to diff.[]
  5. In brief, no Finalization means no controlled types and their ilk. In detail, Adacore’s docs of GNAT contain the following description of the No_Finalization restriction:

    5.1.31. No_Finalization

    [GNAT] This restriction disables the language features described in chapter 7.6 of the Ada 2005 RM as well as all form of code generation performed by the compiler to support these features. The following types are no longer considered controlled when this restriction is in effect:

    Ada.Finalization.Controlled

    Ada.Finalization.Limited_Controlled

    Derivations from Controlled or Limited_Controlled

    Class-wide types

    Protected types

    Task types

    Array and record types with controlled components

    The compiler no longer generates code to initialize, finalize or adjust an object or a nested component, either declared on the stack or on the heap. The deallocation of a controlled object no longer finalizes its contents.[]

February 24, 2021

The Beggars’ Trade

Filed under: Sense and nonsense — Diana Coman @ 11:54 pm

~ This is the very loose English version of an article of mine written in 2011. ~

I don’t give money to beggars and I never did, quite deliberately. Nevertheless, some years ago, I gave all the pile of coins in my purse to a woman in the street, someone I had never seen before nor since. I still recall the way it happened and the few words she repeatedly said to and even after me, as if hoping for an answer that I did not have and therefore could not give her at the time: “forgive me, please forgive me!”

She hadn’t begged nor even asked for anything, not directly, not with any spoken words, nor with any pleading look, nor even trying at all to meet anyone’s eyes. I had observed her idly for a while, as I was waiting for a friend of mine, but she had simply stood there, seemingly just as cold and miserable -neither more, nor less- as all the other people that were waiting at that stop on one of the main streets of Bucharest, one early spring 1. She had moved about a bit as if to warm up and then, all of a sudden, she had shouted “I’m hungry!” – a single, unrepeated and unexpectedly loud shout that had seemingly burst out of her and that carried far through the crisp air, alongside the overpowering smell of freshly made, hot pretzels and donuts from the corner shop. No other words were spoken, no heads were turned at all, some even got distinctly more rigid. A few backs sagged a little more, a little further, that was all.

I observed her a little longer from where I was at the entry to a park, some distance away, as she continued to stand where she had been, still looking at the pavement, still seeming otherwise from a distance quite similar to everyone else around her. After a while, I walked over to her, caught her eye and gave her all the coins I had on me but as I fished them out of my purse, I was paying more attention to the odd bits and pieces that got initially caught in the pile than to anything else. She started apologizing as I was piling the coins in her cupped hands and whether she heard or not whatever answer I made, she continued asking me for forgiveness even as I said good bye and then turned and left.

The beggars I had seen before (and even since) certainly have a wide range of responses at the ready – they might give thanks of any and all description, they might shrug it all off with indifference or they might even be as insolent as possible at times, but they hardly ever apologize and they certainly don’t ask for anyone’s forgiveness. After all, why would they apologize and over what exactly? And why would they ask for forgiveness when they are in the street precisely to sell what is essentially a form – if empty form and nothing else – of forgiveness? Like all other street sellers, beggars simply advertise their merchandise and go each day to their place in the street to find their clients – those who give them alms.

Despite its frowned upon status and general branding of all sorts, begging is just a trade and even a very popular (if meanwhile increasingly more refined and even institutionalized) trade indeed, as the merchandise on offer is in really great demand. This demand though is neither the merit nor the fault of the beggars themselves but merely a reflection of the buyers’ own desperate need. While many things may be said about beggars’ advertisement tactics and even about their choice of trade itself, they hardly need to create any demand: they are merely constant and reliable providers of the cheapest sort of satisfaction for which there is already a huge appetite otherwise. Like all very cheap things, the provided satisfaction is, of course, worth very little indeed but this poor value as well as the resulting popularity of the trade itself is not the fault of the seller – it’s all the buyers’ choice and doing, at every step of the way.

The beggars’ merchandise is indeed very cheap because it’s also entirely illusory – empty feelings are provided, packed as required by ever more demanding buyers within stories made for purpose and then acted for days and days on end, directly in the street. But focusing on the story or even on its fake nature is missing the point entirely. Although central in a way to begging 2, the story that each beggar tells is mere packaging and presentation, essentially branding – the only available way to stand out from the competition that is otherwise selling the exact same thing, not different in any way at all, neither better nor worse, neither bigger nor smaller, neither more nor less valuable, just precisely and exactly the same. After all, how could exactly one nothing be different from another nothing? For the price of the alms given, the givers take for themselves as much feeling of kindness and of moral superiority as they literally want to, obtaining it all at a heavily discounted price and overall negligible cost.

What is being sold thus is a prepackaged, mass-produced “good deed”, a sort of extremely cheap and therefore easily affordable ersatz of the significantly more expensive deeds of any actual charity. Beggars are essentially modern indulgence sellers -there is significant guilt at the root of the demand for illusions instead of reality- and as such, they are quite correct to show disdain for alms that are too small or of the wrong sort: if people didn’t value that much their own laziness and those easily obtained feelings of kindness and superiority, they wouldn’t be looking to buy those illusions in the first place and would go instead through the much more significant trouble of living with as much or as little charitable acts as they might be able to do on their own.

The trouble with good deeds that one doesn’t just buy at the street’s corner is that they tend to require significantly more effort than giving away some money and when they also require actual involvement, they can easily be frightening to *do*: who knows what one might find about oneself in the process and what deeply held and never before questioned beliefs might be exposed to the unforgiving reality! Much better thus to buy simply from beggars the illusion of one’s own kindness – it’s tamer and safer not to mention way, way cheaper, too! Beggars’ trade exists after all simply as a visible sign of people’s laziness and desire for a cheap and cosy, overall undemanding life. So beggars will play their part pretending to need help and setting up the stage with the story, all the required props and even a steady flow of spectators as they pass through the street, while buyers will pay for the privilege to play the coveted role of benefactor and sit on the cardboard throne erected for this very purpose. There’s nothing wrong with it either – play the role you want to play, only don’t complain at the end that your throne is just a soggy piece of cardboard.

Beggars sell illusions, indeed. Because the reality is too expensive and it doesn’t sell well at all, either.

  1. There’s a specific type of misery linked to waiting for a long time in the cold for a bus that is routinely late and even more routinely packed, going as well, in most cases, to a place that is equally cold and perhaps only slightly less packed.[]
  2. There’s a Romanian film of some documentary value on this topic among others: Filantropica, by Nae Caranfil, 2002. There’s a review of it on Trilema, too.[]

February 13, 2021

Blowhate, Torus Blowhate

Filed under: Coding,Computer Graphics — Diana Coman @ 1:47 pm

For the past week, Eulora’s latest version of client and server have been communicating with one another happily and uninterruptedly – as well as actually RSA-authenticatedly and Serpent-encryptedly, generating, exchanging and automatically burning keys as needed, creating accounts, exchanging IPs and generally doing everything as required, not to mention being able to recover from all sorts of troubles, errors as well as any other difficult & unexpected situations that the hell otherwise known as “testing setup” throws at them. So I watched them for a while – there is some beauty to working things going on about their job and handling it all without skipping a beat – and then I switched to just keeping an eye on them, checking logs, sampling measurements from time to time and generally taking notes for future minor and less minor further improvements that are perhaps possible. As useful as all that is though, there’s hardly anything in it to keep me busy for hours, let alone for days. So I rebalanced by getting back to the graphics pipeline that was patiently waiting for me to pick it up again.

The step taken this time on the graphics side covered the implementation in Ada of the polygonization of an implicit surface – where “surface” is a very loose term, covering anything at all, as long as it’s given through a function able to return positive, negative or zero at any point, corresponding to some convention as to whether that point is to be considered outside, inside or exactly on the surface of interest 1. In the overall graphics pipeline, this polygonization of a surface is a mandatory step for obtaining a mesh that CS/Cal3d can work with – such a mesh is needed both for moving objects 2 and for non-moving objects of any sort that might be found somewhere in Eulora.

At the previous prototype stage, I had relied on a C implementation of Bloomenthal’s algorithm for polygonization of implicit surfaces using essentially a 3D lattice of cubes to gradually explore all the space where the surface might be. While the C implementation is quite neat and has certainly been useful during the prototyping stage, it is quite tightly packed indeed 3, so that clarity is not exactly its plus and it also has some limitations (most notably on the total number of vertices due to the hashes and hashmaps it defines and uses, as well as overall on the size and level of detail of shapes it can handle, since it caches most of the data and this means that it runs out of memory on too large or too detailed shapes). Moreover, there’s nothing like implementing an algorithm to *fully* get to know it in detail, especially from a practical (as opposed to merely theoretical) point of view. Finally, I should probably also add that I’d very much prefer to have the full pipeline in Ada rather than keep mixing languages at all steps, so I had to implement this part as well anyway.

The translation of code from C to Ada is not all that straightforward even if one attempts as a first step to do just a pedestrian copy – there are simply structures and approaches that don’t have direct equivalent or are plainly illegal in one language while being the very core of implementation in the other. This was very clear from the very start so I didn’t even try that, but I went instead through the original C code very slowly, with pen and paper in hand, figured out all the pointer gymnastics, bit diddling artifices (C-style, it is what it is), global variables, intricate data structures and their various roles as well as the exact way in which they end up linking to one another (there are linked lists, of course, but also multi-dimensional lattices and lists of lists – quite standard fare for C programming, exactly as I recall it from all those years back even though it took a while to get back into that frame of mind). Gradually, I could find the seams on which to cut the whole into parts and then I could as well start implementing it step by step (as opposed to trying to do it all in one go so that there wouldn’t even be any way to know what or where the trouble was, if it failed.

A few parts of the new implementation could be directly tested against the output from the original C implementation. Most notably in this category, the cube table storing all possible polarities of a cube and their corresponding resulting polygons. For those parts, I instrumented the C code to produce some reference output and then used that to write a test that captures thus exactly what the result should be. But the trouble with polygonization of surfaces (and possibly graphics, more generally) is that there isn’t a single “correct” solution for most tasks – so one can’t really compare results in such a direct way. Moreover, since floating point calculations are significantly involved at all steps and the 2 programs use different prngs, it’s quite guaranteed that the vertices obtained will *not* be the very same – so comparing the list of vertices and even that of triangles is pointless. The more important part is whether the result does cover indeed the intended surface and whether the output fits as expected within the existing pipeline afterwards. So to check this part, I used first a simple surface – the torus, undeformed by anything – and otherwise directly inserted the plain text output of my Ada-polygonizer into the rest of the existing pipeline, basically handing it over as input to generate the exact xmls for mesh, cal3d mesh, then model and fitting animation. All went swimmingly, the model was created and packed, then the file chunked and indexed, the character created for my test player and as a result – meet the pc of many tori, otherwise known as Blowhate, Torus Blowhate:

blowhate_1_640.jpg

As you can see in the picture above, so far the shape is undistorted (not to mention not at all the usual mesh that I use otherwise for creating hopefuls). The apparent distortion of the torus is due to the animation really – it bends the uncooperative shape at a weird angle. Nevertheless, the relevant part for me at this stage was that the polygonizer actually produces a torus as opposed to whatever else and that its output has been successfully consumed otherwise by the formatter and the rest of the pipeline. The next step will be to write in Ada the parts producing also all the required formats directly and then bring back the more interesting shapes, port to Ada the rest of the pipeline as well and finally integrate it all so that it provides any required graphics whenever needed.

On a side note from all the fun above and since I have this occasion to compare the two languages in some concrete situation, I can add that the whole of “Ada is very verbose while C is oh so very compact” doesn’t turn out to be all that true in practice: the original C code has 808 lines (even after discarding some parts that were really not needed such as the display on a SGI workstation), while my current Ada polygonizer has 934 lines (.ads + .adb files) and I didn’t try in any way to make it compact (ie, there still are plenty of comments too and I’m sure that even the code itself can be made more compact if aiming for that). What I can say on this is that the C code spends a lot of lines on defining and allocating/deallocating memory for all those intricate data structures that it uses for caching some data (not even all data, though). Given that my Ada implementation does *not* cache the intermediate data at all so far, there are way fewer new definitions for data structures to start with. There are still some allocations for the final data but those use predefined data structures.

From a practical point of view, the current Ada implementation still requires a few iterations that will be best informed by use, as soon as I get the full gfx pipeline implemented in Ada and so I can put it to some serious use. For now, it handled happily situations that the C code could not handle (e.g. not choking on “too large” shapes, nor balking just as easily on “could not find starting point”) but it is true that all that re-calculating of surface values every time can increase the run time when the number of visited cubes is high enough 4. Nevertheless, so far at least, it didn’t really matter for the the sort of meshes I needed to polygonize – if it turns out that it does matter though, I’ll update the implementation to cache the values one way or another, it’s certainly perfectly doable in Ada just as well although without all the lists of lists necessarily.

  1. The inside vs outside distinction is important in computer graphics because of how the lighting models work.[]
  2. PCs aka player characters and NPCs aka non-player characters.[]
  3. Note that I’m using the direct cube-based polygonization as opposed to the tetrahedral-based variation that he includes as well. The tetrahedral-based variation first splits each cube into tetrahedra and then polygonizes those as it’s a simpler task – the whole implementation is therefore in principle shorter and easier to follow but it results in even more vertices and triangles for the same surface. When used for Eulora’s purposes, all those additional vertices and triangles take up space and basically cost to be processed, stored and then sent over to the client at the very least, while not necessarily making otherwise a huge difference to how the mesh looks on screen (since more detail is not always actually an improvement). So I kept at least for now to the polygonization that gives the most compact *result* even if it requires perhaps a more complex implementation. After all, the implementation is done only once.[]
  4. For a concrete data point here: the Torus shown in the screenshot is generated with a cube width set at 0.05 and a maximum number of cubes in each direction set at 40 (this makes for 81*81*81 total maximum of visited cubes). The Ada implementation took 0.08 seconds on average to do it, while the C implementation took 0.02 on average.[]

February 2, 2021

Young Enthusiasms and Old Memories

Filed under: Lyf,Young, old and oldest — Diana Coman @ 1:42 am

It arrived this Saturday afternoon and I got for starters almost 5 full minutes alone with it – apparently that’s ample time for everyone to figure out where the most interesting action of the moment is going on and come running from all and any corners of the house. They came though and so I simply made space for them, then set the child at it, showed him how to hold his hand and how to play the keys and then set him up with a simple scale exercise too, for I could easily wait, while he couldn’t, not really, for all his honest and good-natured attempt at it. His enthusiasm is strong and fiery and young – too young to know how to burn brightly weeks, months and years whole. All it knows for now are barely todays and at a stretch tomorrows. Those are all that can be known by inexperienced enthusiasms on their meager diet of minutes and hours that fail to sustain – how could they sustain anyway, when they are mostly filled with wait, when there are still so many of them in the future to wait for and so few of them in the past to know from?

I don’t deplore though the short life of youthful enthusiasms of all sorts. Instead, I tend to sustain them when I can and to let them fill thus perhaps with experience rather than empty wait, those minutes and hours – few or many, as they may be – that they burn through. In this case, the sustenance was well received, the burning is still ongoing and the enthusiasm is apparently only growing stronger, at least for now. Long story short though, the child got to explore this new piano before I did and I got to take pictures of him in the act:

piano_1_640.jpg

On that same Saturday, only later on, I sent the youth to sleep and took advantage of the sudden peace and quiet to try and see if I can still play anything at all. After more than 10 years of not even touching a piano, let alone practicing or learning or playing or anything of the sort, I was quite surprised at how easily a lot of it (I doubt it’s all!) came back to my mind – and at least a good chunk of it to my fingers, too! Still, there is also enough tripping over my own fingers to make it clear just how much was lost as well.

The above is, of course, just how it all seems to me now, since I don’t actually have *any* recording of any time I played the piano all those years ago and so there isn’t even anything more reliable than my memory to directly compare and measure the change the years made. There is, of course, nothing I can do to fix that but there is nevertheless something I can do to avoid a repeat of this very same trouble for my future self, namely record and document the way I play now, on an unknown (if very pleasant actually) piano 1 and freshly back at it after such a long and total break. While I kept it at least to the easy classics for now to avoid too much harm to anyone’s hearing, be warned if you do click on it, that I still trip over my fingers (or rather they go ahead of myself!) at times: recording (mp3) of my playing fresh after a 10+ year nearly total break.

  1. Until this year, I had only ever played acoustic pianos, although both upright and concert/grand pianos. However, the technology in digital pianos nowadays – in the best ones at least – has advanced a lot, to the point where I can say that my digital piano is certainly better than some old acoustic pianos I played long time ago. At any rate, the keys are made to simulate extremely well those of an acoustic piano so that indeed, they feel exactly like my fingers remember those of the concert/grand piano, not only as touch and release but also as to change in sound obtained by different pressure – and I was very skeptical in the beginning of such a claim being anything more than just a claim. There’s a lot more to the digital piano technology than keys though and the way the “voices” of a digital piano are obtained from start to end make for fascinating reading actually.[]

January 24, 2021

Christmas Time No. 3

Filed under: Lyf,Young, old and oldest — Diana Coman @ 11:45 am

snow_3_640.jpg
snow_4_640.jpg

A bit delayed according to christmas no 1, a tad late even according to christmas no 2 1 but right on time for the newly minted christmas no 3, the snow delivery today was otherwise perfectly timed, starting quietly as we were waking up and then picking up heart to come down dense and steady for a lovely breakfast background, with huge white flakes crowding the air and turning the ground quite quickly into the very colour of today’s winter sky. Then there was nothing but white above one’s head and white under one’s foot, the air was crisp, the streets deserted and the fresh snow almost forming by itself into snowballs at the lightest touch of hand. So we got a snowball fight going and I even got to take a few pictures in between making, throwing and otherwise dodging snowballs but that was basically handicap-fighting so enough is enough, I’ll dump those here now and be done with all this picture-taking silly stuff – there’s a serious snowball fight to get back to and everything else can wait!

snow_5_640.jpg
snow_6_640.jpg
snow_7_640.jpg
snow_8_640.jpg

  1. Christmas day has its own time zone of sorts: the more to the East you move, the later in the calendar it supposedly “happens” and so we usually pick and choose, not to mention the times when we add our own date as well.[]

January 14, 2021

Rotating in Full Colour Will Make Your Eyes Hurt

Filed under: Coding,Computer Graphics — Diana Coman @ 2:54 pm

In short, being otherwise rather busy with other matters, I just added the “rotated” pattern to my previous puzzle set and then let it fill my hard-drive with wondrous and amazing… art 1. Being the art lover that I am, I’ve also made sure to bin first a few hundreds GB of previous art, since it’s all getting a bit out of balance here and it’s all so expensive and hard to make and worth a ton of money upfront that I’m happy I don’t have to print all this art too, or I’ll be looking very soon for an even larger rubbish bin.

Back to the matter at hand, the rotated pattern is a combination of domain distortion and multifractals: first it distorts the input space by means of a rotation around the 3 axes by 3 different, pseudo-randomly generated amounts, then it applies a first fbm fractal (Perlin-based) and then it tops that with another pattern (which is in turn a multifractal-based domain distortion and transformation – the “layered” effect from the early prototype). Does all that sound rather complicated? Well, it’s more complicated to write up than to do it, as it’s really just a straightforward combination of existing puzzle pieces – a matter of a few lines added to my puzzle set and then a few days of listening to the purring of one computer busy churning out the results.

Although I rather knew what to expect this time (and hence, what values for each parameter would lead to something useful), I still let the generator try out both grayscale and colour mappings for a full set of octaves, hurst coefficients and seeds. As a result, I can provide here some samples of the direct RGB mapping approach to make your eyes hurt and your head spin – the higher the number of octaves, the dizzying the result, too, unsurprisingly (all parameters are coded in the filenames, the images show the results for 2 seeds, with fixed hurst at 0.812 and number of octaves going for each from 3 to 6):

rotated_7_fbm3_s4009_rotated_h0812_o3_w512_h512_normc_pal3d_default.jpg
rotated_8_fbm3_s4009_rotated_h0812_o4_w512_h512_normc_pal3d_default.jpg
rotated_9_fbm3_s4009_rotated_h0812_o5_w512_h512_normc_pal3d_default.jpg
rotated_10_fbm3_s4009_rotated_h0812_o6_w512_h512_normc_pal3d_default.jpg
rotated_11_fbm3_s4010_rotated_h0812_o3_w512_h512_normc_pal3d_default.jpg
rotated_12_fbm3_s4010_rotated_h0812_o4_w512_h512_normc_pal3d_default.jpg
rotated_13_fbm3_s4010_rotated_h0812_o5_w512_h512_normc_pal3d_default.jpg
rotated_14_fbm3_s4010_rotated_h0812_o6_w512_h512_normc_pal3d_default.jpg

Despite the above pain in primary colours, this rotated pattern can work in grayscale, as long as one keeps to a relatively low number of octaves. Due to the rotation being chosen based on the prng seed, there is also enough variation from one seed to another without having to change otherwise any other parameter. To my eye, the results seem possibly best around 3-4 octaves – fewer than that makes for too little detail in there while more than that packs possibly way too much, so that the result looks more like a mess than some sort of landscape with any features worth the mention. Here are some samples for illustration, with all parameters coded in the filenames (2 seeds, with fixed hurst at 0.812 and number of octaves going for each from 3 to 5):

rotated_1_fbm3_s4007_rotated_h0812_o3_w512_h512_normc_graytrig.jpg
rotated_2_fbm3_s4007_rotated_h0812_o4_w512_h512_normc_graytrig.jpg
rotated_3_fbm3_s4007_rotated_h0812_o5_w512_h512_normc_graytrig.jpg
rotated_4_fbm3_s4008_rotated_h0812_o3_w512_h512_normc_graytrig.jpg
rotated_5_fbm3_s4008_rotated_h0812_o4_w512_h512_normc_graytrig.jpg
rotated_6_fbm3_s4008_rotated_h0812_o5_w512_h512_normc_graytrig.jpg

Considering the above as a possible candidate method for heightmap generation brings up the number of such candidates to at least 3. And so I’m increasingly itching to get to try in practice at least *some* of those, to see how they might work or not for actual walking on and digging into. Just looking at the heightmap image doesn’t do all that much (or at least not for me at the moment) but there are still quite a few steps missing before I could basically deploy a heightmap generator even for testing. So for now I’ll just let the patterns accumulate and maybe even manage to refrain from adding more patterns every other week or so…

  1. Supposedly, playing around with fractals for making pretty images makes one a “fractal artist” so now I’m stuck trying really hard to make horrible images instead, if I’m to stand any chance of rejecting being called *that* name, too! I’ll count it as good motivation too, since the more I keep running into pretty (or at least not downright ugly) fractals at all steps, the more I’d rather find a way to make some properly terrifying ones too, all that pretty starts getting on my nerves already. I have a hunch that it’s probably *harder* to make truly terrifying fractal-based images, at that.[]

January 7, 2021

Illuminating Textures from the Perlin Playpen

Filed under: Coding,Computer Graphics — Diana Coman @ 4:04 pm

On a break from the most recent exploration of the wide open complex space, I went back for another look at last year’s noise-based textures and ended up ever more doubtful that there is a meaningful distinction that goes any deeper than “here’s this trodden path vs there’s the world.” Still, trodden paths have their utility too and it takes thorough exploration to gain some serious doubts anyway, so I went ahead and implemented in Ada a tidy set of puzzle pieces together with a working way to mix-and-match them programmatically even, if desired. Then I set it to loop through various parameters, which it dutifully did over a few days and nights, resulting in a deluge of neatly named pictures that took quite some time to go through. I’ll sample from them for this write-up but I don’t quite think there’s much point in uploading them all – do let me know though if you want to see them all, as I’ll keep them around for a while anyway.

Before diving into the exploration and corresponding images, here’s the core idea of the “fbm fractal” approach:

  1. Structured noise (Perlin is the most common but not the only one) is used to provide that sort of controlled chaos and order mixture needed for meaningful variation.
  2. Waves of the chosen noise, with ever increasing frequency and decreasing amplitude are then simply summed up, basically filling in increasingly more detail, as more waves are added.
  3. The number of octaves (o) gives the number of iterations or, in other words, the number of waves to sum and therefore the amount of detail to include.
  4. The Hurst coefficient (h) controls the way in which the amplitude of the waves is decreased at each iteration and as a result, how noisy (noisiest as h decreases) or smooth (smoother as h increases) the resulting image is.
  5. Typically, the amplitude decreases at each iteration 2^(-h) times, with this quantity named sometimes “gain” or g.
  6. Typically, the frequency doubles at each iteration (hence the “octaves” name) but in principle there is an argument for fuzzying this number between iterations, to avoid a too precise overlap of the noise waves where they are 0 for instance (since such overlap will show up as too-ordered artefacts basically).
  7. Overall, fbm is simply a sum function fbm(x) with terms 2^(-j*h) * noise(2^j * x) for all j between 0 and o.

For the exploration part, I had the generator loop through o from 1 to 10 and through h from 0.112 to 1.112. To keep things reasonably easy to follow, I used a single texture mapping throughout but I had the generator plot the result using 4 different RGB mappings: a sinus-based grayscale (for heightmaps), a direct rgb mapping used by the previous C prototype, a fixed palette-based mapping (using the same sinus-based colour palette as employed for the complex curvy space illustrations) and a phase-variable version of that palette (basically changing shade depending on the seed). Scroll further to see what dramatic difference the colours can make, indeed.

First off and keeping it to the grayscale results, a low number of octaves and a relatively high h seem to give as far as I can tell some possibly useful heightmaps of sorts. Basically a high h is needed to ensure smoothness since noise on heightmaps is rather unhelpful as it creates too sharp jumps from high to low. Similarly, a low number of octaves is required to keep detail relatively low – for this particular pattern at least, there is already enough detail brought in by the pattern itself (the pattern is on top of the fbm, basically a composition -at times recursive, too- of fbm at each point). For illustration, here’s the grayscale series obtained for a single seed with o=2 and h 0.212, 0.412, 0.612 and 0.812:

perlin_playpen_7_fbm3_s4005_fracxyzmt_h0212_o2_w512_h512_normc_graytrig.jpg
perlin_playpen_8_fbm3_s4005_fracxyzmt_h0412_o2_w512_h512_normc_graytrig.jpg
perlin_playpen_12_fbm3_s4005_fracxyzmt_h0612_o2_w512_h512_normc_graytrig.jpg
perlin_playpen_13_fbm3_s4005_fracxyzmt_h0812_o2_w512_h512_normc_graytrig.jpg

When the number of octaves is increased, the number of curves in this landscape increases very quickly and to my eye the result doesn’t look that well as a heightmap although the intermediate o values may very well look fine as a creature skin or some other sort of texture perhaps (h is 0.812 while o changes from 3 to 9):

perlin_playpen_14_fbm3_s4005_fracxyzmt_h0812_o3_w512_h512_normc_graytrig.jpg
perlin_playpen_15_fbm3_s4005_fracxyzmt_h0812_o4_w512_h512_normc_graytrig.jpg
perlin_playpen_16_fbm3_s4005_fracxyzmt_h0812_o5_w512_h512_normc_graytrig.jpg
perlin_playpen_17_fbm3_s4005_fracxyzmt_h0812_o6_w512_h512_normc_graytrig.jpg
perlin_playpen_18_fbm3_s4005_fracxyzmt_h0812_o7_w512_h512_normc_graytrig.jpg
perlin_playpen_19_fbm3_s4005_fracxyzmt_h0812_o8_w512_h512_normc_graytrig.jpg
perlin_playpen_20_fbm3_s4005_fracxyzmt_h0812_o9_w512_h512_normc_graytrig.jpg

While working in grayscale, there is little point in increasing o and h beyond 9 and 1 respectively: the result just ends up very noisy and/or matted. However, when colour is brought in, the situation changes, as different parts can get effectively highlighted in such different ways that I can’t say I have any sort of concrete interval to offer as a rule – it’s more likely to depend on the exact colour mapping really. At any rate, the low o and h values can make for clear(er) patterned textures while the higher values (with h even beyond 1) can make for quite striking skies or even lava or similar perhaps – basically I have no idea what they are exactly but there are quite a few that I just like looking at! Anyways, here are some illustrations, with all parameters coded in the filename:

perlin_playpen_1_fbm3_s4000_fracxyzmt_h0612_o4_w512_h512_normc_fpal3d_default.jpg
perlin_playpen_2_fbm3_s4000_fracxyzmt_h0612_o4_w512_h512_normc_pal3d_fsinglef.jpg
perlin_playpen_3_fbm3_s4005_fracxyzmt_h01012_o7_w512_h512_normc_pal3d_fsinglef.jpg
perlin_playpen_4_fbm3_s4005_fracxyzmt_h0112_o2_w512_h512_normc_pal3d_fsinglef.jpg
perlin_playpen_5_fbm3_s4005_fracxyzmt_h0112_o3_w512_h512_normc_fpal3d_default.jpg
perlin_playpen_6_fbm3_s4005_fracxyzmt_h0112_o3_w512_h512_normc_pal3d_fsinglef.jpg
perlin_playpen_9_fbm3_s4005_fracxyzmt_h0412_o3_w512_h512_normc_pal3d_default.jpg
perlin_playpen_10_fbm3_s4005_fracxyzmt_h0412_o3_w512_h512_normc_pal3d_fsinglef.jpg
perlin_playpen_11_fbm3_s4005_fracxyzmt_h0412_o3_w512_h512_normc_pal3d_phasevar.jpg
perlin_playpen_21_fbm3_s4009_fracxyzmt_h0212_o3_w512_h512_normc_pal3d_fsinglef.jpg
perlin_playpen_22_fbm3_s4010_fracxyzmt_h01012_o8_w512_h512_normc_pal3d_fsinglef.jpg

All the above use a single pattern of all those I made last year. There would be in principle all the other patterns to translate over to Ada and then perhaps explore further. There can easily be more/new patterns to explore too, but at this stage it’s not all that clear to me if this is the best direction to press forwards. Compared to the iteration of complex polynomials, this approach is basically limited to a carefully chosen playpen but it comes as a result of this strict limitation with some guarantees regarding the full coverage of the texture space for all seeds and otherwise a guarantee regarding the result based on the type of pattern chosen at any time. Perhaps there is some use for both approaches (noise-based and iterated complex functions) but in any case, at the moment there seems to me to be more promise in pushing perhaps further the more open case of iterating functions rather than in further tweaking the various parameters in this specific playpen of noise-based textures. Then again, there are plenty of *entirely other* things to push further at the moment, not even texture or heightmaps related!

January 3, 2021

His You, My Me

Filed under: Lyf,Young, old and oldest — Diana Coman @ 7:12 pm


Ah! El spuse adevarul. Eu am ras, n-am zis nimica.

“You, you, you.”
“Me? Me it is, then.”
“Yes, you, you and you!”
“So, me, what’s with me?”
“The thing with you is you and that’s why I want you!”
“What do you want me for?”
“For comfort!”

So it goes, so it shows, so it is – for as long as it lasts, one season’s time, one blink of an eye, one ripening of fruit.

jan2021_2_640.jpg
jan2021_3_640.jpg
jan2021_1_640.jpg

December 31, 2020

Happy New Fractals (and Biscuit Designs)

Filed under: Coding,Computer Graphics — Diana Coman @ 6:09 pm

The 2020 end of year fractals come in frame shape and biscuit flavour – as far as I can tell, quite possibly as a payback for that time when I plainly sad I’ll have fully transparent windows rather than live with those horribly boring “artistic” borders that the legacy client came with. So now I’m making a full series of ornate borders essentially and at this rate, I can see it ending up with me *wanting* to add borders to windows too, for crying out loud. In any case, have a look at fractals on the border or otherwise biscuit design to render the chef insane with envy:

border_fractals_4_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_20.jpg
border_fractals_1_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_17.jpg
border_fractals_2_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_18.jpg
border_fractals_3_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_19.jpg

border_fractals_5_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_21.jpg
border_fractals_6_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_22.jpg
border_fractals_7_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_23.jpg
border_fractals_8_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_24.jpg
border_fractals_9_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4000_icount_10_minbail_50_p_25.jpg
border_fractals_10_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_17.jpg
border_fractals_11_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_18.jpg
border_fractals_12_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_19.jpg
border_fractals_13_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_20.jpg
border_fractals_14_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_21.jpg
border_fractals_15_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_22.jpg
border_fractals_16_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_23.jpg
border_fractals_17_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_24.jpg
border_fractals_18_palette1avg_curvature_allp_FALSE_uvAsFreeTerm_FALSE_seed_4001_icount_10_minbail_50_p_25.jpg

To obtain such ornate borders, I changed just one important thing in those high order complex polynomials of last time, essentially aiming at first to explore a bit the Julia set as well, since anyway, Monsieur Julia got less press than Mandelbrot: instead of iterating from the origin and using each point of the texture space as offset (ie as free term), this series iterates from each texture point directly and uses an MT-value (hence, seed-dependent) as offset. To keep it clean, tidy and ultra-regular as you might have noticed already, this series sticks also to the default definition of Julia-like fractals in that all polynomials are simply z^n + c (ie the coefficient of z^n is 1, the free term is c and all the other coefficients are 0).

On the very convenient side of this new series, it turns out that my previous choices of positioning in the complex space and even other parameters work perfectly well for this series too. As a result, I had only to add one single additional switch to my generator to get it to churn out (and fast, one great advantage of those series are that they are *very* fast, especially compared to the noise-based series, perhaps one day I’ll find the time to write about this, too) a whole pile of them – the images included above are just a selection. Moreover, the degree of the polynomial can vary a bit too around that same 20 value used otherwise – it’s this relatively high degree that gives the round shape and pattern, as noticed previously, but changing it slightly (+/- 5 at most) works too.

On the downside of this new series, the approach is essentially less stable than my previous one (and that’s why I went first with that rather than with this) – some seeds can make for lousy offsets that end up in some cases as just nothing at all (well, a plain, single colour, filled rectangle, arguably not exactly nothing at all but close enough). Perhaps this can be avoided by adjusting the interval for those offsets – currently I have no idea if there is an interval in which *all* values make for some sort of pattern at least. For the easy approach, I just went with what I had so that the offsets are picked in the interval -1.5 to 1.5 (there is some interplay with the rest of parameters, hence it’s not that surprising that those work for this series since they worked for the previous one, too). Anyways, if there will be further exploration of this series, perhaps this interval is one of the parameters to look at, too. Before that though, there are certainly quite a few *other* directions I’d rather explore…

And before you ask, otherwise, the above are just part of my still-growing list of stuff to write up, since – most naively – I tried to apply the end of year tidy up approach to fractal matters. In hindsight, I should have known better what will come out of “write-ups” at this time of the year – why, even more to write about than before doing the write-up, what else? 1 Oh well, there’s a whole new year ahead – one for ever more write-ups, why not!

Happy New Year!

  1. Also a ton of images, so that I finally realised that the stupid Image Viewer thing is so idiotically made as to *preload* all images in a directory before it shows anything – as a result, hanging mightily when confronted with the fresh output of my image generator. Oh well, long live feh I suppose, yet again.[]

December 22, 2020

My Colourfully Curvy Complex Space

Filed under: Coding,Computer Graphics — Diana Coman @ 4:08 pm

Getting to see the colourfully curvy parts of the complex space is a matter of degrees, positioning and technique – after all, the well-known 2nd degree polynomial can only get you round and round that same old mandelbrot island that turns forever and ad nauseam into itself. So, as a first step, just crank up your polynomial’s degree while keeping just the top coefficient to 1 and the rest to 0. Then watch the mandelbrot multiply – split and split again, forever content to retrace that shape even in multiples. Here’s how it looks, with black and white illustrations, why not:

curvyspace_10_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_5.jpg
curvyspace_11_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_6.jpg
curvyspace_12_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_7.jpg
curvyspace_13_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_8.jpg
curvyspace_14_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_9.jpg
curvyspace_7_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_10.jpg
curvyspace_8_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_11.jpg
curvyspace_9_graycoscolouriter_count_allp_FALSE_seed_3989_icount_40_minbail_50_p_12.jpg

When tired of all that perfect symmetry, whacking the coordinates one over the head with a well chosen function can do at least a bit of pleasing damage to the perfect mandelbrotian order but there’s little gain in such a cheap trick – basically you’re just looking at the same perfect symmetry only through a distorted lens, trying to pretend that if you marred your vision then the thing you’re looking at has therefore changed as well. Even lying to oneself has got to be at least more fun than such sad attempt. So let the coordinates alone and the vision undisturbed but inject instead some controlled chaos by using a mersenne twister (MT) as a generator of more interesting complex polynomials: simply set all coefficients of the polynomial to the sequence obtained from the MT – all of a sudden, there’s literally an infinity of polynomials of the same degree even 1 and the mandelbrotian order is left behind on the shores of piddly quadratic polynomials with boring 1 or 0 coefficients, while the space opens up and looks rather… empty perhaps:

curvyspace_19_graycoscolouriter_count_allp_TRUE_seed_2993_icount_40_minbail_50_p_3.jpg
curvyspace_20_graycoscolouriter_count_allp_TRUE_seed_2993_icount_40_minbail_50_p_4.jpg
curvyspace_21_graycoscolouriter_count_allp_TRUE_seed_2994_icount_40_minbail_50_p_3.jpg
curvyspace_22_graycoscolouriter_count_allp_TRUE_seed_2995_icount_40_minbail_50_p_3.jpg

The above apparent emptiness of the space is of course just a matter of positioning: while the complex space is infinite, some parts of it can turn out – when seen through some of those polynomials and especially when not iterated too much 2 – infinitely boring and so best avoided. On the brighter side though, for all the infinity of the space (boring or otherwise), one can always map any portion of it wherever desired, so that there is no need to keep fiddling forever with the positioning or (even worse!) end up adjusting the positioning to something else for each new function. So one area is fine enough but which area might that be? Well, there is some pleasing symmetry around the origin, not to mention the fact that I haven’t thrown out with the bath water the critical orbit too and that’s still around (0,0). So pick some space around the origin 3, adjust the zoom for more or less detail depending on whether you want basically small islands on the sea or something closer to mainland and fire up your pseudo-random number generators of the mersenne twister sort. Recall though that there was technique involved too if you are to get anywhere, so don’t despair just yet if it still doesn’t look all that curvy – or even interesting at all – when plotting just that old smoothed iteration count:

curvyspace_15_graycoscolouriter_count_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg
curvyspace_16_graycoscolouriter_count_allp_TRUE_seed_15111_icount_10_minbail_50_p_20.jpg
curvyspace_17_graycoscolouriter_count_allp_TRUE_seed_15112_icount_10_minbail_50_p_20.jpg
curvyspace_18_graycoscolouriter_count_allp_TRUE_seed_15113_icount_10_minbail_50_p_20.jpg

Having set as above the polynomial to use and the bit of space to look at, the last and by far more spectacular part is choosing what exactly to show of it and then how to colour-code it to produce the final image. Since I already had the average curvature colouring implemented, I gave that a spin, with the same trig-based grayscale formula for colour choice. Being an average curvature as opposed to a bland iteration count, it might be rather unsurprising that the result is quite curvy essentially – combined with the grayscale colour choice that curves and blends as well, one might perhaps find those white lines as not-bad mountain-range peaks sneaking their way around, on ever changing (if always rounded) directions of sorts:

curvyspace_1_graycoscolouravg_curvature_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg
curvyspace_2_graycoscolouravg_curvature_allp_TRUE_seed_15111_icount_10_minbail_50_p_20.jpg
curvyspace_3_graycoscolouravg_curvature_allp_TRUE_seed_15112_icount_10_minbail_50_p_20.jpg
curvyspace_4_graycoscolouravg_curvature_allp_TRUE_seed_15113_icount_10_minbail_50_p_20.jpg

The above samples are really just that – samples of an infinite series, since each MT sequence results in a different “landscape” even if one of the same overall type otherwise. Still, since I rather like those curves in there, I really wanted to see them coloured up beyond this black & white that is meant for heightmaps – after all, whether this type of images make good heightmaps or not, they might still make interesting textures perhaps, if nicely coloured in. So I tweaked my formula for the black and white colouring to expand it to some pleasing walk through the r,g,b space 4 and look what came out of it:

curvyspace_23_palette1avg_curvature_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg
curvyspace_24_palette1avg_curvature_allp_TRUE_seed_15111_icount_10_minbail_50_p_20.jpg
curvyspace_25_palette1avg_curvature_allp_TRUE_seed_15112_icount_10_minbail_50_p_20.jpg
curvyspace_26_palette1avg_curvature_allp_TRUE_seed_15113_icount_10_minbail_50_p_20.jpg

For completeness, I implemented as well two more averaging colouring techniques, namely the TIA (triangle inequality average) and the SA (stripes average). Neither of those seems to me very good for this exact series but they might come in handy for others – TIA seems very good at details (so here it ends up filigreeing the corners of the island when they get in sight at all), while SA does what the name says – stripes and more stripes, so perhaps if I ever make a series of stripy skins for NPCs, it will come into its own. For illustration purposes, here’s a sample of how they (don’t quite) work in this setup, first TIA (black and white, followed by colour) and then SA (black and white, then colour):

curvyspace_6_graycoscolouravg_tia_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg
curvyspace_28_palette1avg_tia_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg
curvyspace_5_graycoscolouravg_stripes_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg
curvyspace_27_palette1avg_stripes_allp_TRUE_seed_15110_icount_10_minbail_50_p_20.jpg

Given that I made myself this shiny new toy with colour schemes and complex polynomials on top of everything else, I itch of course to give it a spin with the old style textures too. The only trouble is that such spin is not yet quite available: there’s a bit more to implement in Ada first, some more play second and – last and at times even reluctantly on my list it would seem – some write ups to do as well, too. Basically there’s way more fun in playing with the toys I’m making for myself here than writing about them or even about what comes out of them! Still, I’ll catch up with the writing too, certainly – some day, if not today.

  1. In principle this degree could be a knob to play with just as well. In practice though – and much to my relief really – it turns out that it’s a knob best set once and then left the fuck alone: there seems to be a sweet spot at 20, at least for the current setup – increasing it any higher brings only very little detail on the very sides and hardly worth the trouble while otherwise increasing of course the required time to generate each image.[]
  2. There is some tension here – the more iterations performed, the more detail but that’s not always a very useful thing. First of all it costs in generation time but moreover, it can easily require also more complex colouring techniques to avoid noisy areas while otherwise bringing little of interest overall – too much detail ends up most often as just as much noise.[]
  3. Yet another one of those pleasing knobs of set-it-once-and-let-it-be variety: it’s set so far to -0.8, 0.8 on both axes.[]
  4. In this case the colour scheme itself is fixed ie it doesn’t change with the MT seed. As everything is in fact rather regular with this approach, messing about with the parameters in the colour formula tends to just tint the whole and with a poor effect in general. There are other cases where the whole colour scheme can indeed automatically adapt too, basically making the seed a generator for both pattern and colours but so far I haven’t found a way to make that work well for complex polynomials in general and this series in particular. In truth, I haven’t really got to try at all and make it, as I was just playing around with everything else. []

December 18, 2020

Colour Is Not What Colouring Is All About

Filed under: Coding,Computer Graphics — Diana Coman @ 6:51 pm

My prototype graphics generator has been merrily running on the test server for the past weeks, creating not only the cutest and silliest NPCs I have ever seen but also no end of harsh testing situations for the client-server communications part to expose various potential troubles. As a result, I enjoy the balanced situation where I can either take a break from communications to advance the graphics or take a break from graphics to advance the communications! This is – as you guessed already – the part where I kick the graphics out in the field again.

The aim this time is to find a working way to generate all those heightmaps that an infinite world requires. As a prerequisite and logical move at the moment anyway, the first step was to start building up a production as opposed to prototype graphics generator – while awk and the rest are excellent for prototyping, they are not really up to production standards. So I took first a few days to implement this time in Ada a png writer to start with and then the image generators that I had explored earlier with the awk and C code. While the naive view on this is that “she duplicated the effort having to reimplement now the same thing”, the reality is of course quite the opposite of naivety: having previously explored so much with the quick-prototyping in awk, I knew now both the problems and the approach well enough to design a much more useful structure to start building on. And while it might still happen that bits and pieces will change and have to be refactored and rewritten (as it always happens when truly exploring the unknown), the checks and precision required by Ada actually help with this: it’s way, way easier even to refactor bits and parts when everything is well defined and otherwise never failing silently.

In addition to the above, there was further speed gained also through the fact that Ada comes with very good support for all operations with complex numbers and in general with real numbers – the requirement to actually specify the desired precision is already just great. Moreover, the generics mechanism turns out to be a very convenient way to write packages that can be used as building blocks, to be combined as desired, even programmatically – this is by far the most effective way I found to deal with the sea of parameters that fractal texture generation throws at me otherwise. Anyways, in short, as a result on the code side of those past few days of re-focusing on graphics, I have now a set of generic packages and the tiny bit of glue required to mix them up for various exploration. To start with and for the most basics of checking that everything is working, here’s the familiar shape of the Mandelbrot fractal, in plain gray and all done in Ada, png-writing included 1:

The next break I took was the one in which I read the part that I had previously avoided – colouring approaches. This turned out to be in the end quite a useful thing – I finally found a published text 2 looking at the Mathematics rather than the pretty-pictures-and-futzing-with-parameters-otherwise of this colouring of fractals business, so it took me one day with pen in hand to go through it all but at least I have something to show for the time thus spent! The “smooth” part in there was especially interesting to me, since my terrain-generation goal rather requires some smooth transition between shades of gray – at least if one aims for some reasonable transition from holes in the ground to mountains and everything in between. At any rate, having read that, I realised that the “colouring” name is even misleading – it’s not as much about colours, as it is about choosing the information to represent and the way to pack its representation into a single value, preferably through a function that is continuous and has a continuous derivative as well, over the whole domain of interest. Once all that is done, the actual colouring is a separate step really – one can map the values obtained to any colour palette and therefore paint it all as desired. As usual though, it’s trickier to choose correctly *what* to show and *how* to show it than to pick a bunch of pretty rather than ugly colours! Still, there are known functions for the picking of the pretty, too, and I even implemented a generic palette too, but that will have to wait its turn in the writing queue since this is getting already both long and convoluted so better to not add colours to the mix as well just now.

Given the happy realisation above that colouring is pointedely not about colours at all, I went ahead and implemented one of the fundamental approaches. The core of it is that the information picked for display is an average of the values obtained at each point rather than the counting of the number of iterations themselves 3. This average is smoothed mainly by means of spline interpolation so that effectively there are several moving averages calculated and then combined to produce a final value.

The most interesting part of the above method is that it opens up perhaps a whole areas to explore, since it is but one specific case – the underlying idea seems to me to aim to look at each iteration essentially through a statistical lens instead of focusing so narrowly on only one overall measure at the end of the iteration. I don’t yet know whether the average is indeed the best statistic that can be found for this purpose but since it seems at least slightly more interesting than the plain (or even smoothed) iteration count, I went ahead and gave it a spin. Note also that the actual result further depends on other parameters, such as the maximum number of iterations (to some extent) or the exact interpolation and smoothing techniques applied – for one clue in the images, the pin-point effects are basically discontinuities. It’s also probably not at all surprising that an essentially statistical approach works better – or at least provides more detail – with more rather than with less data. More data in this case means a larger bailout value as well as a higher number of maximum iterations allowed. To illustrate all this, here’s the very same basic Mandelbrot fractal coloured still in grayscale 4 but showing the smoothed iteration count in the first image and the smoothed average curvature for 20, 50 and 100 iterations respectively in the following 3 images:



Armed as above with two working smooth colouring schemes and the generic building block of complex functions, the next logical step is to explore a bit functions other than the good old Mandelbrot. But since I’m running out of writing time right now, I’ll leave the write-up of that exploration for the next article – this one is running long enough as it is and I didn’t even get to mixing in any pseudo-randomness at all to spice things up!

  1. Surprisingly or perhaps not all that surprisingly, it’s really this png-writing part that was a chore to implement. Supposedly png is actually one of the clearer standards out there and moreover, I implemented the bare minimum here but nevertheless, there’s no joy I can find in the job of getting all headers just right and in the correct place and then chunking everything as expected and still having to hunt some tiny detail that just throws everything off at times. Anyways, at least once done it stays done and I guess it will even seem a breeze about the 10th time I implement it or something.[]
  2. Harkonen, J., On Smooth Fractal Colouring Techniques, MSc Thesis, Department of Mathematics, Abo Akademi University, Turku, 2007[]
  3. For a quick reminder here: the fractals are obtained through the iteration of complex polynomials; each point of the image is mapped to a complex number that is then used typically as the free term (ie coefficient of z^0) of a chosen complex polynomial; the polynomial is then iterated starting with (0,0) until either a maximum number of iterations or a bailout value are reached; when the bailout value is reached, the point is considered to have escaped the attractor of the function, basically converging towards infinity rather than remaining trapped in a radius of bailout size around the origin; the simplest representations pick then at each point the number of iterations performed and then map this to some colour scheme (sometimes pre-processing it first to ensure continuity). The averaging method aims instead to use more of the available information: it calculates the average of some characteristic (such as magnitude or argument) of all the intermediate values obtained when iterating at each point.[]
  4. Well, the grayscale is the result of applying a function too but I’ll skip those details for now.[]

December 9, 2020

A Double Take on Mersenne Twister in Ada

Filed under: Coding — Diana Coman @ 11:14 am

Turning to my own blog these days as a faster way to find my own previous code is perhaps worrying in a sense 1 but it’s also absolutely working. Yet another one of those “unexpected” ways in which past work pays now and current work pays later but all the more so for accumulated dividends! So here I am taking the time to write up and publish my code, mainly so that *next* time when I end up looking for it, I can find it straight away and with context too, such a wonder.

The code in question is the Ada implementation of the Mersenne Twister pseudo-random number generator (MT prng). I already had implemented MT in Ada and even packed it for easy use as a standalone library, but I published it only as a patch on a different v-tree, since my need for it at the time was simply as part of my testing code for a UDP library. Meanwhile though and quite as usual, I have found of course a lot of *other* uses for it, especially for computer graphics generation. And those uses come with their own context that turns out – again, as usual – to have some specific requirements, of which two are most significant:

  1. As I am moving away from the exploratory stage in which awk combined easiest with the reference C implementation and worked great otherwise *for prototyping*, I really want Ada code rather than C, CPP or anything else.
  2. It’s not enough to have just one prng sequence at any given time, since there can and indeed will be in principle any number of graphics artefacts generated in parallel.

For the first point above, simply plucking my previous MT lib out of the tester’s vtree would be quite enough. So as a first step I did that anyway, since a prng is not all that related otherwise with UDP communication or its testing and I’d rather have it therefore as a separate v-tree with its own genesis, neatly on my Reference Code Shelf and linked here as well for easy access:

The second requirement of being able to run in parallel any number of MT prng sequences imposes a more significant change to the implementation approach, because MT has an internal state and the reference implementation (that my Ada code above follows otherwise) is essentially sequential: at any given time, one can either reset the state by changing the seed or request the next number in the current sequence but there is no direct way to keep track of several sequences at the same time. Depending on your background, you may reach perhaps as an easy solution for this to either some sort of object encapsulation (basically the OO – Object Oriented – approach) or threads/tasks (essentially parallelization – spawning a new thread for each sequence). Both solutions seem to me rather unnecessarily complex though. There isn’t much need for a “MT object” as such, especially if otherwise the application doesn’t yet suffer from being Object Oriented (and mine doesn’t, nor do I wish it to start on that path). At the same time, there isn’t much need for separate threads (with their corresponding overhead, too) either: the MT algorithm itself is not resource intensive and otherwise the caller(s) in my case have to wait for the prng value anyway, there isn’t anything worth parallelizing at that level.

As usual, Ada provides an option – generics – that fits those requirements better than either OO or threads and has the added advantage of simply making impossible that ugly case when the prng is not initialized (i.e. when a number is requested before a seed is given). Since what I need is simply a way to have any number of different sequences (hence, different seeds) available and ready to question sequentially at any time, I simply changed the MT package to require the seed as a parameter and initialize the sequence directly in its body (hence, the code is run as soon as the package is instantiated aka given a specific seed and before any call to any of its functions or procedures can be executed).

The Ada approach of using a generic package as described above reflects quite accurately 2 the fact that MT as such is just an algorithm (hence, a generic package since that’s exactly what generic stands for – the algorithm), while an actual prng based on MT can only be obtained when a specific seed is given (hence, when the generic package is instantiated with a specific value for its seed parameter). Once MT becomes a generic package, using any number of MT prngs is as simple as writing “package MT_123 is new MT(123)” and going with the MT_123 afterwards, without any concern about “have to initialize before using” (since it IS already initialized, as soon as the seed is specified). And since every new sequence is essentially a new package, there is no trouble with the internal state either – each has its own and doesn’t have anything to do with any of the others.

The corresponding code for the above is packed as a v-tree of its own 3, the mt_generic lib on my Reference Code Shelf and linked here, as usual:

  1. The easy conclusion to jump to on this would be that “her non-published code repositories and archives are a mess”. Jump that way if you are so inclined, what’s it to me? When you’re dizzy enough from all that jumping on the first thing that seems like a thought at all in your head, consider for instance that it might simply be the size, number, variety and even age (in other words history and more specifically preserved history) of accumulated code that has something to do with it, too. My blog may be relatively old enough to have accumulated things too but first of all the very act of writing something up for publishing includes both filtering and basically indexing for easier later finding, what else IS publishing if not this, after all?[]
  2. This by the way is the precise sort of thing that makes Ada such a great language to work with, from my point of view: it provides the matching abstractions, allowing one to implement precisely what they mean rather than having to make do with some vague approximation and then going nuts trying to keep in check all the various fuzzy edges where the whole thing fails. Admittedly, some take the path of just ignoring those fuzzy edges and so they find Ada “hard” precisely because it makes such ignorance difficult and otherwise they find assorted other languages “easier” for not forcing them to pay attention to what they don’t want to pay attention to – until the whole thing fails, of course but that is just… how things are, right?[]
  3. Arguably it could just as well be a branch on the MT vtree as such but I can’t say I found a compelling argument for basically forcing one to have two vpatches instead of one here. I can see the argument of “it’s a refinement of MT for a specific type of use” so perhaps there is something to it but at the moment at least my answer to that is that branching basically immediately after genesis seems to me not all that different from just making two trees to start with. I’m still in two minds about this though, so let me know in the comments if you have some compelling arguments for either case.[]

November 26, 2020

Since When Is the Sphinx Small and Simple?

Filed under: Coding,Open Sores — Diana Coman @ 5:44 pm

As part of recent refactorings of code in Euloran lands, I took a short break to reconsider as well the testing infrastructure such as it is (read: minimalistic in the extreme) and the whole ever-growing pile of tests for Ada code on both client and serverside 1. At which point I realised that I have never done any write up of anything related to existing support for automated Ada tests and as a result I don’t even recall exactly just *what* put me off last time from using any of the supposedly available “testing frameworks” and the like – because yes, I am aware they exist and yes again, I have looked at them before but having failed to document it, the work done then needs at least a partial re-doing now. On the bright side, a fresh look at what is out there never really hurt anything – and in this particular case, it turns out as well that… things haven’t changed that much really in the meanwhile or rather they haven’t changed ~at all!

While I searched around yet again just in case there might be something new and useful just waiting to be discovered 2, the situation seems to be quite exactly as I recall it: there is one single open source unit testing library, Ahven, that claims to be simple, small and useful on its own, alongside a bunch of proprietary tools (e.g. GNATTest from Adacore or VectorCAST from Vector – previously known/written about as AdaCAST) that eerily bring to mind the spittoon 3 of “it’s all in one strand” fame, given their insistence on saddling the user thus caught with a whole additional environment that the vendor currently sells. But never mind that and silly me, of course such saddling of the caught user is not at all and under any circumstances what really happens, no, most emphatically NO! The actual true and real reality must be that those tools and their vendors simply and purely help and empower the user – you – each and every step of the way! Yes, exactly so, those huge tools simply have no choice but to pull in their own large environment just to offer you the great solution of solving the automated testing problem that you started with by importing a brand new set of other problems that are however the “problems that everybody has” and therefore come (for an additional but ongoing price) with known solutions, too! Be that as it may, since I somehow never quite have the same problems that everybody has, I’ll pass on those great offers of help and empowerment by means of giving up control over my own development environment and look therefore in more detail only at the other single option left: Ahven.

At first glance, Ahven would seem to take the right approach and thus be for once useful, perhaps: it’s supposedly small and simple, following some well-known and usual formats for unit testing, what could possibly be a problem with it, right? Well, for starters, merely trying to get the full documentation to show triggers the weirdest of unexpected WTFs: the documentation needs “compiling” but moreover, it *requires* something called Sphinx. A look as to what the Sphinx might be doing all of a sudden in Ada testing frameworks reveals that the mythical creature stands among the open sores tribes for a text search server with “a variety of text processing features” and SQL support and what-not. Do you still recall that initial claim of Ahven’s of being small and simple – is that so small and simple that you need a whole text search server for its documentation? Or is it so small and simple that it forces on to your system a full text search server only for the purpose of displaying a bunch of text files in some readable format? Which of those is exactly your small and simple because neither quite fits into my definition of either small or simple. I suppose I might have gotten it all wrong and it’s not small *and* simple but rather in some parts small and in other parts simple, except the small is never simple and the simple is never small – is this perhaps it?

Leaving though the Sphinx aside and keeping it still out of my systems, I am nothing if not truly stubborn and so I just read the docs as they were, as annoying as reading “source” of plain text turns out to be, on the off chance that the code itself is perhaps the promised small and simple. It turns out that the small comes in at about 4.5k lines of code (the docs claim 3k but by wc -l disagrees) and the simple includes a lot of support for all sorts that I never intend to have anywhere near my development environment ever again – windows and junit and xml formats included. Moreover, there are all the possible software patterns one might want in there – whether the problem solved truly requires or justifies the additional complexity of implementing those patterns is never a question or never answered apparently with “no”. At which point I realise that I’m probably even lacking enough common ground with the code’s author to be able to meaningfully discuss why using this framework would be no asset but a liability to me: their focus is on compatibility with all sorts of tools, environments and anything else, while my focus is on having the smallest and most effective way of structuring and running some automated tests. Basically it strikes me that the whole of “small and simple” is literally a matter of having advanced less (for lack of resources, not for lack of want) on the *same road* as those proprietary frameworks and not in the slightest a matter of traveling on a different road entirely. After all, what different road can there even *be*, right?

Just in case that the above is just my adverse reaction to a heavy dose of software patterns in the morning, I read through Ahven’s own tests as well, as a reasonable example of a relatively significant set of tests. I ran them too and I got precisely the sort of output that my 115 lines of code (that’s my own “framework” – a single Ada package) spit out just the same. The only part I could add (but I didn’t yet need) is a timing of each test – as it’s really not something I need for *every* test, I left it for now up to individual tests to time the code they run, where relevant.

Overall, I suppose it may very well be that my code base is just not yet big enough to justify anything more complex than my tiny “testing framework” that somehow manages to report test results uniformely and even grouped neatly where desired. This may change indeed and so my 115 lines of code supporting test writing and running may very well grow gradually too, as required. For what it’s worth, I don’t even necessarily rule out the introduction of some patterns in there at some point if and when there is some benefit to it other than ticking some boxes that it follows best practices or it’s “as it should be” or whatever else of this sort. The trouble is that those 115 lines of code support already 8k lines of tests and if it is to grow to 4.5k, I expect it to do way, way more than just add timings for every test too! As the whole code base stands currently, I rather suspect that I’ll trim down the non-testing code some more before even considering any expansion of the test-support into thousands and thousands of lines of code. Then again, I keep not having those same problems that everybody has – somehow!

  1. For the curious, there are currently about 4k loc of tests on each side (client and server), so about 8k total. And no, they are not mostly duplicates of one another because even the “common protocol part” is truly common only at the very basic level of packing/unpacking of messages really – as soon as one moves even a tiny bit higher up, the requirements of server vs client are so different as to pull the design and implementation of the solution into significantly different directions.[]
  2. I’m ever the optimist and no cure has worked so far, despite plenty attempts.[]
  3. Archived.[]

November 8, 2020

Readings from a Blog of 1852

Filed under: Word Therapy — Diana Coman @ 1:37 pm

Relieved of any significant hope or expectation (previously self-imposed as a sort of regular exercise, it must be said) of finding any time soon solid quality or much of import in the “new” or even merely the contemporary, I have regained therefore all the more time to further explore the treasure trove of things that not only stood the test of time but withstood it, too! Among those, exploring the explorers of the past has been an absolute pleasure, perhaps in no small part due to simply how wonderfully alive they come across, especially when set against the modern background of stasis and paralyzing fears for which no amount of “safety” seems to be ever enough, no matter how restrictive otherwise. By contrast, less than 200 years ago, there seem to have been still plenty of people for whom the very opposite of “safe” aka fight itself as well as the unknown (with all its potential dangers and total disdain for baked-in safety) stood simply for a welcome and even at times specifically sought after challenge. Quoth Sir Richard Francis Burton:


While at Washington I had resolved – as has already been intimated – when the reports of war in the West were waxing loud, to enjoy a little Indian fighting. The meritorious intention – for which the severest “wig,” concluding with something personally offensive about volunteering in general, would have been its sole result in the “fast-anchored isle” – was most curteously received by the Hon. John B. Floyd, Secretary of War […].

Such striking contrasts as the above are made even more striking when one notices at the same time the similarities, too – for all the “different times”, then as now and probably as ever, there’s always plenty of public and “official” opinion to loudly if baselessly oppose the intrepid and the extraordinary, mainly on the grounds that they are … “too extreme”, in other words too much to handle. Then as now and most satisfying to read, indeed, the extraordinary have a few choice words to say in reply to such “opinions” too, quoth Sir Burton yet again 1:


The greatest difficulty a raw writer on Indian subjects has to contend with, is a proper comprehension of the ignorance crasse which besets the mind of the homereader and his oracle the critic.[…]

Then as now, ignorance never stopped – quite on the contrary – the afflicted from giving plenty of “advice” to the one talking from his own experience. Then as now, anonymous readers formed “their own opinions” through the convenient means of following whatever agreed-upon oracle of the day – one variety or another of the bakers of the intelligentsia, essentially – rather than any inconvenient thought process of their own. I wouldn’t even venture to suppose that there was at any point in time any less time spent on voicing both such advice and such opinions – at most I’d cherish perhaps the hope that there was (as a result of repeated and ever ready to re-repeat itself experience, nothing else) less expectation of the world paying much attention otherwise to each individual utterance of the collective consensus.

Other than that and despite the usual illusions at the time of the events itself, it’s still the case that nobody remembers any of those readers and critics anymore, nor does anyone care at all to remember them. All the importance that those anonymous readers and critics may enjoy still comes from the reply that Sir Burton gave them and nothing more. I don’t even care to look up what nonsense they spouted precisely but I thoroughly enjoyed the rare autobiographical fragment that makes up the response and so I’ll quote here some more from it, with my own comments on bits and parts that caught my eye even more than the whole:


Now, waiving with all due modesty the unmerited compliment of “good boy,” so gracefully tendered to me, I proceed to the judgment which follows it, my imminent peril of “extreme opinions.” If there be any value in the “additional evidence” I have “brought forward on important questions,” the reader may, perchance, be curious to know how that evidence was collected 2. So without further apology 3, I plunge into the subject.


After some years of careful training for the church in the north and south of France, Florence, Naples and the University of Pisa, I found myself one day walking the High Street, Oxford, with all the emotions which a Parisian exquisite of the first water would experience on awaking – at 3 P.M. – in “Dandakaran’s tangled wood.” 4


To be brief, my “college career” was highly unsatisfactory. I began a “reading man,” worked regularly twelve hours a day, failed in everything – chiefly, I flattered myself, because Latin hexameters and Greek iambics had not entered into the list of my studies, – threw up the classics, and returned to old habits of fencing, boxing, and single-stick, handling the “ribbons,” squiring dames, and sketching facetiously, though not wisely, the reverend features and figures of certain half-reformed monks, calling themselves “fellows.” My reading also ran into bad courses, – Erpenius 5, Zadkiel 6, Falconry 7, Cornelius Agrippa 8, and the Art of Pluck 9.


At last the Affghan war broke out. After begging the paternal authority in vain for the Austrian service, the Swiss guards at Naples, and even the Legion etrangere, I determined to leave Oxford, coute qui coute 10, – The testy old lady, Alma Mater, was easily persuaded to consign, for a time, to “country nursing” the froward 11 brat who showed not a whit of filial regard for her. So, after two years, I left Trinity without a “little go” in a high dog-cart, – a companion in misfortune too-tooing lustily through a “yard of tin,” as the dons stared up from their game of bowls to witness the departure of the forbidden vehicle. Thus having thoroughly established the fact that I was fit for nothing but to be “shot at for sixpence a day,” and as those Affghans (how I blessed their name!) had cut gaps in many a regiment, the “relieving officer” thought proper to provide me with a commmission in the Indian army, and to start me as quickly as feasible for the “land of the sun.” 12[…]


So, after the first year 13, when I had Persian at my fingers’ ends, sufficient Arabic to read, write, and converse fluently, and a superficial knowledge of that dialect of Punjaubee which is spoken in the wilder parts of the province, I began the systematic study of the Scindian people, their manners and their tongue.


The first difficulty was to pass for an Oriental, and this was necessary as it was difficult 14. The European official in India seldom, if ever sees anything in its real light 15, so dense is the veil which the fearfulness, the duplicity, the prejudice and the superstitions of the natives hang before his eyes 16. And the white man lives a life so distinct from the black 17, that hundreds of the former serve through what they call their “term of exile,” without once being present at a circumcision feast, a wedding, or a funeral 18. More especially the present generation, whom the habit and the means of taking furloughs, the increased facility of enjoying ladies’ society 19, and, if truth be spoken, a greater regard for appearances 20 if not a stricter code of morality, estrange from their dusky fellow subjects every day and day the more. After trying several characters, the easiest to be assumed was, I found, that of a half Arab, half Iranian, such as may be met with in thousands along the northern shore of the Persian Gulf. The Scindians would have detected in a moment the difference between my articulation and their own, had I attempted to speak their vernacular dialect, but they attributed the accent to my strange country, as naturally as a home-bred Englishman would account for the bad pronunciation of a foreigner calling himself partly Spanish, partly Portuguese. Besides, I knew the countries along the Gulf by heart from books, I had a fair knowledge the of Shieh form of worship prevalent in Persia, and my poor Moonshee was generally at hand to support me in times of difficulty, so that the danger of being detected, – even by a “real Simon Pure,” – was a very inconsiderable one 21.


With hair falling upon his shoulders, a long beard, face and hands, arms and feet, stained with a thin coat of henna, Mirza Abdullah of Bushire – your humble servant, gentle reader – set out upon many and many a trip. He was a Bazzaz, a vender of fine linen, calicoes and muslins; – such chapmen are sometimes admitted to display their wares even in the sacred harem by “fast” and fashionable dames 22; – and he had a little pack of bijouterie and virtu reserved for emergencies. It was only, however, when absolutely necessary that he displayed his stock-in-trade; generally, he contented himself alluding to it on all possible occasions, boasting largely of his traffic, and asking a thousand questions concerning the state of the market. Thus he could walk into most men’s houses quite without ceremony; – even if the master dreamed of kicking him out, the mistress was sure to oppose such measure with might and main. He secured numberless invitations, was proposed to by several papas, and won, or had to think he won, a few hearts; for he came as a rich man and he stayed with dignity, and he departed exacting all the honours. When wending his ways he usually urged a return of visit in the morning, but he was seldom to be found at the caravanserai he specified – was Mirza Abdullah the Bushiri 23. […]


Thus it was I formed my estimate of the native character.I am as ready to reform it when a man of more extensive experience and greater knowledge of the subject will kindly show me how far it transgresses the well-established limits of moderation. As yet I hold, by way of general rule, that the Eastern mind – I talk of nations known to me by personal experience – is always in extremes; that it ignores what is meant by “golden mean,” and that it delights to range in flights limited only by the ne plus ultra of Nature herself. Under which conviction I am open to correction.

As far as I know, there hasn’t been any correction – only the usual louder and more diverse complaints, especially from those knowing least about the subject, as it tends to happen apparently in all times and all places.

  1. In his postscript to “Falconry in the Valley of the Indus”[]
  2. I certainly was curious, indeed.[]
  3. Yes, he literally prefaced this fragment with what amounts to an apology for having to go into biographical details and no, it’s not just for show, I don’t think so. He just doesn’t think anyone all that interested in his biography simply because from his point of view, the personal is by default (ie unless otherwise relevant to support/refute a point of wider interest) NOT interesting to anyone other than the person in question. Quite refreshingly sane perspective, too.[]
  4. While I couldn’t find the exact quote word by word, there’s a lot of Ramayana happening precisely in the “tangled wood” of Dandakaran/Damdakaran/Dandakaranya/Dandak forest. For instance, here’s a fragment from Book III, in Ralph T.H. Griffith’s translation (since I sadly can’t read the original):

    Ha, short lived wretches, ye who dare,
    In hermit dress with matted hair,
    Armed each with arrows, sword, and bow,
    Through Dandak's pathless wood to go:
    How with one dame, I bid you tell,
    Can you among ascetics dwell?
    Who are ye, sinners, who despise
    The right, in holy men's disguise?
    The great Viradha, day by day
    Through this deep-tangled wood I stray,
    And ever, armed with trusty steel,
    I seize a saint to make my meal.
    

    []

  5. I assume he means Thomas von Erpe, a Dutch linguist, owner of a printing press and otherwise pretty much the reference across Europe for all matters regarding Arabic – his own Arabic grammar book became “the” textbook and otherwise his collection of Arabic manuscripts formed the basis of the university library at Cambridge. He died in 1624 from the plague.[]
  6. I suppose he means most likely Richard James Morrison, who wrote indeed under the pen name of Zadkiel (even Zadkiel Tao-Sze), supposedly on astrology and astronomy. He seems to me more of a trolling character than anything – e.g. his “The Royal Book of Fate: Queen Elizabeth’s Oracle of Future Events, from an illuminated manuscript, found in the library of the unfortunate Earl of Essex”.[]
  7. While I have no idea what was available on the topic at the time, it’s clear from Burton’s own detailed description of the topic in his later writings that he knew the practice – both training and use of the birds – very well indeed. So whatever he read, it seems it turned out to be of some use, at least.[]
  8. I assume he means Heinrich Cornelius Agrippa von Nettesheim, author of De occulta philosophia and quite the character, too.[]
  9. This book is a riot to read, too. Basically he read all the cool (and as irreverent as possible) stuff he could find as well as all the interesting people (dead or alive) that he could hear of and otherwise ignored entirely the “official” reading list as well as the officially appointed “interesting people.” Anyways, to keep this footnote from expanding into a full blown article just yet, I take it he means “The Art of Pluck. Being a Treatise after the Fashion of Aristotle; writ for the use of students in the universities. to which is added FRAGMENTS FROM THE EXAMINATION PAPERS. by Scriblerus Redivivus” – more prosaically though, by Edward Caswall. []
  10. The lack of accents in the French words is entirely my fault here as I keep to the ASCII set of characters. Sir Burton wrote in perfect French, all accents included, of course.[]
  11. Yes, it’s froward, NOT forward![]
  12. His quotes are all the more meaningful if one read already his descriptions of that land with its sun and especially everything else, too![]
  13. On the one hand, look at the natural and unconcerned assumption that doing things takes time indeed – “first year”, as simply as that. On the other hand, look also at the list that follows and tell me truthfully just how many of your own years does one of his turns out to stand for.[]
  14. If you’re looking for the part where he starts explaining how it is therefore *impossible*, it can’t be done, it won’t work and so on, then you’ll be sorely disappointed.[]
  15. I suspect this is part and parcel of what being an “official” consists in, it’s basically the very substance of officialness – not ever seeing anything in its real light.[]
  16. Eh, I think he just got to know the Indians way better than he ever got to know the Brits actually and has otherwise different illusions on that end of the equation, that’s all.[]
  17. Presumably this means “Indians” here.[]
  18. Hah, they were basically tourists, of that peculiar sort that keep at all times only to carefully controlled & approved surroundings – can’t go just anywhere, what if they might actually, for real, find something new, oh no! – throughout the whole duration of their all-inclusive “volunteering holiday/gap year/organised tour” with that predecessor of both charities and travel agencies, the army! Apparently even good travelers are and have always been rare.[]
  19. At least they enjoyed it rather than feared it, or so it seems to Sir Burton and mind that it’s unclear whether he ever suspected he might have needed a way stronger disguise at home than he ever did abroad.[]
  20. This ever increased until it took over entirely – at times it certainly seems that there’s not much left other than appearances anyway.[]
  21. Do you realise he lacked any charts, posters, rules and regulations and even any government approved guidance and statistics to support this? It’s all by his *own* evaluation and at his own peril too, as incredible as that might sound nowadays![]
  22. Do you see now what I mean regarding his vs his compatriots’ ability to enjoy women’s society? Sure, it can be argued that ladies’ society was not quite the same as that of women – fwiw though, he set apart in clear as entirely unenjoyable only the company of some very specific type of “ladies” he met in America, if that’s any help.[]
  23. Funnily enough, Sir Burton is otherwise mostly known for his translation of the Arabian Nights. He could have clearly written the Arabian Days and I rather wish he did, too.[]

October 31, 2020

The Lushdrizzler Way

Filed under: Dark Modern Ages — Diana Coman @ 9:04 am

As yet another year of mine is almost over and I take stock of that part of it that consists mostly in a relentless cutting of various tangles, draining of swamps, making of interfaces and bringing back to life forgotten dragon bones of the most potent kind, it occurs to me that the very same cleanliness, clarity and productivity that I obtained as a result of all this work of mine can very well mean also utter devastation and total disturbationnce for the two-cents invested young’uns 1 not quite ready to take the scary step of playing the game but certainly ready to futz inconsequently at the door while never daring to open it up at all 2 for fear of a less-than-optimal (thus not good enough for them!!) opening that might ruin their chances, their future, their success their possibilities and impossibilities even, otherwise and putting it all together plainly, their very impossible chances of a possible future success! Imagine Eulora’s 2.0 client from the perspective of the lushdrizzler come to futz importantly about it and notice his utter horror when the simple act of running the client 2.0 turns vicious on him as it directly plunges him into the game, his character all made and set, without any “choice” in the matter, without any door left to open, nor any stats left to study, nor looks to alter nor even a name choice to agonise over!

Does the above mean indeed that Lushdrizzler’s path has been closed forever leaving that many followers lost and forlorn? Could it possibly be indeed that Eulora 2.0 will be so open that one can’t even hesitate at the door anymore? If such prospect terrifies you, despair not young’un with two cents to spare for I am kindly disposed and so ready to point you in the direction that your heart desires: it may not be your character’s stats, it is true but it’s even better than that for it’s the whole game’s own…configuration file! And it’s all on your own hard-drive so you can indeed utilize your mighty Excel powers on it until you’re sure (but do be sure-sure not merely sure!) it’s absolutely optimally configured for your best advantage. It gets even better than this, since I can even point you directly to the most important part of it all, seeing how it has to do with keys and encryption and security – look at all those important words and tell me sincerely if they are not simply by themselves a total proof that it’s worth Excel-izing anything related to them for a few hundreds of hours at the very least!

If you wonder how a mere configuration file can be so excellently suited for your excel-lent efforts, consider this: communications between client and server are encrypted using Serpent keys that are stored in a circular buffer; those keys would need of course to be changed from time to time, since otherwise it becomes increasingly possible for an attacker to collect enough information to start decrypting messages, too; to allow therefore updating of keys, the client needs to maintain its circular buffer in sync with the server’s corresponding buffer. While the client can send to the server new keys at any time, the communication protocol states that any keys received are set in the buffer on available positions considered in order – so if the server misses for instance one message from the client, its own “next available positions” may suddenly be different from those on the client side. Given that keys are afterwards identified in client-server communications solely by their position in the circular buffer, it follows that any time your client’s buffer becomes out of sync with the one on the server, the immediately following communications may fail since the server will use a different key than expected – not as much for not having the correct key as for having it simply on a different position. In such case, the best bet from client’s perspective is simply to discard the mismatched key (position) and pick another – but note that there is no guarantee that another pick is in sync, either!

Basically any change of key comes with a risk of discovering a mismatch and thus missing as a result as many communications from the server as it takes until the blessed state of sync is achieved yet again, at least partially for the selected ONE key (since anyway, there is no hard guarantee of any other keys matching beyond the one that is in use and …works). And now imagine that this sort of situation happens while your character is fighting all sorts of monsters – as a result of this unexpected sin of getting out of sync with the world essentially, your character becomes blind and dumb in the most direct sense, while the monsters being immune to such crypto-challenges as they are, will surely make short work of the blind and the dumb! Imagine this horror – your future greatness is already lost for lack of having set the relevant constants in your configuration file to their most auspicious values!

What relevant constants in what configuration file? The client’s very own .ini file, easy to find, easier still to change, comes with various constants and settings but for the above issue, the value that is most relevant stands for the maximum number of times you want to use the same key before discarding it. If you go for the golden standard of OTP 3, the inevitable consequence is that your client will change keys *very often* indeed! How often? Well, it depends on the situation really 4 but generally speaking the more crowded and animated the situation, the more you need to find out from the server and therefore the more messages your client receives so …the more often it will have to discard a key and pick a new one! Add to this the fact that if you discard the key after one single message, you run into the very likely situation where you *also* discard as a result any multiple-messages answer that the server might give you since there is no time to change the key in between the several messages that are just parts of the answer to one single question (and no, your client can’t even know in advance when such situation will happen or how many messages may constitute one single answer).

If the OTP is such a pain, you might say, fine, go with some big-enough-but-not-too-big number of uses! Sure, what exactly might that be though? If it’s any help, I can even give you some shiny numbers, not like there’s any lack of them as long as computers are involved: in the simplest of cases where your character is basically alone in a deserted world and for a fixed update interval of 10 seconds (ie the client asks the server for a world update every 10 seconds), using a key for a maximum of 8 times triggers a key change around every 15 seconds; setting the maximum uses to 16 increases that to about 21 seconds, then 32 maximum uses further increases it to about 50 seconds and at 64 maximum uses it manages to finally get slightly over 1 minute (at least at times…). Is that enough/too much/too little? Which of those shall it be and is that 10 seconds interval between requesting world updates even enough to give you that optimal configuration without which you surely can’t even try for the game for it would be just such a terrible loss of face and future fucks? No way to know other than excelizing it so go forth and good speed to you!

Then again, if you made it all the way here, you might even avoid the futzing and who knows, perhaps try at least to come up with a useful improvement to the client code itself so that it *adjusts* so well to various situations that there is indeed neither danger of key overuse nor of that most dangerous blindness and dumbness to the world around it – thus literally gaining an actual edge in the game. Mind though that such attempt requires at the very least some proper thinking and actual work rather than fashionable excelizing. Not to mention also that it certainly requires as the most basic prerequisite even playing first the game and talking to people to figure out what’s what and why and how

  1. Immature really, nothing to do with biological age as such.[]
  2. In the words of their best known avatar to date, Baldwin Lushdrizzle, this frantic activity in front of the door while avoiding at all costs the handling of any possible handle is called having “invested over 100 hours into the largely unexplored goal of understanding and utilizing the game’s stat system”. If you are following his path, might as well know his words for it, too, you know?[]
  3. One Time Password = as the name says, each key gets used only once and then it’s promptly discarded.[]
  4. It gets better/worse actually, since you get to also set how often the client should ask for an update on the world’s situation so that the actual value as to “how often does the key change” depends on that too![]

October 24, 2020

A Numerical Look at My Own Blog

Filed under: Sense and nonsense — Diana Coman @ 10:20 pm

From time to time, I review from various angles anything and everything, my work and habits included. As this blog made it through more than 10 years since the first articles that I wrote back in September 2009, I got recently quite curious as to what story its accumulated numbers might tell – and how far that story might turn out to be from the more forgiving picture that memory is bound to provide if left to be the sole narrator of things past.

With one quick query to the blog’s database, the numbers were easily produced 1, providing in a separate file a neat listing of each article’s date and time of publication as well as character count, word count and link count:

select date(post_date) as articleDate, time(post_date) as articleTime, post_title as articleTitle, length(post_content) as charCount, (length(post_content) – length(replace(post_content, ” “, “”) ) + 1) as wordCount, (length(post_content) – length(replace(post_content, “a href”, “”) ) ) / length(“a href”) as linkCount from wp_posts where post_status=”publish” and post_type=”post” into outfile ‘/tmp/blognumbers.txt’;

The file obtained with the above query 2 is quickly 3 loaded into R and then all charts and stats are a few commands away, ready to tell you whatever you want to know and quite a few things you’d rather… not know.

First of all though and as always with any data set whatsoever, there’s some cleanup to do: in this case, I discarded all the logs articles (both #eulora and #ossasepia) since they are a sort of special category on their own and I’d rather not have them mixed with the rest. As a result – and highlighting already my low blog-output otherwise- the dataset shrinks significantly: from the initial 2334 articles including logs, I’m left with only 636 articles.

For the 636 articles remaining, the summary stats are those:

Minimum 1st Quartile Median Mean 3rd Quartile Maximum
Word Count 15 354 611 1149 1077 15107
Link Count 0 1 2 4.55 5 238

The first thing said by the stats above is that my shortest article is 15 words long. That sounds rather surprising to me on first pass, so let’s look at what that wonder of an “article” might be, since it’s just a matter of one quick select in R: the shortest article is… this one aka literally the statement of the question “how do you go about finding out that which you don’t yet know you don’t know?” All I can say is that now I’d make that article even shorter – the title is all that matters really, but other than that, I’d say those few words (15 or less, as they might be) still make quite an article in this case indeed: while there’s a lot more that I could write in answer to that question, it’s still… the question that matters and quite a lot, at that. Not a bad thing to be reminded of, either, as an unexpected gain at number-questioning my own blog.

Moving on, the rest of the numbers say that half my articles are between 354 and 1077 words in length, which is no surprise. Moreover, the fact that the median article is 611 words long while the average article is 1149 words long is again quite as expected – there are some really long articles that pull that average up but it took me otherwise a long, long time (and way more effort than the blog itself shows) to get into the habit of expanding rather than forever contracting my writing until there would almost be nothing left to write at all. So I’d expect indeed that the length of articles is perhaps more consistently 1000+ words only over the past few years, but not earlier. It’s worth noting also that more words by themselves is just verbosity so more of a minus rather than a plus in itself but while I’m focusing on the numbers in this article, it does *not* mean that it’s only those numbers that I’m relying on when considering the increase in length of my articles as an improvement of my own writing rather than the opposite of that. At any rate, since I still write relatively few articles anyway, I expect it will take quite some time until this change towards writing consistently longer articles shows more marked in the overall summary.

The summary of links count as it stands doesn’t say perhaps all that much except that there is clearly some outlier(s) with a high count of links – as indeed there is, a review article of 200+ articles, linking therefore to each and every one of those. Nevertheless, taking out the outliers doesn’t change anything other than the maximum value itself (the 2nd highest is 63 links) so I’ll let it be as it stands.

The full graphs for those 636 articles can be plotted as well, to finally have some sort of pictures in this article, too:

blog_stats_2_640.jpg

blog_stats_1_640.jpg

Looking at the graphs above, 2018 seems to mark a clear change, with both word count and links more settled at a higher level than before. At least knowing my own history otherwise, the expected cvasi-break around 2013 is visible too – if anything, I’m almost surprised that it doesn’t look even worse than that, I’d have almost expected a nearly total flat-line there. Then again, it’s clearly the only place where such flat-line is actually visible on some intervals at all – if there was a point where the blog could have stopped, it’s there but it turns out it was indeed a temporary break rather than the sort of “temporary” that becomes permanent.

To see more clearly the woods rather than all those individual trees making the charts above, I calculated some aggregated values on yearly intervals as well – after all, why not do it if I already got all the data and all the powerful R just waiting to help. Plotting the number of articles per year removes all doubt at least – there was barely any writing in 2013 and 2014, indeed. The surprise comes at the peak in 2011 and perhaps not as much at it being then as at it being so much higher than anything else:

blog_stats_3_640.jpg

One single number though, no matter how chosen, barely gives at any time anything other than a quick but extremely, extremely narrow (focused, if you prefer) view of anything at all. To add to it a few more similarly narrow but at least differently angled views of it, here’s the median word count and link count of articles for each year:

blog_stats_4_640.jpg
blog_stats_5_640.jpg

While the overall clear upwards (if slow) trend is quite obvious to me and matching otherwise everything else 4, the peak in 2018 (or dip in 2019, if you prefer) seemed at first rather surprising to me – from my point of view otherwise, there isn’t/wasn’t anything all that special with either of the years involved. But then looking at the blog’s archives, it turns out that the peak in 2018 can be easily traced to … the EuCrypt work (that I didn’t otherwise assign mentally to 2018, at all, go figure!). So on one hand there is indeed an overall visible, if slow, improvement but on the other hand it’s also rather clear that I still write the most when some project quite requires it as such – not that I’m all that surprised at it or anything.

After those 1500+ words that I could write today quite easily 5 out of a few numbers that I obtained again without much trouble, I’d rather say it plainly also that I don’t hold those numbers to mean *by themselves* all that much: they are certainly very useful in their unflinching precision but that very same precision comes at the cost of narrowing the perspective so much as to make it almost a single point, effectively blinding the naive (or the fool, if you prefer, there aren’t really all that many different words to describe accurately the one who relies on “just the data”) to all the complexity that actually yields that specific point in that specific place. So don’t discard the numbers when they are honest measurements for they don’t lie but don’t expect of them more than they can offer, either: data points, even when aggregated or otherwise put through any intricate analysis are still just that, mere points, not by themselves models of the underlying reality.

  1. And then they threw me on to an entirely unexpected direction as I got to discover a silently broken article on the blog that I proceeded therefore to fix.[]
  2. To count the words, the query basically calculates the number of spaces as difference between the length of the article as it is and the length of the article without spaces and adds 1 to that. Counting the links is done in a similar manner, only taking away the length of the article without “a href” and dividing the result by the length of “a href” itself.[]
  3. Quickly enough at least: since mysql spit the values in tab-separated format and my titles contain all sorts including apostrophes and #, the read.table command of R needed some parameters (sep aka separator, quotes and comments) set to something other than the default values but R’s help is clear enough and always at hand so the whole thing really took 5 minutes.[]
  4. This part is more important than it seems – if you look long and hard enough, you *can* find *anything* in some data. Whether it also means something and moreover whether it means what you think is quite a different matter entirely.[]
  5. And this says way more and is more important than all the numbers in this piece taken together.[]

October 15, 2020

Sonofawitch, the GAWK Logbot

Filed under: Coding,V — Diana Coman @ 8:43 pm

Since active people nicely asked me for the code of my GAWK logbot, I took the time to genesis it, for whatever use they may have for it. As always, the only possible author of some code is its reader, not its writer, so don’t run “my” code, but read it and make it yours in whatever way suits your need and your environment (don’t expect it to just suit blindly anything and everything either because it most certainly won’t). The bot’s code is commented in enough detail to make its purpose quite clear so I won’t repeat any of it in this article but I’ll give instead some background on it, since this goes way beyond what fits or indeed belongs at all times in the code comments.

My prototype GAWK logbot code ran in my irc chan, #ossasepia, under the name of Sonofawitch, between April 2020 and the closing of the chan in September 2020. The more recent articles in the logs category are the fully automated output of this log code. The raw logs for #ossasepia and #eulora are dumps of the bot’s raw loglines database.

The code itself grew from the original 140 lines of code to 413 lines currently (including rather detailed comments), mainly because the bot’s use got cut short when I closed my chan, so that the bot basically ran out of time before it got to move out of the prototype stage. As a result, the current logbot code includes not only the logging of irc lines but also the trial (that turned out to work perfectly well) formatting and create/update of log-articles for real-time publication on a mp-wp powered blog. This piling of both functions in the logbot code was meant only as an initial easy way to test what I had never attempted before, namely to just create and update automatically and on the fly articles in a mp-wp database. There were for that matter some initial unexpected findings (iirc there was some flag that needed set for the publishing of a new article to happen) and some tweaks to make such as adding the change of day, so the testing itself was valuable as far as I’m concerned but it’s true that over its last couple of months the bot simply ran perfectly smoothly and without any trouble.

The next step was meant to be a full decoupling of logging from publishing: the latter is best handled perhaps directly through a MySQL trigger function so that the bot itself does not need to be concerned with that and can return both to its nearly-microscopic original size and its simpler focus on writing the raw lines as they come and citing lines from known URLs. Nevertheless, since my need for irc-logging turned out to be non-existent at this time after all, there was no reason to spend any further time on this and so the poor bot remained as it currently is, despite its perfect and long-enough functioning in the field otherwise.

The genesis .vpatch for the bot code and my sig for it are as usual on my Reference Code Shelf and linked here as well, for your convenience:

October 11, 2020

The Bugureaucracy

Filed under: Coding,Dark Modern Ages — Diana Coman @ 7:02 pm

Hot on the heels of having solved that gnarly compilation trouble, I ended up taking a walk through the byzantine labyrinth of bugs that may – or may not! – cause libmysqlclient 1 to be effectively single-connection, whatever other claims and pretense may be put forward anywhere – and yes, I know that such claims are made and such pretense is and will be hotly supported. Nevertheless, the fact that libmysqlclient’s connect method (mysql_real_connect) simply hangs randomly and unrecoverably 2 means exactly, precisely and inescapably that libmysqlclient provides at most one connection to a MySQL server and nothing else. And if you itch to tell me all about how my environment is “wrong” because “should have” used this not that and “upgraded” and so on, better shut up and read some more around – who knows, you might even arrive then some day to actually have something of your own to say instead of pushing and peddling without even realising it the precise problems that weigh you down currently.

The above unsavoury discovery of libmysqlclient’s limitation came about in the usual way this sort of things do: by surprise and at a slight change of the environment otherwise. I took about one week to implement -with suspiciously little trouble- a fully working set of Ada bindings for MySQL to finally ditch the awkward and time-consuming dance back and forth Ada-C-Ada for each and every query that the server needs to do. And then I took a deep dive in madness as the code that worked perfectly fine in one environment started simply hanging randomly as soon as deployed on the actual working server and with a rather weird stack trace and error – all of a sudden, since the… latin1 charset was supposedly not found despite obviously being both installed and previously found! Isolating the call and retrying proved entirely futile too: no, libmysqlclient and the whole stack of chairs that’s supposedly a working environment is utterly unable to recover, no matter how much time or retries you are willing to spend on it. Whoever heard of recovering from errors, right?

At any rate, I started then reading around to see otherwise if I can perhaps find the actual source of such trouble and maybe even – such strange idea – fix it in a way that is for once slightly easier than making my own libmysqlclient-equivalent too. Well, sources of trouble I found for sure, even more and more interesting than I had hoped for. For starters, the hanging behaviour is confirmed to happen sometimes indeed but you get your pick and choose – hey, you wanted the freedom to choose, right? – as to what exactly causes it in any specific observed case! For instance, searching through MySQL bugs leads one to #22322504 and #79510 that would perhaps fit the bill since they have to do with mysql_real_connect being in fact not thread-safe when invoked with some default options. Except, at a closer look, it turns out that those bugs (yes, it’s not just one, never just one, bugs come in sets and bunches at this level, basically it’s organised bugs ftw) are supposedly *fixed* in MySQL 5.7.14, while my environment is running MySQL 5.7.28. Sure, they might have reintroduced one or both or a combination or something else entirely in between those two versions – do you want to spend your time checking and tracking that?

Or perhaps if you choose to just believe that release document of MySQL and therefore assume that the problem is a different one, how about following the trail of that weird complaint about the latin1 character set? That one leads apparently to a very original set of bugs reported though, it would seem, mainly on freebsd lists starting with a bug in… libc, since libc provides a stub pthread_once method to “help” when you don’t actually need to link in the pthreads library: the way it helps, is that it makes therefore *sure* that you DO have to link the pthreads library or your program will crash since the stub does not do the initializations that it’s supposed to do. There’s at least one MySQL bug report dismissed though as not a MySQL bug so let’s quote instead from where someone actually looked at some code instead of dismissing the problem as “not my fault”:

libc.so defines a “stub” version of pthread_once(). Unfortunately, the stub version simply returns zero (success) without ever calling the init function, which does not satisfy the contract of pthread_once.

The effect of this is that if code which uses pthread_once is accidentally linked without libpthread, the code’s attempts to initialize data structures using pthread_once will silently fail, probably leading to unexpected and hard-to-debug crashes or other problems. When debugging this code, the developer may figure out easily enough that pthread_once() is not functioning, but is unlikely to realize that this is because he has not linked against libpthread — most developers would expect to have seen a linker error if this were the problem.

Do you enjoy the helpful way libc helps you yet? Wait, it gets even better though: further down the line, there’s also libstdc++ that decided to *rely* on this faulty behaviour of libc 3 so that now fixing one breaks the other and therefore you are neatly caught in the classic bureaucratic manner – you have plenty of options and none of them solves anything but they can surely keep you busy and bouncing from one to the other forever. You wanted “freedom to choose” and they serve you exactly that – in name, of course but isn’t that exactly how you “deliver” on your word and with your tasks, too? So, enjoy it, I guess.

Perhaps you noticed in the links above that they are on freebsd lists so now the additional question thus gained is – does the specific libc on my machine have the faulty or the correct stub? Sure, I can write some code and test it, as one option. Or I can dig out the code and read to find out, as another option. Both though are “options” to spend my time on something with dubious return at best. Isn’t this a wonderful world when the attempt to solve one problem which shouldn’t have been there to start with simply results in increasingly more and more complex trouble that – just the same! – shouldn’t have been there in the first place at all? Well, if you are the sort who wants to actually expose and solve problems as opposed to making do and hiding them but otherwise doesn’t quite stop to pick and choose the problems worth solving, then all and any bureaucracies will always be happy of course to provide you with as deep a set of nonsensical problems as you require to never get to do anything useful anyway!

As for myself, by the time I read all about that stub and the rest, I stopped wasting my time digging any further. Instead, I got back to my Ada bindings for MySQL and added to its functionality so that it can provide thread-safe access to a single connection since that’s all that it is actually available currently. It took all of half a day, too and it will serve *me* a lot in the future as well although indeed, I don’t expect it will serve libmysqlclient in any way. Did you ever stop to really and fully consider just who exactly does your work, whatever that might be, actually – as opposed to seemingly – benefit?

  1. I can give specific “version numbers”, sure, here you go: 20.3.15 for libmysqlclient and 5.7.28 for mysql. Do you think those are *exactly* the same on any OS and moreover do you think that nothing else comes into play when you try to actually use them? If you do, then the more fool you but don’t let me spoil it for you – go forth and waste in that labyrinth as much time and life as you want, I don’t even want to stop you, why would I?[]
  2. If reliably, as well, since all it takes is enough calls to it, for varying definitions of enough in this context.[]
  3. Here’s the reason as given: “Revert the previous change to pthread_once() stub in libc. It is actually a feature that libstdc++ depends on to simulate the behavior of libc’s internal ‘__isthreaded’ variable. One benefit of this is that _libc_once() is now private to _once_stub.c.” The classic “it’s not a bug but a feature! Why and how come? Because… I find it more convenient like that![]

October 4, 2020

The Story of Foxybot

Filed under: Coding,Eulora — Diana Coman @ 5:06 pm

Prelude:

~it’s ten minutes to set up and ten minutes of use to make itself indispensable. the chick can code, i don’t remember a tool becoming THIS FUCKING NEEDED in recent times.~

The Story

Going through my own archives and old logs may be time consuming but also quite an interesting exercise, meaning as it does that I get to look at an older context and a younger self again, only with more knowledgeable -and not just older- eyes. With the benefit of hindsight and of accumulated experience, even well remembered situations and well remembered words (of mine and of others) still yield more meaning than they did at that time, for what were *then* merely tiny signs and seeds meanwhile either grew and blossomed or shriveled up and died but looking back one can more easily see -in both cases- why and wherefore that specific outcome was even quite likely for each of them to start with. At times there are also the rather funny in hindsight bits, like those very, very early signs of my want of a bot:

diana_coman: I’m rather clueless at scripting unfortunately, did not have to use it much until now
chetty: there is a plan to allow crafting to proceed even if you are not online, queue up actions, but it is a way off
diana_coman: I will try to look into it, but not sure how much I can do 1

diana_coman: chetty, can you help with any pointers regarding eulora client’s structure if I am to start looking into the code? I have no idea of a crystal space app, so probably any ideas/pointers would be helpful
chetty: well what did you want to do with the client?
diana_coman: I first need to get some reasonable understanding of the code and what is done where, as otherwise I will hate just hacking it 2
diana_coman: but anyway, I was thinking of something along the lines of making annoying tasks less annoying 3
diana_coman: such as: automated “go to coordinates” 4
diana_coman: (I don’t even know how difficult that would be, lol)
chetty: lo, well the user interface pretty much all goes via ‘paws’
diana_coman: or “repeat crafting x until out of recipes/ingredients/etc”
diana_coman: or even shopping list thing for a given recipe
chetty: ahh some nice botting, that would actually be pretty cool
diana_coman: well, after playing it so much 5, I think I have some clear ideas of useful features, but I am still clueless regarding the client code, so not so sure how much/when I get to actually implement :p

diana_coman: for the moment more like trying to figure out the code with the hope to improve a bit the game experience afterwards; as in: automate repetitive tasks.
thestringpuller:reminds me of Eve
diana_coman: wasn’t Eve anti-bots?
thestringpuller: so is WoW but it didn’t stop people from using them
diana_coman: well of course, but as far as I understood Eulora is actually pro-bots
thestringpuller: tis like dinosaur island without the geneticism. (dumb facebook puzzle thing)
mircea_popescu: diana_coman eulora is actually pro. and ima write an article detailing it 6.

The above log conversations happened throughout June 2015. By the end of July 2015, I had released version 1.0 of my Crafting Bot. I still recall those weeks in the summer of 2015, of rather intense wtf at contact with the legacy client code. Not as much because they are the worst I know or even knew then otherwise but more likely because they packed quite a shock, seeing how at the time I had been happily away from code for years. So it was an unpleasant shock, a lot of unpleasant work and otherwise no help to be had from anywhere, but I still made my bot because I had a use and a need -in other words a real want- for it, as simple as that. Or as I was writing some time later: last year I started programming again, rather unexpectedly. Simply out of interest, as it happens with most things worth doing: I wanted something that did not exist, so I knuckled down and did it – as a result, now it exists.

From there on, things moved on quite quickly. There was indeed a prompt reward and publicity granted for and to my fledgling bot, as well as some various further discussions of it all on irc 7. At least one other player clearly stated they had a use for the bot too but if you think that actually helps concretely in some way… what can I say, it doesn’t really, no. At any rate, by September of the same year, I had released the second version that included a lot more but was also essentially a full re-write of everything: basically the first version served more as a prototype and ended up thrown away, the new bots re-written almost from scratch and all that on my own effort, my own time and my own dime, imagine that! Silly woman that I am to actually put in such effort when nobody is paying me for it and others are even stood -and waiting- to benefit from the results 8, right? Well, perhaps it all comes from my stupidity or perhaps it all comes from evaluating things a bit more thoroughly and from more angles and sides than you are used to even consider at all. At any rate, even laziness might have more sides than you think and for illustration of this, here’s the intro to this second version of the bots:

Like anywhere else, work in Eulora is a most wonderful thing …to watch. So rather than work on working, I worked on avoiding working – and [as a result] here are my two bots ready to take over Euloran world

By November of 2015, there was yet another version of the bots released and I can tell even now from my own writing that I wasn’t all that happy with all the muck and yuck involved in getting things done there. But nothing worth doing gets ever done without some struggle or without having to overcome unexpected shit so what is needed gets done whether it’s pleasant, easy, convenient, expected or exactly the opposite (as direction, while double, triple or many times over as intensity) of all four and more to boot.

The above is not to say of course that there weren’t also good things coming out of it – there were for instance the first actual maps of resources entirely *made possible* by and through my bot, even as early as October 2015. There was also the fun had in finally having a working systematic tool to use against the full bulk of unknown 9 that stood between myself and any significant gains in Eulora or otherwise put between myself and …actual playing (scratch that, I mean: winning) of the game! While it’s not documented as such at the time because I didn’t want to give it away 10, I can still recall that fine morning when I woke up to find that the tirelessly working bot had discovered an entirely new item and had produced already a very clear map that fully outlined the area of interest, as neat as neat can be. I’d say that’s about as close as one can come in this time and world to discovering new worlds essentially – if you think Eulora is less of a world for being made of bits, you might be missing yet again some sides and angles to it, so perhaps read a bit more about what Eulora even is and how it’s complex economy means way more than it may seem at a first glance or than the construct “real cash economy game” has meant so far.

At the end of 2015 and beginning of 2016, S.MG faced an unexpected blow of just about the worst sort possible: the CTO at the time and co-founder of S.MG fell ill and she didn’t recover. The announcement came as a terrible shock in more ways than my brief words in chan at that time might suggest. Then again, the #eulora chan or any other irc chan for that matter is not the place for everything, either. At any rate, this is the sort of event and resulting context for which nobody can really plan or get “fully prepared” in advance – when it happens you’ll face it with whatever you got to prepare *unknowingly* up to that point and whether that’s enough or not quite or not at all or only just there, it’s still all there is. In this case, all that useful work that I had put in before opened up simply a chance and nothing more, certainly not much choice: a chance for Eulora to restructure rather than close down and a chance for me to get involved even more than I had ever considered even possible by that time. Note perhaps that there’s little choice involved in this at all, more of a close and narrowly avoided encounter with the end.

As I started working for S.MG, there was of course less time to pour into developing the bot further. Nevertheless, its use only increased as players simply could not quite afford to *not* use it and there were various additions to it by myself (for instance, bundling) as well as by other players: first, Daniel P. Barron’s drunken explorer mode and then Mocky’s updates that were directly commissioned by S.MG though meanwhile vanished 11 together with their author.

The article on Foxybot’s 1st anniversary gathers together quite a few pieces of evidence regarding its usefulness and widespread use. And beyond that, there is of course a lot more that came out of it, not least of which a lot of discussions in the logs and a distillation of that into a whole model of software development, no less. While that specific direction didn’t *yet* get pursued much further (mainly for lack of time on my side, as I got swamped with a lot of other more pressing matters), it’s still precisely the sort of “unexpected” growth that marks as far as I can tell ~all things worth doing, worth *committing* for, in the first place – correctly or not, I consider that this is the best sign of having made an excellent decision as to what problem to solve: a good (or at least decent) solution to a random problem may solve that specific problem and no more but a similarly good/decent solution to a problem that *matters* offers in return a whole lot more than the initially visible direct benefit, as it practically opens up entirely new directions for growth.

The above theme of opening up new directions for growth is in fact very central to Eulora as a whole, I should say – and with good knowledge of it – by now. There’s the whole of the S.MG category documenting that for one perspective but meanwhile there are all the additional directions merely touched and barely opened up as part and parcel of all the work that went into getting some actual computer graphics and making the 2.0 client. While the old Foxybot is not going to make it as such into the new client (mainly as there’s little point to importing through it all the state-machine madness that was imposed by the rotten parts of the legacy client), the directions it opened are not lost or closed either and the automation of tasks will be just as needed some point anyway – only quite an easier task to implement with the new client and protocol.

Nevertheless, for all those openings and opportunities happening in plain sight, for all the documented amounts of Bitcoin involved and exchanging hands through the game and for all the previous opportunities not taken when available and closed meanwhile, those fewer and fewer remaining openings seem just as invisible today while available as the previous ones were back when they were still available, too. Arguably this is also exactly as it should be: the very same environment can seem empty and deserted to some and overcrowded with opportunities to others. At the end of the day, those seeing and capable do, those bright enough may at least follow and the rest will – at best – wait for whatever might happen since no happening has anything to do with them at all, anyway.

  1. Bwahahaha. How much did it turn out I can and did do and how much more there is to be done…[]
  2. Oh, the naivety of this young self of mine, how I wince to see it yet again! Did I get meanwhile a “reasonable understanding” of the unreasonable, would you say?[]
  3. This is how useful things start before it even registers as a start: by improving something that is, in its context, in its *meaningful* context. Not all that much by “being found”, nor by popping out of nowhere all formed and valuable by and in itself, objectively and in a void, no, how surprising. (For my English-speaking readers, here’s a translation of the highlighted fragment: The attempt to create value alone and in a void, apart and away from actual people and their interactions, the failure to understand that such a thing is not even possible since all the value comes from the subjective evaluation by others, the nutty search of some objective “gold” in the virtual world, those are all telltale signs that you still have all sorts of lessons to learn about the virtual as well as the real world and anyone having any money would certainly prefer, at least in principle, that you learn those needed lessons on your own money [rather than on theirs].) []
  4. The most important part of this aka pointing to the correct place was relatively easy to do, if extremely useful. It’s still in use: the /pilot command.[]
  5. In other words… after getting some actual experience and therefore beginning to form some understanding of the whole context too, as just the most basic prerequisite for coming up with anything useful anyway.[]
  6. Worth a read and a re-read at the very least, I’d say.[]
  7. The whole conversation there is quite funny for me on re-read. Then again, I suspect there’s at least one participant who’d rather prefer that the conversation and even its whole context never existed at all.[]
  8. Note that this *second* part is very important, too: while a lot of effort can be put into all sorts for which nobody is paying you, it does NOT follow that the lack of pay is a way to choose things or some sign of …usefulness! This is not something new, of course, nothing is new after all, but here’s a more straightforward statement that may help with it all (the loose translation to English is mine): in short, the fear and avoidance of competition is the mark of the incompetent and of those who know already that they’ll lose. The rest of people deliberately look for competition, focusing on identifying salient inefficiencies, coming up with strategies to get rid of them and then knuckling down to work. That’s what doing business even means, not just on the Internet but everywhere[]
  9. As part of the attempt to attack that, I also made and published a whole library of items that turned out very useful too.[]
  10. There is some data published at a later time and then even the actual fragment of the map, close to one full year later.[]
  11. Eh, except those I have mirrored myself, of course, as usual.[]

September 24, 2020

Of Boys and Chocolate

Filed under: Lyf,Young, old and oldest — Diana Coman @ 2:37 pm

The mysterious missive was read and a new purpose gained: “Now to understand what all this means!”, he joyously said, going through it all again in his head. “The trouble is clear: my presents are near but well hidden, I fear. There are clues and a key so I really can’t see what big trouble might be to figure it out in time for my tea. And if it takes the whole day, it’s even better, I’d say, since a difficult quest is really the best. In practice I’m told, it’s good to be bold but asking as well those who know to “please, tell” yields advice one can take to get faster to cake”:

bravehearts_1_640.jpg

At a later time, on the lookout for more (of everything really: more missives, more mysteries, more cake, more enemies, just… MORE):
bravehearts_2_640.jpg


Since I’ve been asked, here’s the text of the missive in full (and yes, I got a bit carried away with it since it was a welcome break from coding and more)
:

The word has spread throughout the realm that you may be looking for brave defenders for your castle! If that is so, we hope you’ll find us to your liking and we pledge our brave hearts, trusty arms and mighty weapons to your service.

We’ve heard the special day was set to be this Tuesday and so we traveled from far away and spared no effort to make it to your sight on time but here, so close to your castle, something terrible has happened to us: we got lost from one another and found ourselves in the most unsettling of places that we couldn’t even begin to describe! Will you come to our rescue as this realm of yours is unknown to us and we are afraid we’d be too late if we have to make our own way without any of your gracious help?

We are three brothers in arms: an archer, a swordsman and a halberdier. We know not how it came to be that we got separated but here’s what we know of our current surroundings, in the hope that some of it might hold a clue for you to find us soon:

– the archer found himself in a terribly, terribly cold place where there’s nothing to hunt, it’s mostly dark and only at times a ray of light shines blindingly through for a moment and then vanishes again before the eyes could even get used to it at all.

– the swordsman got trapped unexpectedly in a sort of traveling dark place, between a plastic wall and a white paper roll of something that seemed peaceful enough when left alone but who knows what it might do if poked with a sword!

– the halberdier is in an even worse predicament as it seems to him that a whole continent fell on top of him, almost squashing his entire breath out – the only chance he had was that this continent or whatever it is turns out to be relatively soft when prodded with the halberd but it’s still way too big to be moved out of the way.

Finally, there’s also a rumor going about that your castle has attracted a lot of interest, being as it is, a special kind of castle, as it befits your Highness surely. Unfortunately, some very interested party seems to be trying to snatch the castle for themselves and so you’ll have to find the place where they hid it! I’m told that the castle is big enough though (way bigger than us, of course!) and so it shouldn’t be all that difficult to find. Only remember the clue we’ve heard from an old woman that lived a long life and learnt a lot through all that living: all is not what it seems and the easiest place to hide something is in plain sight, among others of its kind.

We are eagerly awaiting you and hope you’ll find us all soon enough!

Your faithful servants to be,
Archer, Swordsman and Halberdier.

September 19, 2020

The Day When I Did Nothing At All

Filed under: Word Therapy — Diana Coman @ 3:47 pm

On the day when I did nothing at all, I woke up with a throbbing ball of accumulated tiredness instead of my usual head on the shoulders, I cooked breakfast for three, tidied everything up, then cycled with the child to school, bought some bread on the way back as it was needed at home, sorted out some pending correspondence and then did the laundry because that was needed too. I rested then for all of 15 minutes or rather those 15 minutes imposed their rest on me, without much cause for appeal.

On that same day when I did nothing at all, I cooked lunch as well, then discussed and clarified various issues as they popped up and claimed time that seemed stretched beyond recognition, cooked dinner, made some caramelised walnuts too, washed and cleaned everything as needed in the kitchen, set all up as required for next day’s meals as well, looked after the child, got him all ready for sleep and ready for his next day too. And then as I noticed off hand to someone else that I *really* did nothing at all the whole day, they replied that they nearly got tired only hearing that list of “nothing”, so what on Earth am I talking nonsense for?

By the end of the day when I did nothing at all, all it took was that unexpected question (such are the best friends to have!) to knock off entirely a whole ball of accumulated tiredness, for it was the weirdest of things to hold at the same time as equally valid that I did nothing at all and that I did at the same time quite a lot, too. Nevertheless, there wasn’t much of the day left (nor much awake of me) to figure this out in the least and so I let sleep claim whatever little was left of it all.

After the day when I did nothing at all, I woke up with the riddle solved, the answer all ready and fitting: it wasn’t as much that I hadn’t *done* anything the day before as it was that -for once, for one rather rare once- I hadn’t really *grown* at all that day as all those doings were the sort that had no weight for me anymore: they claimed merely some of my time and certainly my existence but close to none of my deep engagement otherwise. I had been present that day, certainly, but I hadn’t travelled with it anywhere further than on any of the days that had passed before, merely treading the same old ground, familiar and easy as it might be. And so it felt correctly that there was indeed nothing done – more precisely said nothing achieved that day, for all its enumerable motions that may seem like activity only to the youngest or most superficial of glances.

September 12, 2020

#eulora Logs for Sep 2020

Filed under: #eulora_irc,Logs — Diana Coman @ 8:09 pm
Day changed to 2020-09-12
feedbot: http://trilema.com/2020/desperation-in-desolation-or-the-woes-of-the-contemporary-entrepreneur-or-what-came-of-my-first-attempt-at-running-the-second-generation-eulora-client-ornery-in-any-case/ << Trilema S.MG — Desperation in desolation ; Or, the woes of the contemporary entrepreneur ; Or, what came of my first attempt at running the second generation Eulora client. Ornery, in any case. [20:09]

September 6, 2020

Moving On

Filed under: Dark Modern Ages,Outreach — Diana Coman @ 6:29 pm

For the past year and change, I kept bridging what seemed a naturally occurring gap and as such a sign of growth and life but turned out to be instead a pressure-induced crack, the first or more pronounced one of myriad to come and simply a sign of decay and death. While I am indeed willing to spend quite a lot of effort (as this past year shows, as much of my history otherwise records) to help new growth blossom and new life flourish, the flip side to this is that I can’t summon any interest *at all* in merely mending cracks and thus preserving or artificially keeping in a semblance of life what is on its own almost or already or only-not-quite dead.

What started last year in July mainly as an accessible entry point to TMSR, grew very rapidly although at times in rather unexpected directions. Several newcomers joined indeed in the very first months and despite their needs being at times greater than I had initially expected, I happily extended my hours, my resources and my effort as required to support them since they were working for their part as well. A short few months later however, the increased demand came not as much from new people as from those who had been around for years. Although surprised at this unexpected direction, I still did not turn them down but added yet another part to the project to try support as well the rebuilding and revitalising of old endeavours basically rather than just the starting of new ones.

Then people were caught unawares and some quite distraught in the aftermath of TMSR’s closure so I remained available and I didn’t just move on as swiftly as I could have done, as it would have been easiest and most convenient for me to do, too. I remained, reviewed and restructured instead. As I said then in #ossasepia, I planned to remain available for as long as there was use to it, but not longer, since from my point of view I had committed already to help those I had accepted and therefore I wasn’t going to shut anything down from under them. Yes, I hadn’t said it until now in quite those words because they weren’t required and I for one don’t need otherwise to affirm some commitment of mine for it to still carry more water and be more reliable in practice than a whole lot of verbal “commitments” and pledges from many others. If you think that pledge was there because *I* needed it in any way, think again and then look perhaps at what everyone involved actually did each and every day over this past year.

Right after TMSR’s end, there were various pushes and prods from old and new people alike and for the record, I’d rather state this part plainly too: while I was at the time quite open to anything moving indeed forwards and aiming for a new start (in other words: alive), I was at the same time indeed entirely opposed to any attempt at transforming the whole thing into either a preservation effort (dead but we keep it moving!) or a sort of cheapened, “more affordable” tmsr (sure, nobody called their intentions *that*, since finding the apt words is anyway a difficult matter and on top of it, plainly stating facts is unheard of and utterly scary – this direction was called instead a “continuation”). Given this position of mine and since preservation or cheapened replacement were indeed the only directions in great demand otherwise, things came to various heads and different more or less noisy dramas but when all those passed as well, there was mostly silence left and otherwise… going back I suppose, what forwards.

Perhaps one way to look at it now would be to simply say that it finally came to be indeed that there is no more use to it that I can see. After all, the Young Hands Club blog is unused since June and the irc chan has some use – if I use it, pretty much. This in itself wouldn’t be enough reason for me 1 to close it down and move on, since learning and sustainable self-improvement are just as needed today as they were last year, while the places that help and support that are just as scarce (or even scarcer) now than they were last year. It is however not at all the same time now as it was last year and I am more now than I was then, for the full experience of it. There’s a lot gained from the experience with the project itself over this relatively brief but intense past year, as well as from all the further explorations (some published, most unpublished) that I did as part of it. As a result, I am quite satisfied that this project in its current shape has helped as much as it could but has reached now its end, clearly enough. I’ll state it plainly too that I don’t bear anyone involved any ill will at all. Each came when they needed help, got what they could out of it, learned as much or as little as they could figure out and then moved on (or even moved back) as their own revised interests pushed them to, whether acknowledged plainly as such or not. I wish them all good luck and all the best in what they are doing now.

If and when I get involved to this degree again with helping others learn, it will take indeed a different shape and most likely it will be on a different scale as well 2 because part of the reason this ends here is precisely the fact that the uncovered problem is of such nature as to require a mass solution if there is indeed any solution to it. The one to one, highly personalized interaction may be in many ways great but it’s not going to ever do enough by itself as things currently stand and so I’m simply ending the Young Hands project now, so that it doesn’t drag on beyond its usefulness and doesn’t keep anything or anyone tied up to it in any way, for no good reason. This being said, the significant advantage of direct relationships built to any degree for real is that they can endure and grow beyond and outside of any project-frame as such – if and only if both parties put in the effort required for that to happen, of course.

In practical terms, I’ll get around some time to update the shared blog’s About page and turn off any logins but I’ll keep it all still online and accessible at younghands.club at least for a while so that if anyone wants to mirror it, they can. I’ll leave my irc client on and I’ll still be around at times in #ossasepia and in #eulora but not all that often and certainly not so reliably at the same hour every day any more 3. I will probably turn off/devoice all the bots in #osassepia for the time being too, as there is little point indeed in logging just blog feeds or the like.

If you want to talk to me, a simple comment here on the blog will do – after all, I’ve been here for more than 10 years already and unless I unexpectedly die one day soon, I’ll still be here for years to come, while countless others come and go, as others before them came and went having as they did all the consistency, substance and self-direction of dust blown about by the wind.

  1. It’s called staying power, dedication, commitment, at times even stubbornness. All sorts of words that once had a well-known meaning through common practice.[]
  2. For what it’s worth and if it’s any consolation to anyone, I rather think this will actually happen, although in a few years from now rather than next month or anything of this sort. Some things take time and some things moreover *have* a time of their own, too.[]
  3. For direct communication over the network, I still consider irc the best currently available solution and so I rather expect I’ll come back to it at a later time but only if and when other projects require it indeed.[]

September 1, 2020

#ossasepia Logs for Sep 2020

Filed under: #ossasepia,Logs — Diana Coman @ 6:09 pm
Day changed to 2020-09-01
feedbot: http://trilema.com/2020/king-ralph/ << Trilema — King Ralph [18:09]
feedbot: http://ossasepia.com/2020/09/01/ossasepia-logs-for-Sep-2020/ << Ossa Sepia — #ossasepia Logs for Sep 2020 [18:13]
Day changed to 2020-09-02
feedbot: http://trilema.com/2020/maria-full-of-grace/ << Trilema — Maria full of… grace [06:09]
feedbot: http://trilema.com/2020/one-day/ << Trilema — One day [10:30]
Day changed to 2020-09-05
jfw: diana_coman: I can't commit to taking on the irc to chat-apps-du-jour bridging project presently. Things are moving forward on JWRD's infrastructure build-out deal and I expect that work to heat up again soon; meanwhile my hands are pretty full otherwise. [21:08]
diana_coman: jfw: no worries and rather happy to hear that the jwrd deal is moving forward. [21:09]
jfw: thanks. I'll let you know if things change such that I can revisit the project. [21:10]
diana_coman: sure, it can't hurt, although I rather expect things will change regarding the project itself, too. [21:12]
Day changed to 2020-09-06
feedbot: http://ossasepia.com/2020/09/06/moving-on/ << Ossa Sepia — Moving On [20:33]
cruciform: diana_coman, I just wanted to say thanks for your help, attention and advice through Young Hands; thank you! [20:53]
diana_coman: cruciform: no problem at all; did anything come out of it for you? [20:54]
cruciform: yes – I got a better understanding of how inadequate, lazy and languorous I am [20:56]
diana_coman: well, I do hope you dress up for it too then, at least from time to time. All that has its own requirements of attire if nothing else! [21:02]
cruciform: lol [21:03]
cruciform: the tuxedo's been in the closet since pre-plague, so it's not even been a stylish indolence [21:05]
diana_coman: ah, no, no, it goes back quite a few years before that, more of those times when everyone looked at men's legs rather than women's. [21:06]
cruciform: how far back are we talking – Georgian? [21:07]
diana_coman: ah, I suppose george 4th might serve, indeed. My mind went of course across the channel though, there's something to be said for the French in such matters. [21:10]
cruciform: I suppose it is a bit odd that women tend to be the peacocks, nowadays [21:12]
diana_coman: what else can they do, you know? [21:13]
diana_coman: (and for that matter, hm, there's always Italy, that land where women have to work hard to only keep up with men's creams and perfumes and the like, not sure it's any better!) [21:14]
cruciform: ah, yes – there's a wonderful Italian perfume critic – Luca Turin; has an unreal ability to put scent into words [21:18]
cruciform: I was wondering – would you consider keeping my Young Hands login active? [21:20]
trinque: diana_coman: just wanted to pop in and say that I have a great deal of respect for you, and wish you well in the future. [21:21]
diana_coman: trinque: thank you. I'll always gladly hear from you! [21:23]
diana_coman: cruciform: I would, if I see a good reason for it. Do you want again to write there? [21:25]
jfw: diana_coman: in case my own dedication/stubbornness doesn't say it clearly enough already I also offer my thanks for the time & attention given through YH. [21:25]
cruciform: very much – I've been putting it off again and again [21:26]
trinque: diana_coman: I'll continue to be a reader of your blog, for sure, and will chime in there sometime. [21:26]
jfw: cruciform: what stops you from setting up your own blog? [21:26]
cruciform: jfw, mostly technical know-how [21:27]
diana_coman: jfw: my pleasure; (and yes, in your case it did say it already clear enough; for that matter you are the one and only member of the club as it were!) [21:28]
jfw: cruciform: so maybe you have now a reason to pick up some of that? :) [21:28]
cruciform: jfw, yes! [21:28]
trinque: also I have to say that as a part-Italian mutt, my bathroom drawer of lotions feels singled out! [21:29]
trinque: must be in the blood, lol [21:29]
diana_coman: cruciform: for starters it's as simple as this: if I see a published article there at least 2 times per week, I won't turn off the login of that author. [21:29]
cruciform: diana_coman, thank you [21:30]
diana_coman: trinque: who knows, maybe at the time of 2.0 you give a try to eulora too. [21:32]
trinque: sure, I'll be looking out for it [21:33]
diana_coman: (and lol @ lotions, I never quite figured out to what degree it was a cultural thing only, for sure!) [21:33]
trinque: I just don't see how having fine things became "gay" [21:36]
cruciform: trinque, indeed – I get constantly ribbed by friends/hit on by gays for dressing up [21:37]
diana_coman: eh, it "became gay" only in that sense of "those not having fine things gathered together and decided that having fine things is bad-for-you" [21:37]
trinque: fact [21:37]
diana_coman: cruciform: you know, now you'll have to add at least 1 picture per month to those articles too. [21:43]
cruciform: diana_coman, lol, deal! [21:44]
diana_coman: thank you all for popping in today, I'll need to go offline though in a few minutes; as mentioned, I'll still be around from time to time so sooner or later I'll read anything left in here anyway. [21:49]
Day changed to 2020-09-07
lobbes: diana_coman: likewise, I'd like to once again thank you for all your help over the years. I'll certainly be a continued reader of ossasepia and will be keeping an eye on euloran development [03:18]
lobbes: I'll probably end up mirroring YHC before the end of this month. I'll post a link once that is complete [03:19]
feedbot: http://trilema.com/2020/guys-things-attestament-of-life-times-oceanside/ << Trilema — Guys & things, attestament of life & times, oceanside [08:21]
diana_coman: lobbes: no problem. [16:06]
Day changed to 2020-09-08
feedbot: http://trilema.com/2020/the-dusts-of-days-a-consolation/ << Trilema — The dusts of days, a consolation. [20:36]
Day changed to 2020-09-10
feedbot: http://trilema.com/2020/my-first-mister/ << Trilema — My first mister [12:44]
feedbot: http://trilema.com/2020/aaaalge-bra/ << Trilema — Aaaalge-bra [18:18]
whaack: diana_coman: Thank you for all the effort you put into younghands. I hope from the mentor side you got a fraction of what I got out of it. I'll still try to get out the block explorer project, and hopefully will find a way to revive my blog. I'll also try to put some time into playing Eulora when 2.0 comes out. [19:34]
Day changed to 2020-09-11
feedbot: http://younghands.club/2020/09/11/waking-up/ << Young Hands Club — Waking Up [02:11]
diana_coman: whaack: no problem. [14:08]
diana_coman: Those already having an Eulora account have/have had quite some time to figure out both how things work and what sort of things could be done with it all far beyond "putting some time" into a game. [14:12]
diana_coman: not that this option saw much use, but stating it for the record anyway. [14:13]
Day changed to 2020-09-12
feedbot: http://trilema.com/2020/desperation-in-desolation-or-the-woes-of-the-contemporary-entrepreneur-or-what-came-of-my-first-attempt-at-running-the-second-generation-eulora-client-ornery-in-any-case/ << Trilema — Desperation in desolation ; Or, the woes of the contemporary entrepreneur ; Or, what came of my first attempt at running the second generation Eulora client. Ornery, in any case. [20:09]
feedbot: http://ossasepia.com/2020/09/12/eulora-logs-for-Sep-2020/ << Ossa Sepia — #eulora Logs for Sep 2020 [20:13]
feedbot: http://younghands.club/2020/09/12/credenda-agenda/ << Young Hands Club — Credenda, Agenda [23:24]
feedbot: http://younghands.club/2020/09/12/credenda-agenda/ << Young Hands Club — Credenda, Agenda [23:33]
Day changed to 2020-09-13
feedbot: http://trilema.com/2020/night-and-the-city/ << Trilema — Night And The City [06:51]
feedbot: http://trilema.com/2020/i-go-out-walkin/ << Trilema — I go out walkin… [18:58]
Day changed to 2020-09-14
feedbot: http://younghands.club/2020/09/14/ossasepia-log-notes-1/ << Young Hands Club — Ossasepia Log Notes 1 [03:14]
feedbot: http://trilema.com/2020/ben-doesnt-get-fingered/ << Trilema — Ben doesn't get fingered [03:18]
feedbot: http://younghands.club/2020/09/14/dg-agenda-20200914/ << Young Hands Club — DG Agenda 2020.09.14 [03:26]
feedbot: http://trilema.com/2020/the-magic-johnson-and-other-stories/ << Trilema — The Magic Johnson and other stories [18:24]
cruciform: deedbot, hi! thanks so much for your most recent advice! [18:45]
cruciform: I may be derping, but it appears some logs are missing from the ossasepia records? For example, the last entry for July 2019 is the 19th, whereas asciilifeform's log viewer shows, eg. logs for the 30th of that month [18:48]
cruciform: *diana_coman, hi! :P (greetings to deedbot, too) [18:51]
diana_coman: cruciform: how is that the last entry? look http://ossasepia.com/category/logs/ossasepia/ [18:53]
diana_coman: and mind that dates/times are a matter of where the bot runs so they might not match (ie a line may be recorded by one bot to be on the 19th while another bot considers it on the 20th) [18:54]
diana_coman: anyway, full logs for July as far as I can see e.g. http://ossasepia.com/2020/04/20/ossasepia-logs-for-20-Jul-2019/ so dunno, learn to look properly first and use that category for all it's worth? [18:54]
diana_coman: is away from keyboard. [18:55]
jfw: looks like an out-of-order import so the next/previous links don't always work, and the ordering in the category shows as jul-aug-jul-sep. [18:57]
cruciform: aha, I was indeed derping (searching for June, rather than July…) – may be more tired than I thought :P [18:58]
cruciform: diana_coman, jfw – thanks for the clarification [18:58]
Day changed to 2020-09-15
feedbot: http://younghands.club/2020/09/14/ossasepia-log-notes-2/ << Young Hands Club — Ossasepia Log Notes 2 [00:41]
feedbot: http://younghands.club/2020/09/15/dg-agenda-20200915/ << Young Hands Club — DG Agenda 2020.09.15 [02:45]
Day changed to 2020-09-16
feedbot: http://trilema.com/2020/the-pishtar-gate-cathouse/ << Trilema — The Pishtar gate cathouse [00:46]
feedbot: http://younghands.club/2020/09/15/ossasepia-log-notes-3/ << Young Hands Club — Ossasepia Log Notes 3 [00:59]
feedbot: http://younghands.club/2020/09/15/dg-agenda-20200916/ << Young Hands Club — DG Agenda 2020.09.16 [01:27]
dorion: diana_coman, thank you for being you. I've read your article and the #o log. while I've not seen vacation as mp asked, I'm reminded that's pretty much what I've been on since returning to vermont. [21:03]
dorion: on the bright side, the light at the end of the tunnel has been the deal jfw and I are closing this month (which we've been waiting on since july (there coulda/woulda/shoulda been other deals, but hence the vacation)). [21:03]
dorion: we're contracting ourselves to weekly reports to the client, so the muscles we developed with you and young hands will be flexed. [21:04]
dorion: thank you also for keeping yourself available as long as you have. while it was a bit of shock in the moment for mp to close tmsr, I'm thankful I don't have to consider where I would have been without you. [21:04]
dorion: upon a moments' reflection it made sense when he did it, just as your communcation makes sense. [21:04]
dorion: whether or not I will deal with that sense in a rational manner is for me to decide and prove. [21:05]
dorion: I'm sorry diana_coman for the promises I've made to you that I didn't deliver on. part of me wants to say more, but I'll rest on the fact you're pretty consistent in evaluating actions and those simply speak for themselves. [21:05]
diana_coman: dorion: you are very welcome. [21:06]
diana_coman: and I'll gladly hear from you, of course. [21:07]
dorion: I like ossasepia.com's header photo today, btw. [21:08]
diana_coman: dorion: heh, that's in Lugano and yes, it kind of stirs some memories [21:08]
dorion: ah I see. is it a cafe ? bakery ? looks like the arches are being repainted for the nth time. [21:10]
diana_coman: ha! those in the back are salamis! enormous and tasty but ..salami and sausages and the like [21:11]
diana_coman: it was a side shop, there's a street with arches like that [21:12]
diana_coman: the arches-style is quite common in that area (roughly speaking tyrol but svizzera italiana might take offense at that) [21:12]
diana_coman: and yeah, there are …slabs of chocolate to be had there too, but what can I say, I like sausages better than chocolate, lol [21:14]
dorion: my misperception there was lulzy. sounds like a cool street. [21:16]
Day changed to 2020-09-17
feedbot: http://younghands.club/2020/09/16/ossasepia-log-notes-4/ << Young Hands Club — Ossasepia Log Notes 4 [00:22]
feedbot: http://younghands.club/2020/09/17/initial-thoughts-on-trilema-log-linking-problem/ << Young Hands Club — Initial Thoughts on Trilema Log-Linking Problem [02:12]
feedbot: http://younghands.club/2020/09/17/dg-agenda-20200917/ << Young Hands Club — DG Agenda 2020.09.17 [02:36]
cruciform: hi, diana_coman! [20:02]
cruciform: May I ask you questions, here; what is the nature of our relationship post-moving on? I’m very grateful for your continued help, but don’t want to presume anything. [20:04]
diana_coman: hi cruciform. So don't presume and all is well & easy, lol. Other than that though: questions can always be *asked*, how would that part even be somehow depending on anything else? Note that not asking is never really anything other than protecting your own fear of "what if the answer is not what I like to hear" (silence/rejection included), [20:18]
diana_coman: the pickle however is that if you do *not* ask, you'll… never know the answer, either. [20:23]
cruciform: aha, so I can be safely ignorant, or else take a risk and speak up [20:24]
diana_coman: here, found the ref, it's 200% valid for asking too : http://ossasepia.com/2020/04/20/ossasepia-logs-for-29-Oct-2019/#1008057 [20:25]
sonofawitch: 2019-10-29 17:55:51 (#ossasepia) diana_coman: eh, speak, there's nothing worth keeping that you might lose just for the speaking; quite the opposite [20:25]
diana_coman: "safely" as in maintaining the illusion of safety, that's about it. [20:25]
diana_coman: and with that illusion, maintaining as well (even growing) the fear(s). [20:25]
diana_coman: anyway, to make it crystal clear: anyone can ask anything, there's no way *that* somehow magically "can't be done"; it's your action so you can do it. [20:26]
diana_coman: whether I answer or what or when or so on, is my action though, true enough. [20:27]
cruciform: I didn't want to give the impression that I thought you were obliged to answer – or otherwise (seem to) be impertinent [20:28]
diana_coman: you can't control impressions, you know? but I can set your mind at rest there: I don't feel obliged to answer questions in general like that, no, I'm kind of too old (or not British enough perhaps) for that sort of thing. [20:29]
cruciform: phew :) [20:29]
cruciform: so [20:29]
diana_coman: as for the rest, sure, so don't ask impertinently, easy. [20:29]
cruciform: makes sense! I'm probably spinning/inventing problems [20:30]
cruciform: but, is there any sense in my asking about the nature of our relationship? [20:30]
diana_coman: if you want something, you'll have to ask for *that* so be more precise there. [20:33]
cruciform: for example, I have categories for friend/relative/lover etc., with defined behaviours for each – erm, what category does our relationship fall into – student/teacher? [20:34]
diana_coman: ahahah [20:34]
cruciform: :P [20:35]
diana_coman: alien category! [20:35]
diana_coman: now what? [20:35]
cruciform: yes, I thought it might be uncategorisable, or at least one unknown to me [20:35]
diana_coman: you seriously are telling me that you have a sort of internal/mental 3 ring binder with "defined behaviours for type of… relationships"? [20:36]
diana_coman: lolz [20:36]
cruciform: well, in the least autistic way possible [20:36]
diana_coman: and so if all of a sudden you encounter in this horribly mean world the…alien, what do you do? "error!" [20:37]
cruciform: but, you know – I'd call my boss "sir", and not tell dirty jokes to someone's grandma – that sort of thing [20:37]
diana_coman: some grandmas might love them though [20:37]
cruciform: back to speaking up and taking risks! [20:37]
diana_coman: and I'd rather bet some grandmas know dirtier jokes than you. [20:37]
cruciform: lol [20:38]
diana_coman: this sort of "living by the book-of-rules" is not altogether very… sane, how to put it. [20:38]
cruciform: what's a better way? ad-hoc play it by ear? [20:39]
diana_coman: sure, be *aware* of context and knowledgeable but that is an entirely different thing; quite in the same way that learning something is quite different from memorising a pattern of "solving" [20:39]
cruciform: If I take time to respond, it's because it often takes me 5 goes to parse what you're saying (incidentally, this is only the case with your/MP's text) [20:41]
diana_coman: getting back to your original question: the more logical thing for you is to figure out what you want it to be and then what to do for that. [20:42]
cruciform: I thought you might say that! [20:42]
cruciform: is this a causes/purposes thing? [20:42]
diana_coman: as the saying goes: so you are not *entirely* an idiot! [20:43]
cruciform: lol [20:43]
cruciform: one other thing, is the correct pronunciation of your name "DEE-ana", as opposed to "DIE-ana"? [20:44]
cruciform: (a Romanian corrected me) [20:46]
diana_coman: it is but once again, I lived in enough places to not be bothered by ~any of that. [20:46]
diana_coman: somewhere in the logs I linked once a video with the pronounciation , as someone else asked, I don't quite recall who. [20:47]
diana_coman: cruciform: re earlier question – it's more an active/passive thing first of all than causes/purposes. [20:47]
cruciform: what can *I* do to define our relationship, rather than what is done to me by you? [20:49]
diana_coman: ahaha [20:49]
diana_coman: figure it out, you know? [20:49]
cruciform: :p [20:49]
cruciform: yes – food for thought! [20:49]
cruciform: ok, I shall ruminate over the above; thanks for your help! [20:50]
cruciform: gets back to work [20:50]
diana_coman: no problem [20:51]
diana_coman: cruciform: if it's any help, note perhaps that it tends to be easier to figure out what one does *not* want; arguably it's more important too, anyway. [21:13]
diana_coman: is afk [21:13]
Day changed to 2020-09-18
feedbot: http://younghands.club/2020/09/17/dg-agenda-20200918/ << Young Hands Club — DG Agenda 2020.09.18 [01:57]
Day changed to 2020-09-19
feedbot: http://trilema.com/2020/a-slew-of-supersluou-subdates/ << Trilema — A slew of supersluou subdates [15:26]
feedbot: http://ossasepia.com/2020/09/19/the-day-when-i-did-nothing-at-all/ << Ossa Sepia — The Day When I Did Nothing At All [17:59]
Day changed to 2020-09-21
feedbot: http://younghands.club/2020/09/20/dg-review-week-of-20200914/ << Young Hands Club — DG Review, Week of 2020/09/14 [01:16]
feedbot: http://younghands.club/2020/09/20/dg-agenda-20200921/ << Young Hands Club — DG Agenda 2020.09.21 [01:33]
cruciform: diana_coman, is the bitcoin foundation still the reference implementation of TRB, or are they deprecated, on account of negrating? [21:57]
sonofawitch: 2020-06-06 20:58:55 (#ossasepia) diana_coman: well, at least TBF's status is quite clear now although apparently I have to go fish it out and add it to the record since those involved are too busy calling me names but not to my face; by the ponder of words in tbf's log apparently asciilifeform runs now the foundation in any case and jurov practices his hand at [21:57]
cruciform: also, would you kindly recommend an OS to attempt the installation on? I've had a look around republican blogs, and am having trouble finding a known-working one [23:10]
feedbot: http://younghands.club/2020/09/21/initial-thoughts-on-setting-up-a-trb-node/ << Young Hands Club — Initial Thoughts on Setting Up a TRB Node [23:38]
Day changed to 2020-09-22
feedbot: http://younghands.club/2020/09/21/ossasepia-log-notes-5/ << Young Hands Club — Ossasepia Log Notes 5 [00:07]
feedbot: http://younghands.club/2020/09/21/a-smoother-style-of-summary/ << Young Hands Club — A Smoother Style of Summary [00:07]
feedbot: http://younghands.club/2020/09/21/dg-agenda-20200922/ << Young Hands Club — DG Agenda 2020.09.22 [00:45]
diana_coman: cruciform – a reference for *whom*? In the absolute like that aka "the" reference, there isn't such thing anymore and not because of my negrating but simply because there is nothing to back such claim of "the reference". So now it's each with whatever they consider their own reference(s) and up to each to figure out what is worth what and why and so on. [09:07]
diana_coman: Sure, you'd like some clarity (just as you wanted it before with the relationship status here and all that) but note that *all that time when crystal clarity has been available and freely offered* you… were busy, found problems and faults with it and stayed away from it. So no, it's not "just like before only in just those parts that are convenient for me to consider or ask for". [09:09]
diana_coman: with this, the moving on is finally done for #ossasepia too: I devoiced everyone and removed all flags from all bots, feel free to take them offline as there isn't going to be any use for them in here. [09:57]

August 31, 2020

In Euloran Moving Updates: Inner Slots and Outer Wheels

Filed under: Coding,Eulora — Diana Coman @ 7:39 pm

I don’t care how many angels can dance on the head of a pin! What I want to know is how many tiny details can one devil simultaneously be in.

The only reason why my love for graphical user interfaces (GUI) suffered no loss over this past week or so is that I hadn’t any such love to start with. The clientside required bits and parts for performing actions turned out to be a considerable pile of small but quite detailed pieces that seem tiny each on its own but add up quickly to eat a lot of time while remaining otherwise hidden internals so that there is at first nothing to actually show for all the work. As I looked in more detail at what the GUI needed to be able again to fully interact with the world, the work seemed at first to just keep growing at every step instead of shrinking: there were GUI elements missing and then new methods required for querying the local cache and new configuration options and synchronizing and whatnot.

Experience helped here a lot, as I know this sort of pile-of-details stage for exactly what it is, part and parcel of work at times. So I just kept the work as contained as possible and otherwise I kept going with it until I finally brought it all to the point where there are enough of the required internal mechanisms in place so that they can support the desired GUI interaction itself. As a result, I can illustrate now at least some of the new additions, if still not all. At any rate, Eulora’s client has now in place the basic mechanisms for interacting via mouse or console (text) with any items or characters in the world, whether they are contained in one another or simply directly in the world, on their own. There are still all sorts of details that will have to be sorted out – or possibly altered even – as everything else comes together but those are secondary details, those that can never be fixed in stone at the first pass anyway, nor should they ever be so inflexible as to have to be fixed in the first place.

To start with, the Console has increased usefulness and usability. The most important improvement from my point of view is that there is now in place a generic mechanism to deal with any command from the user: the first word is the command itself, while any following text is read as a list of “parameter=value” tuples, where the order does *not* matter and there is no restriction whatsoever on what “parameter” might be. Basically the Console simply grabs the full text, uses the first word to find the action that goes by that name (if any) and then passes whatever text follows to the action itself to handle. The action in turn has its own default values for all parameters but then goes through the given text and sets the given values as found, if and when found. As an interesting effect of this approach, the user can even set the same parameter several times in a single command but the value used will simply be the last one encountered. Moreover, as much as possible the same letter stands for the same thing for *all* actions – the most obvious example is the target which is t everywhere, not like it’s all that difficult, really. Anyway, by means of illustration, here are two screenshots with some commands:

gui_movement_2_640.png
gui_movement_10_640.png

The above new wiring of commands to actions means also that I can now easily add new actions at any time, since it’s just a matter of implementing what the action is meant to do and otherwise adding it to the list, nothing more – all the wiring from Console and even from the rest of the GUI will simply adjust and include it too, as it should. In addition to this, there are a few more small but rather very useful improvements including clearer feedback from entered commands, resizing of the Console window so that it correctly resizes the two internal parts as well and a 1-line “history” so that one can recall the previous command at any time. In funny inherited weirdness that I’ll probably have to look at later on, it turns out that a resize has as side effect the reset of the font’s colour though! Such is the underlying nature of the inherited core widgets, this ever plentiful source of surprises of the most… surprising kind.

As you can perhaps notice in the illustration above, the GUI offers now the full list of actions defined in the communications protocol but also a few additional “actions” of its own, such as “pos” or “examine”. The reason for those additional actions is that they are simply quite convenient for the user and entirely a clientside concern: one might want to find out their exact position for instance and the GUI can expose that easily so I’d very much rather it did. There is of course no limit to what can be added there either but I didn’t spend time to polish this: the point for now was to have the very basics in and otherwise have it there as an example rather than anything else. For illustration, here’s the result of “examine” applied to the character itself:

gui_movement_3_640.png

While the Console remains to my eye the easier interaction option the user can have, I’ve nevertheless put in the work required to have a working mouse-powered option as well. So the skin.zip file got bigger and includes now at least one icon for each type of (inter)action known to the client. (And don’t ask me why is the “repair” icon showing a hammer crossed over by a rolling pin, I can’t begin to imagine where that combination comes from!) Those icons are then used in a new Context window that can be accessed with a right click on any item 1 and provides links to all the known actions. And since my GUI is not made with love 2 but with calculations whenever possible, this Context window simply uses basic trigonometry to just figure out where each icon goes so that all actions are shown neatly in a circle. As a consequence, if a new action is added, the Context window will simply adapt and include that too, there’s no need to add it manually and fiddle with its position through xml until the cows come home. Such are the results of bringing the ancient magic of the sine and cosine to the innocent lands of GUI and other computer ruralia! Lo and behold the euloran outer wheel of perfect roundness and plentiful context interaction (see the console in there for feedback on clicked actions):

gui_movement_4_640.png
gui_movement_5_640.png

Getting back to the actions itself, with the exception of lock and exchange, all the other protocol-defined actions are currently fully wired into the client, meaning that the relevant messages are created and sent to the server. The movement action is at the moment rather annoying and choppy so there is certainly more work needed there but I think it should still wait as some of the issues are likely to get smoothed out anyway as everything else advances (part of the choppiness is likely to be more a matter of the values I have currently set for the sync intervals for the whole world, for instance). Although I didn’t fully go into all the remaining movement part at this time, I start thinking that I’ll have to do that too at some point, most probably to finally kill that stupid of “leg length” and “falling below 0”, if nothing else. Nevertheless, it can still wait a bit, perhaps.

Arguably the most time-consuming “action” in all the above was the move/pickup since it required the whole inventory GUI with slots and equipped vs non-equipped and stacks and splitting stacks and moving items in inventory too and everything under the sun in there. There was a bit of mini-puzzle fun with the formula for inventory (non-equipped) slots, some annoying further misbehaving of that listbox that has the handy scrollbars and all sorts of weird discoveries regarding the number-prompt window. Nevertheless, the whole thing is now working, the Contents window got basically an upgrade, can move items about and is quite ready to be of further use as half of an exchange of any sort. The “move” action on items in the world is effectively a “pickup” – it will attempt to move the items to the next empty slot (calculated on the fly, too) in inventory and won’t care a bit whether that is possible or not possible. After all, you never know unless you try so my GUI here is not at all in the business of telling the user what they can and can’t do: it provides the widest set of options to everything and then dutifully executes what the user asked for. The inventory window updates with server-given data only on reopen (all it takes is to press i for that) but otherwise it will happily show the user whatever they thought they could do, pretty much. I’m quite sure that there are all sorts of details to change here on future iterations but for this first pass, I think it does as much as can be done for now:

gui_movement_6_640.png
gui_movement_7_640.png
gui_movement_9_640.png
gui_movement_8_640.png

For the number input window, I initially wanted to reuse the original window as it was since it had in place some input checks and limits and all those things that are in principle quite useful. The fun part started though when it turned out that it had of course all sorts of silly expectations – that got therefore cut away – and otherwise it used a horizontal scrollbar to allow the setting of the amount via mouse movement. This horizontal scrollbar was simply not able to use 64-bits integers without requiring otherwise a full update throughout the whole client, basically in all places where a scrollbar is used at all. So rather than indulge in such waste of time, I just dropped the silly scrollbar-set from this window and otherwise updated the remaining small part to deal with 64-bits integers, what else. Since I was at it, I added also overflow guards, as there were none but other than thatm the thing is (at least now) small enough to be perhaps of some use currently.

On a side note related to inventory and slots in general, I added again the quantity and quality labels to each slot but the trouble is that the maximum 64-bits value has 20 characters and to fit as many as that onto a slot, the font ends up so tiny as to be unreadable. So for the time being I let them be as you can see in the screenshots above, using a reasonably small font that means however that the full value might simply not be visible at times. I suppose this might remain as one of those low-hanging fruit to pick for any client developer out there.

Regarding the actions themselves, on serverside, at the moment, those action messages that the client sends are received, unpacked, recognised as what they are and otherwise promptly discarded. There’s quite a lot to implement on serverside before they can fully be acted upon as intended. Nevertheless, for current testing and illustration purposes, the serverside simply has some mock data that it sends to the client as “the world” and that is quite enough for the moment (though it won’t be for much longer, by the looks of it all).

With all the above in place and working, there would still be the exchange and lock actions and corresponding GUI elements as such. Other than that, there are various non-GUI parts that could be done (and need done at some point anyway) on the client, such as the management of Serpent keys and actually dealing with a change of connection/server on the fly.

Let me know in any case if there’s anything else/different you want done for the GUI part at this stage and otherwise if there’s something else specifically burning/best to tackle next. I should also mention perhaps that in the interest of documentation and seriously applying myself to learning the craft of GUIs, I have indeed reinstalled Diablo as well and gave it a spin – the windows are a pleasure, the tick-tock of idiotic walking is more annoying than any skeletons that might appear from the barrels. Nevertheless and purely for work interests, I shall therefore endure Diablo re-plays whenever required!

  1. This ran at first into a weird “attachment” thing that apparently was required in order to have a direct link between CS meshes and the game objects that the remaining client core works with more directly. And when that in place, there was the repeated and infuriating further run into the PS notion of “any item”, such as it still remained in the various parts that are still in use in any capacity: “Oh, by any you surely *don’t* mean meshes AND moving items, do you?” and “Even if moving items too, then *surely not* your own character, too!!” and so on and so forth, it’s like the devil is not in the details but rather the devil is a detail inside a detail inside a detail inside… []
  2. By now this made-with-love advertisement stands as far as I can tell for “it will blow up in your face but you should be happy about the blow up, because it didn’t mean to do you any harm!!”. Here’s an illustration, too, some typical result of the made with love approach.[]

August 20, 2020

The GUI, the Core and the Data

Filed under: Coding,Eulora — Diana Coman @ 3:49 pm

This report brings to you the latest news from the lively Euloran development grounds: the GUI is shedding code and growing in usefulness, the Core adds to its services the packing and unpacking of all user actions known so far, the Data cache refuses to be led astray into unnecessary sync swamps and gets its responsibilities right, while overall all three parts arrive at a clearer way of working well together and working well apart, providing what’s needed for others but minding otherwise their own business at all times. This last part of “minding their own business” took a bit of thinking over those past few days, as the newly added user actions didn’t yet have a clear place of their own and it’s precisely the clear and fitting definition of “own business” for each component that makes or breaks the whole: do it right and everything fits afterwards quite “efortlessly” or do it poorly and then you’ll fight at every step to fit all sorts of square pegs into round holes (and rebuild the swamps, too, as a result of that sort of mindless fight).

To describe the whole thing, it’s clearest (and not too long) to start from the beginning: Eulora’s client has currently implemented 2 main components, namely the Core and the GUI. The responsibilities of those components have been defined initially at a high level only, as the details were not yet clear. That initial definition got gradually more detailed as I implemented more and more of the actual communication protocol but broadly speaking, the original scope is still valid: the Core is responsible for handling *all* aspects of communication with server, from network data packing and encryption to actual logic for data acquisition and storage; the GUI (as stated in its name itself) is responsible for data presentation to the user and handling all user interaction.

While the above high level view is clear enough as it is, the trouble with going into the more detailed, concrete user interaction is that its very purpose is precisely to *change* the data so carefully acquired by the Core and so neatly presented by the GUI. Add to it that any user actions in the game are more accurately defined as *attempts* to change the data, with no guaranteed outcome until and unless the server actually changes the tiniest bit of the game-world in response to them and it would seem that those user actions are indeed straddling most uncomfortably the responsibilities of both Core and GUI: get the action from the user (GUI), send the request to the server (Core) but also change the data already so that the user promptly sees the effect of their action (Core *and* GUI?). At which point, the reader familiar in the slightest with the PS coding swamps might recognise that old pattern of “all GUI elements require a connection to the server and direct knowledge of message types.” Because indeed, it can easily *seem* like a …solution of sorts, except it’s of course no solution at all but simply the path of least resistance and even less reflection: it “seems” and therefore it is, why bother with anything else at all. Well, to keep this short, I’ll note only that I’ve been toiling for quite a few years precisely cleaning up the results of others’ even *more years* of following that path of least resistance.

The change to data as result of a user action is further problematic in that any change done by the client is essentially a guess: at best it gets confirmed in time by the server and therefore all is fine but at worst it gets undone (while *other* things may change too!) and that brings with it the potential further invalidation of all sorts, even of later user actions! Quite the thorny problem to handle, as any synchronizing problem ever is. So the naive approach to handling those thorns goes (again!) the route of yet another part of the PS swamps: we’ll effectively mark data in the cache as “dirty” or “clean” and then go back and forth and over it all to attempt sync with the server and to handle all possible cases that are not even all that clear in advance, since they can’t possibly be. For the most obvious trouble, there is no guarantee as to *which data* changes as a result of any given action so going this silly route of marking dirty data is at best a pretense to solve the problem but certainly no solving it at all. So no, naive doesn’t work any better than lazy above did but it serves at least to highlight more clearly the root of the whole trouble, namely that there are in fact and inescapably TWO data caches on the client: one is indeed the explicit data cache that is held by the Core but the other is the implicit data cache that the GUI keeps in the graphical engine itself! There is no way in which the GUI can show a persistent representation of data without having therefore a cache of that data and as a result, the GUI can’t shirk taking on the full responsibility for the *local* data cache where it can make whatever changes it wants, without however expecting to have any direct access to making changes on the authoritative data cache that the Core maintains.

In a nutshell, the Core aims to maintain its data cache as closely as possible to the server’s view of the world, without caring at all about anything else, while the GUI aims to maintain its data cache as a reasonable guess of the world essentially: as responsive as possible to user actions and as close as possible to what the Core provides. This means that there is really no need to mark some data as dirty and some as clean in either of the two data caches: the one in Core is always and by definition as clean as the client can ever get; the one in the GUI is at best a fresh copy of that in the core and at all other times a… guess. The Core will regularly refresh its full data view by asking the server for a World Bulletin (and then following up through the world hierarchy as relevant), while the GUI will regularly refresh its full data view by asking the Core for what is in view at any given time. Whenever a user action happens, the GUI will promptly provide to the user whatever feedback it can and otherwise it will simply ask the Core to communicate that action to the server. There’s no need for anything further really: whatever the result of that communication, the changes (if any!) or the undo of attempted changes (if any!) or in other words whatever effect the action has or doesn’t have will be obtained anyway as part of the regular refresh of the data done by both the Core and the GUI on their respective caches.

While the above general principle works for all user actions, there are indeed some that are easier to handle than others. In particular, movement is quite apart from the rest, as it’s basically a “continuous” sort of action that moreover needs to have an immediate effect shown to the user. So the GUI will have to balance here the need to synchronize the player’s position with the server to avoid annoying abrupt relocations and the need to keep the user’s costs low as all messages sent to the server have a cost and nobody will be all that happy to use a client that racks up huge costs just for moving about the land. Nevertheless, the great part in all of this is that it’s all clearly and entirely the responsibility of the GUI and so it can be all contained in one single place and none of Core’s concern. The less than great part in all of this is that the actual movement part in the current GUI is still afflicted to some degree by planeshittism 1 and so it will still take some work to figure out a way to make this work, preferably cutting out or at least avoiding that remaining bit of swamp.

Other than the above specific trouble with the movement, there is still some work to be done to implement in detail everything needed for all the other, more straightforward actions. For now and mainly as a basic test, I’ve implemented on the client side just the simplest of them all, the “explore” so that I could confirm indeed that the whole approach works: the GUI reacts promptly to the user command and asks the Core to send the request to the server, the Core packs it correctly and sends it, the server correctly unpacks it and recognizes it as such. For that matter, I’ve implemented already the packing and unpacking (+tests for them) for all the actions, so the next steps will focus specifically on the higher level part of this and first in line, the clientside required bits and parts for performing those actions.

  1. Without even counting all the parts that have been shed already in this area, there’s still a psCharControl and otherwise a psLinearmove that does the actual calculations and heavy lifting but also a psMovementManager that can anyway “manage” only ONE actor at any given time and through a tangled web of back and forth calls from actor to manager and the other way around as well as from other parts to both actor and manager or to actor through the manager as well as to the manager through the actor – the usual PS “style”, really[]

August 12, 2020

What the Fuck, Planeshift?

Filed under: Coding,Eulora — Diana Coman @ 5:21 pm

There’s no other title fitting this. Here’s the priceless context for the question above, context worth not one thousand but 100 000 lines of open source code, at the very least:

gui_inv_2_640.png

The above is the amazing result of trying to make use of all those psSlot and psSlotManager and pawsManager with their drag-and-drop wonder and marvel functionality, a true crowning achievement and glory of open source development. I ask the bloody “manager” class to drag something across the screen, as it claims it does and as a result it… breaks everything else pretty much, as nothing really updates anymore and the thing leaves a trail wherever it goes. But all is well, I’m sure, at least according to the manager and to everyone else working very hard and tirelessly and wonderfully and so on 1.

As I am apparently still naive enough to try and debug even the above sort of madness, I ended up in short order following a back and forth web of calls that are increasingly bringing to mind the way chaotic systems tread their path, ever random when it concerns the very next step, ever building nevertheless the same known shape in the end, as predictable as it can be. To give a clear view of how this goes, here it is: the widget calls the manager and the manager calls then the mouse class that calls back the widget that calls its parent class that calls back the manager that calls -at another time- the mouse class that calls…

Fortunately, those days I get at least faster out of such naivety and optimism and so I stopped just about there and didn’t waste any further time with it but looked instead at some way to do it more directly. I suppose by now it’s not surprising that all that crazy web of shit for “drag and drop” was anyway on top of and to the side of a somewhat less crazy “move with mouse” and then it turned out that even that was spurious and in fact the core class of ALL widgets in that bloody gui even had a method specifically for …”center on mouse” sort of thing – and it even worked! So I made therefore my own “drag” as I had made my own prototype inventory window and my own prototype console overlay and my own seedling for the rest and let the many managers rot and fester in there unused and increasingly cut away from everything until that day when I’ll finally get around to delete the whole mess too and there won’t be any difference other than having suddenly a much smaller client that is however way more useful. At any rate, as a result of this most recent adventure, I stand corrected in my initial opinion that there might still be at least a tiny amount of utility in all that PS code – there isn’t, there never was, there never can be.

As to the current status of those windows and overlays on my list: I have now a perfectly working way to drag stuff about (not yet to drop it but I don’t expect that to be a huge problem, seeing how I am not going to touch any of the PS shit for it, not anymore), as well as working prototypes for both “Console” and “Contents” windows, with a few commands wired in already mainly for testing and poking that Contents view. Everything in those is created from code and without any xml in the loop so that the Contents view for instance can easily create as many slots as one wants, there is no limit of any sort anymore. The logical thing is probably to simply create slots *as needed* and without limit but for now I disentangled (and cut and wrote anew) enough of that underlying widget that has scrollbars – the scrollbars are useful but the design of it otherwise required a bigger hammer to bend into something usable in the least. As you might notice, I even gave in and added arrows for the scrollbars! In any case, all the images and graphics and colours are just for testing for now and I’ll gladly use better ones /let someone else design any window whatsoever. For now, here’s how the prototypes look like (in order: a test with adding and replacing stuff in the contents view, based on id of the *underlying* object instead of id of slot and other madness; the successful dragging of ‘shrooms with icon and everything else):

gui_inv_1_640.png
gui_inv_3_640.png

For the next steps, there would still be first a bit of cleanup around those latest parts and assorted cuts made for it. Then I’ll have to see if it makes perhaps more sense to get back one round to adding more working parts on the data side + communications and then let that drive any further development of the GUI itself. At least I’m now quite satisfied that I’ll be able indeed, one way or another, to add to the GUI what may be required, even if some parts are very likely to throw some more wtf of the sort illustrated in the very introduction to this and eat as a result rather more time than I’d like to spend on them.

  1. It could never not be great and wonderful anymore either, there is no such thing as something *not* being well, nowadays it’s either great or otherwise forgotten or simply not mentioned for it’s surely the mentioning that is causing the problem in the first place, obviously.[]

August 5, 2020

#eulora Logs for Aug 2020

Filed under: #eulora_irc,Logs — Diana Coman @ 5:06 pm
Day changed to 2020-08-05
feedbot: http://ossasepia.com/2020/08/05/you-will-have-to-push-my-buttons/ << Ossa Sepia Eulora — You Will Have to Push My Buttons [17:06]
Day changed to 2020-08-10
feedbot: http://thewhet.net/2020/08/close-encounters-of-the-costa-rican-kind/ << The Whet — Close Encounters of the Costa Rican Kind [01:37]
Day changed to 2020-08-12
feedbot: http://ossasepia.com/2020/08/12/what-the-fuck-planeshift/ << Ossa Sepia Eulora — What the Fuck, Planeshift? [19:32]
Day changed to 2020-08-20
feedbot: http://ossasepia.com/2020/08/20/the-gui-the-core-and-the-data/ << Ossa Sepia Eulora — The GUI, the Core and the Data [17:56]
Day changed to 2020-08-31
feedbot: http://ossasepia.com/2020/08/31/in-euloran-moving-updates-inner-slots-and-outer-wheels/ << Ossa Sepia Eulora — In Euloran Moving Updates: Inner Slots and Outer Wheels [21:44]

You Will Have to Push My Buttons

Filed under: Coding,Eulora — Diana Coman @ 3:02 pm

Until such time that you make any buttons of your own at least, it’s now all settled, clear and without a choice: on all Euloran soil, it will really be my buttons you’ll have to push 1 and my views you’ll have to use and my winPAWS 2 that you’ll look at. For there was/is barely anything useful in all those 100 windows that were each terribly important on their own, each with their own layout xml file and own hand-rolled loader and own parser and own further numerous attendant misfortunes that are inevitably linked back to that mighty struggle of trying to have a singleton manager without admitting however of having any *specific* manager. It’s a riot reading the code and the famous “software patterns” and even all the Object Oriented paradigm in this obvious key. It’s even funnier now as the end of the swamps is otherwise in sight and as the intelligent idiots are out of my way and staying there in their narrowly delimited circle where they are taking over the world, I’m certain, only it’s each of them taking over their own world but that tiny detail is entirely unimportant and can’t possibly matter, can it? They are after all solving problems with code and moreover solving “problems” picked and ranked based first and foremost on what they are familiar with and the sort of solving that they have done before since that has to be the best way – the more independent, upright, sane and intelligent way. Not that this has anything to do with it being also the only way that is still in the least open to them, no, absolutely not.

Back to that fast growing life of Eulora, the dive into the full depths of PAWS was essentially successful if not lacking in crashing, segfaulting and downright maddening experiences: the whole thing is not unlike a carefully constructed castle of sticks that stands for as long as it’s untouched and then unravels entirely at the merest movement of air around it. There is in fact already a set of “basic” elements and those 100+ windows are on top of that but even those “basic” ones are at times anything but basic. The most screaming out loud example of this would be the humble title of a window/widget/whathaveyou – in order to show *any* title (as in text, a few letters, nothing more), the “widgets” require a border and that requires buttons and styles among other things and those in turn require preferences and all sorts that further require the requirements of requiring required requirings… Why does the title part require buttons or borders or all that? I suspect it’s because someone was solving there with his code a lot of problems that I don’t have! So I took instead the smallest thing that I could find, trimmed it further and added it directly to the core “pawsWidget” class so that any damned thing CAN now show some text as title without requiring anything more than the… text itself! Shock and horror, I know, just look how violent I am with titles and buttons over here!

Moving paws on the path further, I started to simply write the code for some generic “views” – the sort of windows that can be used for a purpose and otherwise displaying whatever information is relevant. At first, this ran fully into all sorts of intricate weird: the show that won’t show, the click that won’t click and other such crazy stuff from working with the castle of sticks where everything interacts with everything else and that results in a whole ritual -where order of steps is important, too!- necessary for achieving the tiniest effect. Disentangling all that was no pleasure but it’s still the fastest way I know of to get to the point where something useful can be done with the whole mess and it worked with this mess as it has always worked with any and all messes I ever encountered. As a result, I am quite confident now that I *can* make my views, windows and overlays in a reasonable amount of time and *without* a whole lot of clutter sticking to them.

For the initial practice, I first cut to pieces that “bar” at the top and then put back together only a skeleton of it, as an overlay that has so far only the quit and help buttons – and those are my buttons indeed, made through my code and in a more direct way than the original entangled messes. The reason why the whole bar itself is still there as a thing at all is that it holds also quite a bit of the keyboard interaction part so there’s more that needs to come away before it becomes fully clear if it comes off entirely or not. At any rate, otherwise I changed that pawsManager to actually act as one and therefore I have now in place the building blocks to allow the desired approach of “one window at a time and otherwise overlays”. This also cut a lot of crap dances around all sorts but mainly in the sense of not using a lot of code, not yet in the final stages of deleting and discarding it too. For illustration, here’s the new “menu bar” overlay and the confirmation window that a click on the Quit button made appear:

gui2_4_640.png

Once I had those buttons showing and working as I wanted them, the next step was to add various bits and pieces that arguably come in handy and could at least build on what I had so far. So I enhanced that minimal “helpwindow” of last time, as it’s in my view the prototype for a generic view aimed to show structured text 3: it has now a title and there are also functioning scrollbars that use Eulora’s own icon as tracker – I rather like them; the +/- signs for opening/collapsing a topic get shown now with their own icons in the skin.zip file; there’s also further experimenting making sure that both background and text colour can indeed be set as desired:

gui2_1_640.png

I’ll have to note here that the above is still not giving a damn about stuff like “borders” and stuffing buttons everywhere, from title to sidebars and anywhere in between. To be honest, I personally prefer by far the transparent and minimalistic windows and I make a half-hearted exception only for text really (as it’s rather easier to read when it’s the traditional black on white or gray on black). So if you’d really, really want those windows to have anything further, please say it sooner rather than later, as left on my own I doubt I’ll find much reason to add even “title bars” as separate things, let alone stuff like border-this and border-that or decoration-here and decoration-there.

For further practice with making whole windows really from scratch rather than starting with a previous overgrown thing and cutting thorns at all steps while still remaining with a crooked trunk, I made also an “Info” view that is meant to show an image + name + description for anything in the world: it’s barely a page of code and it even sets its size depending on how big your screen/eulora is, aiming only to maintain the ratio of its minimal size. The image gets indeed re-sized to fit exactly the space available in its side of the whole view so that’s perhaps not ideal but it can be changed for sure. To fill it with something for testing purpose, here’s the very info on Eulora itself, first in the transparent version and then with the black background for that half-hearted concession to showing text on a non-transparent background:

gui2_2_640.png
gui2_3_640.png

With the above done, my current list of generic views (aka windows+overlays) reads like this:

  1. Command line – TO DO. This is in my opinion crucial as it’s meant to be the game’s console basically, the only place for the player to enter commands and thus be able to do anything, whether there is a button for it yet or not. This would be an overlay, I should think.
  2. Confirmation – prototype DONE. This is a very basic yes/no type of window, aka one question + 2 buttons, modal thing. The current prototype is perfectly and fully working, if entirely transparent. The wiring of the buttons is now mine too, entirely circumventing the several layers of passing the buck that used to be “the way this is to be done”. I don’t know if there really is a need for any sort of other “view” as such – if it’s just a text message, it can still be shown either directly on the screen (that fading sort of thing, dropping down as it faded) or otherwise in the console/command line thing above, I guess.
  3. Waiting – prototype DONE. This is meant as a placeholder/information for when the game is not available/unable to display the world as such. It simply takes over the whole game window and it displays an image + a label/text at the bottom. The prototype is fully functional and even wired in its correct place aka displaying at the start while the client is waiting to obtain from the server the most basic stuff such as who am I, where am I and what does this world even look like. I kept that boceto drawing as I quite like it (even more so than the “splash” thing).
  4. Info – prototype DONE. This is meant to show image+name+description (or any subset of those) of anything in the world.
  5. Contents – TO DO. This would show everything that is “inside” any given object in the world. As such, it could show the contents of some container but equally well the player’s inventory or the equipped items or a storage or the contents of an exchange of any sort. In my current hazy view of it, this will simply show as many “slots” as required, each with their own icon + text (e.g. stack count and quality or similar) + tooltip (to show the name of whatever is in there).
  6. Exchange – TO DO. This would be made out of 2 Contents essentially, with wiring as appropriate for whatever specific exchange is shown at any given time. Basically the “inputs” would be the 2 items whose contents are to be shown on each side of this view. In my opinion and just as an example, this can even work to provide a GUI for activities such as “equip” since it’s an exchange – stuff from inventory being moved into equipped and the other way around.
  7. Management/Ownership – TO DO. The details of this are not very clear to me currently but as I gather that there will be various types of managing involved (e.g. jobs or land), I’ve added this to the list as a generic window that can hopefully be made to cover adequately the management of whatever is needed. I’d say there is still time to figure out this in more detail and there’s no rush – it’s on this list as a type, not much more so far.
  8. Skills/Self – TO DO. This is quite hazy too but what I mean here is mainly a view that is able to show also things that require something other than image or text: perhaps bars/percentages or the like. I am not fully clear on this part yet but there’s certainly time for it to clarify.

As next steps, I would push this a bit further still to fully transform that “helpwindow” into its intended generic structured content view and make otherwise at least a prototype of the Console/Command Line and Contents generic views. The Contents one is quite important because it means figuring out all that slots business and dragging stuff from one place to another, which is another potentially big chunk of this. Hopefully as part and parcel of that, I should be able also to finally delete another pile of useless code, as it ends up entirely stranded. In terms of specific GUI bits and icons, the more I work with this, the fewer of them I want in there so do let me know if there are *any* parts that you absolutely want in there as otherwise I’m afraid I might easily end up ditching just about *all* of them and have the whole “skin” consist in something like a plus, a minus, a quit icon, a help icon and a tracker for scrollbars, not much else really. Of course, anyone can otherwise ship to the client any .zip file with anything at all but the default client will not use anything else and keep those windows as minimal and as invisible as possible, by the looks of it.

Other than the above, let me know also if the approach of “generic views” makes sense to you and whether you’d like any others added to that list, even if just as general types, to be perhaps fleshed out (or discarded) later, as everything gets into more concrete shape.

  1. Heh. I know.[]
  2. Well, they’d be windows except when they are overlays and otherwise they are made still on top of and with various bits of the paws that apparently would really, really want to be of some use, if only it hadn’t been so thorougly misdesigned and abused by means of pointerfuck…[]
  3. By structured text I mean here text that has a hierarchy of parts that can be shown/viewed separately and allow navigation through a tree of contents.[]
Older Posts »

Work on what matters, so you matter too.