My coding project, part VII

After a long break

My pygame project has advanced more than you could guess by the amount of posts about it. Mostly I've been fooling around with the background stuff, not much of what I've done will be directly visible to the user. Then again, if you look at the previous post, quite a bit has changed.

The last time we got to a part where the game world and its sectors were created and a map based on that was shown to the user. At this point there's absolutely nothing to play so I refuse to call it a "player". The map could be opened and closed and the game could be (un)paused. Basic stuff but nothing spectacular.

Next steps

In the first iteration of my project the game's view was fixed and the ship flew around freely. The first thing I had to do was to attach the viewport to the ship. So the ship would always be in the center and the viewport would scroll around the sector, following it. Because the sector would always be (much) bigger than the viewport, there was no sense in rendering objects that weren't inside the viewport's area. Therefore the sector would need a data structure for its gameobjects that would give all the necessary information to achieve this.


The idea of a QuadTree is that whenever a single cell's capacity is used up, it subdivides into four subcells where the objects will be redistributed. And so on and so on until the maximum depth of the tree is reached. No explanation I give can be better than the existing ones so you can read more from wikipedia, for example.
The necessary explanation is that I implemented my own version (or a part of it) of a QuadTree. At this point, when its mere existence is enough, all the sector's contents is inserted into the qtree. The aforementioned need of finding all the gameobjects inside the viewport was the first real use case. Because the sectors are squares, all my gameobjects are basically squares and all the quadtree cells are squares, everything can be solved with pygame's colliderect methods.

def get_contained_objects(self, rectangle):
  contained_objects = []
  if self.gameobjects:
    for gameobject in self.gameobjects:
      if rectangle.colliderect(gameobject.get_rect()):
      if self.top_left:
  return contained_objects

What's most important in the code above is the rectangle parameter, which is the surface area of the viewport. That viewport is calculated around the centerpoint of player's ship. While working on that also the offset of the ship from the sector's 0,0 point is calculated. That offset is needed to render all the other gameobjects related to the ship.

Maybe (most likely, even) I explained it a bit funnily, but what can I do. Solving this small set of problems took a few evenings and sessions. I was pretty proud when I finally got it working properly. My biggest problem had been that I thought of it way too complicatedly - yet again.

Return of the GameObjects

Of course I needed something to be rendered on the screen, so that I could check the basic functionality of my QuadTree. In  the beginning I had those three subspace pirate ships I mentioned a related post or three ago. In addition to those I wanted to return the Asteroids back to the screen as well, but better than the last time. While I was on it, I'd test the insert and division methods of the tree with some randomly generated content.

My old asteroid code was almost directly transferrable. Mostly I added some more randomness to the init. Based on a 2d6 toss, a result between 9-12 spawns an ice asteroid, otherwise a rock asteroid. Anohter 2d6 decides the size with the old familiar small / medium / large / enormous options. The material affects both the color, the randomized mass and the rotation speed. Those asteroids that consist of rock are both heavier and slower than the icy ones.


Redoing the camo pattern

Yesterday evening I brushed a new camo pattern on the Turkina. I have to say that the result is still suboptimal but better than the previous attempt. Mostly that's because I had to beware of the preexisting detailing and such. Had I started all new, it'd been (hopefully) much better.

I think I'll apply a brown wash on this one, just like I did with the previous four OmniMechs. Unless I run out of paint. No matter what I'll report about that next year earliest, because I'll be on a vacation without pieces, paints and all those things.


Ongoing tiny fixage

December and all the other random things, also known as other projects, have eaten most of the resources from the 'Mech fixing. I've also had little inspiration for this for some reason, so other projects have actually had the chance to steal my time from this stuff. Mostly I've been educating myself about Alex Denton's adventures or had the PyCharm running, but more about that in a couple of weeks.

A guinea pig

The Assault 'Mech of the Jade Falcons - Turkina - that might end up being the Cluster Commander's ride, needed some repainting. The problem with this one and the others painted in the same batch was that the Dark Green I used (on top of black, no less!) was way too dark. Something needed to go over that and I chose Sick Green (Game Color 72029) from my storage and started brushing around.

Turkina before

Turkina now

I didn't even remember (or realize) how awful my paintjob had been. Almost the whole can was repainted without a rat's behind given about the pre-existing excuse of a camo pattern. As my next task I'll redo the pattern with semidark gray and fix the jade highlights.
Why didn't I repaint them as well while I was at it? Because I really liked the Galaxy insignia on both sides of the torso, destroying them would've been a huge shame.

Based on my experiences with this mini I'll put the rest of them in the grinder the same way. As long as I get this one done out of the way first.


Quick fixes III/13

Going through all the old minis

I was  bragging earlier that I'd go through all the OmniMechs I had assembled and painted years ago and redo their cockpits. Sometimes I'm a man of my word, so here's a quick report:

The beginnings of the fifth Trinary

Numerically my smallest and therefore easiest to fix was the set of four Points of my Aerospace Fighters. It really didn't take long as the cockpits are tiny and there were only four of the fighters to be fixed. In the more or less distant future I'm going to need to work on more of these, but when do I have the time for that? Not soon, I guess.

Two-legged monsters

While I was painting the cockpits I also separated the broken minis for fixing. I had also once accidentally bought an old sculpt of a Summoner that was sold as a D variant, and that was a horrible piece. That one I didn't bother touching at all as I'm going to reuse it as random ruined pieces on the bases of other, proper miniatures.

This jungle of 'Mechs isn't too clear so I'll show the pieces in a few separate rounds. First you'll find a Nova prime, Cougar prime, Cougar C, Ice Ferret and an Cauldron-Born prime. The C-Cougar had lost its right arm at some point, so it marched on towards the Mech Bay and restoration.

Next up: heavier units. First a Mad Dog, Hellbringer, Summoner as primes and a Summoner B to round them up. Each was in prime condition and without anything to complain about. Unless you want to complain about the painting decisions I'd done all those years ago, that is.

In the Assault class I had an Executioner, Gargoyle, Dire Wolf, Turkina and Warhawk, each in their prime configuration and then my absolute favourite: the totally, absolutely sick C-variant of the Warhawk (2x LPLas, 2x ERPPC, flamer, TC). Funnily enough the first four were those I had intended to repaint because I had painted them with too dark a green. I just didn't have the time to repaint them at this point, so that had to wait for a while still.

The first Timber Wolf of my Cluster (I've got two, because I like them but no more than that because they're not supposedly typical for Falcons) is naturally a prime, like so many others:


My two Novas were armed with somewhat lighter equipment than the rest of the Cluster, with the idea "run quickly to the grinder and drop the Elementals". I admit that it can fight against the very idea of a Talon Cluster's description so I'm prepared to set them up later with Heavy/Assault class 'Mechs. The point was, that personally I found the fast Omnis much more likely to be found in a Nova.

So here they are, first three Stormcrows. The ones at the edges are primes and the one in the middle's a random custom.

The next set had three Kit Fox primes and two Fire Moth primes. I can't even rememeber if at the time I ordered these there were any customizing options avaiable. Or if customizing had been even sensibly doable.

The Nova and Ice Ferret that you saw in an earlier pic were assigned to these Novas in addition to these eight.

Some damaged ones

Critical Hits had been delt out more than just once. The reason to that was of course in my own assembly methods, because the custom joints were done before my Dremel period and generally however. The first sad example is my early Hellbringer A, that got its right arm AC made from a topz pipe. This one had taken two criticals in its both Lower Arm Actuators. With some pinning they'll stay put in the future.

The second Timber Wolf of my Cluster is an A variant and it had lost half of its left arm. Just like the Hellbringer above this one had taken a critical hit in its LAA.

Luckily only three Points had lost limbs. Oh, and that one pitiful excuse of a Summoner that had gone in two pieces from its hip. But we don't talk about that because it's going to be replaced completely.
The fault in these breakings is only mine and that's why I'm going to fix them to the best of my abilities. Well, I'd do that anyway, even if it wasn't my fault.


Some finished OmniMechs II/13

Finishing touches

After my last post about these 'Mechs I finished up painting the numbers and insignia. These pieces were practically done two weeks ago, I just didn't have the time for photos or this text until now. Maybe these aren't the best photos I could've taken but it happens. I can take new ones if needed.

I thought I'd continue by fixing all the cockpits of my old miniatures with red paint and then get the rest of my Elementals done. Last time I also complained about breaking my airbrush but that wasn't a huge issue after all: the pipe that goes to the pain pot just broke. As a result that pipe is now three, four millimeters shorter than it used to be and that's not a real problem, I just can't empty the paint pot by spraying anymore. Replacing that would be easy.


I counted all the miniatures I have finished so far. A grand total of thirty 'Mechs with four Hellbringers (two of them in alt.conf. A), which is fitting for Jade Falcons. Each unit has an individual number and its own place inside the Cluster. This is something I hadn't really pondered on at all so far, unless you count my "maybe that Turkina should be in the Command Star" as real pondering.

Planning has to be started at some point, so why not now? These four ended up being in the second Star of the Beta Trinary. There's nothing magical or special about this, just plain randomness.

3 - Gargoyle

This one carries a sort of an (Ultra) AutoCannon and two lasers. All the weapons are just slammed there, so I've got no MechLab explanation for this. Obviously this is not an official config.

52 - Summoner A

Gauss Rifle, LPLas, SRM-6

26 - Hellbringer A

2x ERLLas, UAC/5, LRM-20, NARC, ERMLas, 2xMG, BAP

17 - Mad Dog C

2x Gauss Rifle


A 350 ton Combat Drop

Game on!

Two or closer to three years have passed since our previous BattleTech game. This would be a party where my recently worked on Jade Falcon OmniMechs were not going to crash in, other than being ogled at before the game itself. This time the limelight would be stolen by my underrepresented (and miscoloured, considering the scenario) Elementals.

We had tried the infantry in two earlier games: a couple of Elemental Points against some IS 'Mechs in one game and some random, badly trained normal soldiers (they were more like Volkssturm, even though my greenest of the green rifle squad alone blew up a Marauder with a beautiful critical hit). The idea of playing an Alshain Avengers themed game had been simmering in our sick minds for a good while already - now we were going to try it out.

The background in a nutshell

At some point in the Clan Ghost Bear had conquered planet Alshain from the Draconis Combine. Former members of the Alshain Regulars were plotting on revenge for a good long while. At some point these people, now known as the Alshain Avengers, saw their chance to strike and to "liberate" their planet from the "oppression" of the Ghost Bears. Even the intel told them that there were no Clan 'Mech units on the planet. What could be better?

Artwork © Punakettu

Operation Batu

In a way it was all correct and truthful. Nobody just didn't know that there were some units sitting on the planet, after all. To our great pleasure we're talking about an Elite Zeta Galaxy - which consists only of Elementals.

The Zeta Galaxy

Based on a quick checkup the Zeta has four Claw Clusters. Each of them has five Elemental Trinaries. And each Trinary consists of three Stars of five Points, which all have five individual Elementals in them. A quick countdown (4*5*3*5*5) tells us that the headcount's 1500. Yes, one and half a thousand two-and-half-a-meters tall angry, armored one-ton dudes with Jump Jets, an SRM-2 launcher and a small laser.


A known result

Being lazy I just quote a couple of things from Sarna to get this thing rolling:

"The regiments suffered heavy losses while still in orbit and were completely destroyed after landing on planet in October 3062. After hearing of the betrayal of the Avengers, Coordinator Theodore Kurita ordered the death of all member of the Avengers who invaded Alshain, should they survive the invasion."

"Operation Batu was an unauthorized invasion of the planet Alshain, held by Clan Ghost Bear in 3062. The strike was mostly planned by the Black Dragon Society. Three of the four Alshain Avengers regiments attempted to retake the world for the Draconis Combine, and were obliterated by the Ghost Bears."

So, the invaders were cut to shreds in real life, so how could our game end any other way but still remain entertaining? By implementing a part of the whole show, of course.

We ended up giving the attackers the following list, mostly based on propriety and existing gaming pieces (so the red DMCS miniatures were on the top of the pile): Dragon, Hunchback, Jagermech, Mongoose, Clint, Panther, Assassin, Jenner. The IS players could share the toys however they felt like but so that if you wanted a heavier 'Mech, you got nothing else but if you wanted two, you got somewhat lighter toys.

All in all the assault was going to weigh in at 350 tons and the equipment was chosen with the scenario itself in mind. Short range weapons were considered more important than insane LRM setups. Flamers, BAPs and some other systems were also locked out.

These madmen would be facing a Trinary of hidden Elite Elementals. In the planning phase we had assumed that my fifteen Points would not be enough and because the history has to survive our sillinesses even if we have to force it, we had prepared two extra Binaries of Elite Elementals, to begin with. These would be carried to the battlefield with a Star of Svantovit hovercrafts. The hovercrafts were not supposed to linger on the battlefield but to shuttle the Elementals in, but of course they could fire at will if someone was stupid enough to be caught on the wrong side of the weapons.

Both teams were set up with a gut feeling and as the Battle Value 1.0 system told that my Clanners would be a bit weaker, we had decided it was going to be just fine as it was.

How it went, more or less

I took photos of the rounds however I remembered. There's no way I'm going to try to write a magnificent APR but maybe deliver the feeling in the about 8-hour game instead. As is more than customary, the efficient playing time was much, much less than that, thanks to the fact that it'd been such a long time since the last game and that we hadn't even met more than once since it. Oh well, this always happens anyway and we spend at least 50% in bsing, who am I trying to fool here? :p

Typically we used two maps side by side, both had some bumps and vegetation to provide a bit of an equal footing to both teams. To emphasize the absolutely chaotic (automatic fail) Combat Drop we decided that during the Drop the map would be a toroid. No one could fall out of the map. Sadly no one failed that badly or that much in the wrong direction, but at least we had prepared for it.
The pilots fell like autumn levaes, some more and some less to where they intended to. Even more sadly, just a couple of them fell.

Let it be noted that even though I used numbered subheadlines, they don't represent the going of the game 1.1, because I didn't remember to take enough photos - nor can I remember what happened and when. Worry not, just a couple of rounds are missing at worst, anyway.


After finally getting up the invaders started walking to safe-looking directions on the otherwise empty map. Mister d's Jenner just happened to walk into a middle of some Elementals, to my great amusement. Naturally I succeeded in my Swarm attack and started beating the tincan as if there was no tomorrow.


For some reason these little people swarming around the surprised Jenner succeeded in kicking the paranoia gear of the Spheroids to a new high. They all started shooting around like madmen, trying to ignite all the foresty hexes they could (or could not) reach, in hopes of flushing out my armored defenders. Not the worst idea they had that day.

My Elementals kept on tormenting the Jenner and managed to ram a couple of SRMs into the internal structure and blew up the missile bin with a critical hit. That was indeed quick. Another sneakily but cleverly concealed Elemental Point stopped the Dragon on its tracks.


The Elemental Point that was shooting at the Jenner/Assassin on the northern map was jumping around to make their shooting more difficult. A Jagermech was slowly stomping to help but as its new course took it by a shore, it also got jumped on by a hidden Point. That way it also avoided another sneaky attack, but I got to attack it anyway, so I wans't complaining.

Being a coward the Dragon's pilot bravely turned his tail and fled, leaving his friends to work with the Elemental issue. In the Southeast corner a Mongoose had been running a bit too fast and had left the best protection of the Hunchback - and found itself in a surprising crossfire.


To the west the Panther found more hide-and-seek champions peeking from a nearby forest, in the southeast both the Mongoose and Hunchback were attacking like the french while my Elementals were leaping after them. The Point that surprised the Dragon swarmed the Clint in the middle of a raging forest fire while three 'Mechs were trying to shoot them down.

T's Jagermech was running away but in his panic the pilot left the lightly armored back totally open - to three Points of  Elementals, one of which had sadly run out of missiles already. Very prettily one of the shots went through, to the inner structure (can't really remember if it went through the torso or an arm) and cooked the AC ammo. Those two missile salvos are very pleasant tool but they are spent damn quickly. Though in all fairness I have to say that these guys make the Small Laser pretty handy after all, because they hit usually quite a few times per round even if there's only one guy left in the Point.


North side was practically cleared now, so all three already revealed Northern Elemental Points could relocate towards their next victims. At this point between them and the red machines was a pretty open space. I decided that the interlopers get a chance to do something honourable and accept their fates.

To the south my Elementals kept pushing. A bouncing Clint actually managed to shake the swarming Elementals off its back in the middle of a firestorm. So far I had revealed six out of my fifteen Points.


What a surprise. The honourless freebirrth barbarians had no guts. My Elementals resumed their attack. I had decided to pull my two Eastern Points to join their friends at the tiny hill in the center. The plan was to surround the 'Mechs and mow them down while allowing my troops to use their greater number as their own protection. Besides, the pilots of the Hunchback and Mongoose were, unlike their comrades, their eyes open and fingers on triggers.


It was getting somewhat late in the real world, so I raised some of my still concealed units. Handily I now had three untouched and fully armed Elemental Points almost directly behind the Hunchback. One of the Points I had just turned towards the center hill got rererouted towards these two old targets. My idea was, still, to set up a good old-fashioned beating. Especially if it was done in the always classy "many against one", because that's something that Elementals are allowed to do.

My attack to the center bump was succesful in a way, as I captured it but all its previous occupants had fled from my onslaught, firing wildly to the skies. Oh well, it was all the same to me, to keep my troops assaulting, as long as my enemies were going to be wiped out to the last man, woman and piece of scrap metal.


All the fighting had been centered to two places. In southeast my Elementals failed a swarm attack for the first time, but that Hunchback still got four Alpha Strikes. For some strange reason both these pilots decided to concentrate all their firepower on the same missileless and only slightly damaged Point. Not that it mattered, they couldn't have killed anyone in the next five rounds in any case. At this point the Mongoose had had its right leg's all actuators blown away and its engine had been hit once as well. The Hunchback took a savage beating as well, but nothing extremely serious yet.

In the west the light show provided by four BattleMechs was undeniably beautiful and decorative, but nothing else. My Elementals kept bouncing back and forth and pointing with their flashlights (those aforementioned Small Lasers). It's pretty telling that those tiny lasers did constantly much more damage than the big weapons on the 'Mechs.

Final round

On the final round (it was late and I had things to do, places to be in the early morning, sorry!) my Elementals kept pressuring the attackers who were fighting for their dear lives. In the southeastern corner my Elementals were only a round or two away from a total annihilation of the intruders. I don't really believe it'd taken more than that, the tin cans were in a bad shape.

There were at least two Points somewhere in the north, waiting for some action. Why didn't I raise them while I got the others out of hiding? They were way too far away from everything to be even remotely useful, especially when I really started going at the freebirth scum.

You can see in the photo that one of my Points was pretty well damaged (but still decently useful) and another, with clearly less time on the field but still a PPC bolt captured in someone's face plate. I'm the first one to admit that I wasted a sickening amount of time due to my bad markings that made me work on "who is who and where and when". That's something I hadn't thought of in advance and my unit handling routines that I kept updating on the go weren't too optimal in their first two or three iterations.

Ending mumblings

Let's just say that the d6-luck was simply incredible around our gaming tabe that Saturday evening. My "this many will hit" throws were generally very good, especially for the SRM salvos. My dear enemies on the other hand had huge problems and great difficulties hitting even the planet itself. One telling example is one of my first Elemental Points: for many a round there was just one guy left with one single hitpoint - and they still couldn't get rid of it, even with concentrated fire from many 'Mechs, repeatedly!

Then something like that Panther hit with its PPC twice in the whole game. And the mighty Dragon, who spent most of its game emulating a static turret in a corner, didn't do much better with all its arsenal through the game. Best (or in my opinion, worst) action was offered by Hunchback and Mongoose who were huddling together in the southeast corner all the time, they shared more pain and death than all the others together. All in all I lost one full Point and a handful of individual Elementals, still less than a dozen.

I had assumed that if we had kept on playing further into the night I would've been forced to call for my reinforcements. Before that I would've torn at least those two 'Mechs to shreds from southeast and maybe one or two others from the west. Had the dice kept working the same way all night, maybe I'd killed them all single-handedly.

One of the conclusions we came to later in IRC is that those poor bastards had few chances. Staying close to my units ended up in swarm attacks and from further away they wouldn't have hit even this much. My suggestion - voiced afterwards of course - was using the "Zoom & Boom" immortalized by some MiG-pilots. At least that way they'd made my hitting a bit more difficult instead of just walking a hex or two which doesn't really do much.