Decision time for top-of-level behaviour!Finally got around to making some decisions about Top-of-Level behaviour, and implementing it as best as I possibly can.
In short,
the Top Pixel (i.e. Y = 0) is now a virtual downwards-forcefield, much like the sides are one-way forcefields.
Here's how it works:
If a lem somehow reaches (Y <= 0), they cannot be assigned skills. So, the forcefield nudges them downwards into the level by 1px, regardless of whether or not there is terrain there; this is so that the lems remain visible, active in the level, and assignable-to. Pending extensive testing by people more determined to break the game than me, this situation is currently almost impossible* and should never happen anyway.
Meanwhile, any pre-existing terrain pixels along the top row are virtually extended upwards, so that Walking lems encountering these pixels will act as if they've met a wall, and turn around (this can be regarded as a side effect of the force-field, essentially preventing access to the topmost pixel).
Brack-based construction skills (Builders, Platformers, Stackers, Ladderers) are prevented from adding a pixel along the top row: Platformers and Ladderers can't get up there to do this anyway, whilst Builders and Stackers are cancelled just before they place a brick along the top row.
Freezers have additional top-of-level checks to prevent Frozen lems accessing the top by stepping out of the partially-erased ice cube (a current bug in 2.7.3, now fixed). Additionally, Freezers' bottom-of-level checks have been re-implemented, simplified and improved. So, Freezers are once again assignable anywhere in the level.
Jumpers, Swimmers and Gliders-in-Updrafts are nudged down to keep them within the visible level area (and, to keep them assignable-to).
Climbers and Hoisters are cancelled (and turned) mid-action before they reach the top.
Ballooners bob around at the top (they are turned by the forcefield sides, and nudged down by the forcefield top) until the balloon is popped, as per current behaviour.
Fencers are also cancelled once they reach the top of the level.
All other skill actions are unaffected by the forcefield, since they are either sidewards, downwards, or in-place oriented and therefore don't (necessarily) interact directly with the top pixel.
I'm about 99% sure that this is as glitchproof as it can possibly be, and all skills/actions behave as you might expect given that the top pixel is now a non-solid forcefield. If anything does come up during testing/gameplay that seems broken, I'll do my best to fix it.
CheckLevelBoundaries and various other parts of LemGame have been refactored for readability and to implement the above - see Commit 70b045b25 for changes.
*
There are currently 2 known ways to get a lem to Y = 0:
1) Assign a Freezer such that any nearby lems will ascend out of the Freezer cube, and thus arrive at Y = 0. Possible fixes: i) move these lems away horizontally instead (could cause terrain phasing bugs elsewhere), ii) apply Blocker field to lems in the "Freezing" state (more preferable since Freezers are often used for this purpose anyway, but doesn't work for falling lems), iii) disallow Freezer assignments at (LemY <=11) (easy but too heavy-handed, and won't work for Slowfreeze lems), iv) erase top pixel of Freezer cube if LemY (<=11) (easy, consistent with other construction skills, looks wierd), v) set an ice cube map wherever there is a Freezer, handle accordingly (most versatile solution, but more work and more rendering load).
2) Pre-place a lem outside the level area. This has been addressed in Commit d8df70e5b - if a lem is pre-placed outside the level area on any edge, they are automatically saved!