Rules and apps come second. First is finding an army/faction that you really love! Here’s some videos to help you decide:
Hard to play a game if you don’t have the rules…and there are a lot and they’re spread out across multiple locations.
Apps:
Free Army Building Apps:
This section is the most opinionated and honestly the least important. Find what works for you and your needs. None of this is by any means truly necessary and I’ve just found these things work for me and maybe they will for you too!
I personally prefer non-Citadel products. No real reason. I just prefer The Army Painter as they’re a solid budget option:
Similarly for primer, with horde armies, you can go through Primer quickly so I prefer non-Citadel:
Again, for horde armies, you go through a lot glue too, so these $10 20g bottles are nice: Loctite - 20g Super Glue
Again, these are just budget alternatives to Citadel’s products. Citadel works just fine.
For the following, you could use anything, it doesn’t much matter:
Finally, the most unnecessary and ridiculous splurge spend: Fancy dice from Baron of Dice
Q: What’s a Faction? Codex? Index? Detachment?
A: First, “faction” is what Warhammer calls the different armies, chapters, etc. For example, Tyranids are a faction. Blood Angels are a faction. There is more nuance for factions like the various Space Marines but you probably get the idea.
At the start of the 10th edition of Warhmammer, each faction starts with an initial set of rules, called their Index
The Index contains their Army Rule and a single default Detachment. With only one Detachment, if you choose that Army you get that Army Rule and Detachment Pair.
As time goes on, each army gets an updated rules book which replace their Index rules, called a Codex. A Codex (generally) contains more Detachments, which are the styles of play for a faction, and has some rules updates to their units.
When you pick a faction, you get that faction’s Army Rule. Then you get to pick one Detachment from among their available Detachments. If your faction’s Codex is not yet out, this generally means you have just one Detachment to choose from.
Upcoming Codexes in Summer 2024: Adepta Sororitas, Genestealer Cults, and some unknown “Redacted” Codex!
NOTE: Exceptions of course exist. Some factions got Army Rules changes (e.g. Death Guard) or even new Detachments (e.g. Drukhari) before their Codex came out, as they were needed for balance.
]]>I’ve been working to finish (roll credits) on some unfinished games lately. I personally get overwhelmed if I have too many “open threads.” Too many unfinished books and games and I get stressed; as in, around three. So as I started finding games I wanted to play, I found myself needing to finish some (damn) games first. Here’s a quick review of some games that were stuck in my In Progress queue for too long.
What HAS NOT been said about The O.G. FPS?
As a kid I only got to play the first level bc my introduction and only initial experience PC games was a demo CD that my grandpa had on his computer. So basically, I never got around to actually playing Doom.
It was basically free on PS5 so I finally got it. Which is honestly hilarious given that it’s been ported to EVERY device imaginable and I could’ve played it in True Fashion a thousand times, but no, had to wait until it was available on the most-overpowered dedicated game-machine in 2024 to finally play the most iconic video game in existence.
It was great. Only the second to last missions in the fourth/extra episode “Thy Flesh Consumed” was a bit clunky as they went a bit too far with the “puzzle” aspect of the levels.
A couple of design aspects that I especially liked are:
Review: 10/10 still GOATed duh
Fuck. This. Game.
Story? Fine; maybe good. The use of light/dark got super derivative but one could also say it’s meta.
But OMG the gameplay is absolutely atrocious. I really wanted to actually finish the games on my list, and not just give up on them but Alan Wake took every ounce of my will to actually get there.
I’ve never wanted a game to NOT be the kind of video game it is and instead be any other form of interactive media.
Review 0/10. Pure Hatred
While it starts with a strong framed narrative and a good first two acts, it fully falls apart in the second half by just completely dropping the story on the floor. Plus tons of game-state bugs: clipping out of “locked” fights, tasks not clearing after completion, music getting stuck, etc etc.
It’s just so hard to come close to Ori in this genre
Review: 2/10. There’s a reason you haven’t heard of this game
The latest big Soulslike. I was SUPER hyped for this game when the trailer dropped and (like many other games on this list) stuck with it much longer than I should’ve.
I actually put this game down for several months, even fully uninstalling it because I ran into multiple game-crashes on the old version. For the first time ever, I thought about seeking an actual refund on the PS Store but I think I was just a few days too late.
After seeing on Reddit that a major version update had been released, I gave it another shot.
It has a really cool “shadow world” called Umbral. Like most shadow/mirror dimensions in games, it’s a clever way to basicaly double the world for probably not double the code. It’s a tale as old as Zelda. The game has some unique interactions with this shadow world that I really enjoyed.
However, I did not enjoy this game. When most people say “soulslike” they don’t often mean “All the fun of Dark Souls 2 but with none of the soul” I think a major contributor was that I tried just going with a Strength build. Big Sword is fun in actual Souls games but got very boring very quickly.
The best part was when my friend Natalie joined me streaming the game for The Game’s Most Boring Boss fight. It was just a dude with a hammer in a 30x30ft square.
Review 3/10. Miiight be re-playable but probably never will
Another “soulslike” but with a twist and a beat-you-over-the-head message.
However, the last act gets super muddled, drags out, and completely drops storylines flat on their face.
The shell-swapping mechanic is fun but easily solve: The Valve is OP.
Review 4/10
This is why I love to write. It wasn’t until I wrote this up that I realized that there’s probably more value in just dropping games that aren’t doing it it for me.
There have been some notable exceptions of games worth “slogging” through, but after this latest batch of flops, I might just listen to my gaming gut more.
I’m back in the saddle of doing web development for dollars again, especially working with React. I’m thinking of doing a post on some dev tech that I like: Tanstack/React Query, Remix, and mise-en-place are some on top of mind.
]]>“How do I get started with Tyranids?” “Where do I start with Tyranids?” “Is Leviathan/Combat Patrol/Christmas Box good?”
I recently just got into Warhammer and into Tyranids myself and want to help answer those questions with what I’ve gathered. I’m not an expert, but I hope to help where I can with a guide that I wish I’d had a few months ago.
Here’s a brief, high-level overview of what Tyranids are, what makes them unique, as well as their general strengths and weaknesses.
The Tyranid are a Xenos (meaning non-human alien) faction in Warhammer 40k. They’re very much a combination of the Xenomorphs from Alien, Zerg from StarCraft, and the Arachnids from Starship Troopers. Actually, the Zerg were based off Tyranids! They’re one of the older and most established non-human armies in Warhammer 40k
Here is a 3-minute video overview of Tyranids from Games Workshop
Lore-wise their motivation is pretty dead-simple: eat everything The Tyranid army invades planets, consumes all available organic “biomass”, and converts that biomass into more Tyranids. Tyranids were named after the first human planet they consumed.
All of the Tyranid units and weapons are purely organic: mostly generally claws or guns that shoot burrowing slugs or acid.
The Tyranid armies also have psyker (psychic attacking) units, which often serve as relays for the Tyranid Hive Mind, known as Synapse. Mechanically, this Synapse boosts the Battle Shock tests of units within 6” range of a Synapse keyword unit to 3d6 roll instead of the normal 2d6. On the flip side, Tyranids also can also, once per game, force every enemy unit to take a Battle Shock test with the Shadow in the Warp ability, which represents the oppressive eldritch terror that the Tyranids project, signaling their incoming invasion.
NOTE that the “Synapse” keyword is what “has Synapse”. Only those that actually give Synapse have it in the keyword. Every Tyranid unit has the Synapse faction rule, which just means they can receive Synapse.
For example, the Neurotyrant has the Synapse keyword, so it “has” Synapse and projects it 6”. The Termagant does not have the Synapse keyword but only the Synapse ability so it it has the ability to receive Synapse (when within 6” of a unit that has a Synapse *keyword).
Here is the Neurotryant, which “has Synapse” because it has the Synapse keyword:
—
Here is the Termagants, which do not have the Synapse keyword:

You must have a unit with Shadow in the Warp on the board to do Shadow in the Warp.
TIP: do Shadow in the Warp during your opponent’s turn to maximize its effect
What they generally lack in raw power, they make up in their superior ability to swarm, control objectives, and adapt.
That point is worth repeating: Tyranids are an objective-focused faction. Prioritizing objectives and secondary objectives is crucial to winning with Tyranids. Tyranids are generally not an army that can “table” (completely kill) the opposing army. If a Tyranid army wins, it’s often with some or even most of their army dead but have earned more Victory Points, which ultimately is what determines the actual winner. This cinematic video from Games Workshop demonstrates it perfectly: the Tyranids appear to be getting slaughtered, but at the end of the video it shows the Imperium is losing the war.
I emphasize this because it’s often demoralizing to newer Tyranid players to have dozens of models taken off the board in one phase or even in one attack! This isn’t to say that Tyranids cannot kill at all; the larger Monsters can punch.
Of course, these are in general! Specific units will, of course, break out of these general weaknesses.
Before we go anywhere, it’s crucial to have some valuable resources:
First, This one is Easy: the Leviathan box set. Split the box with a friend or buy the Tyranid half from somewhere like eBay.
This box also includes a deck of the Leviathan Chapter Approved cards, which are used for playing current standard games of Warhammer 40k.
Many units within aren’t top-tier (then it would be a steal of a buy), it’s a great start and recommended if you’re new to Warhammer in general.
Next, get a 10th edition Codex new, in plastic! It has a QR code that you will need to unlock the Tyranid rules in the Warhammer 40k Official App. Also, it’s very easy to confuse the obsolete 9th edition codex with the 10th edition codex. The 10th edition has the logo-watermark. See the image below.

Unfortunately, the Leviathan Box doesn’t have a TON of great units even though it has a ton of models. Here’s a rough breakdown of the Leviathan Units:
The Number 1 question asked is “After the Leviathan box, what units should I get?” There’s no perfect answer and opinions will vary, but currently, here are some of the top units in the Tyranids that aren’t in the Leviathan or Starter boxes:
There very good and strong units within the Tyranid roster, but its most-often their points cost that is prohibitive. What makes the units above very good is their relative utility/power to their points cost.
NOTE It is currently VERY hard to find Neurolictors and Maleceptors for purchase. Good luck!
After those highly-recommend units above, here are the next tier of units. You don’t need all of these, but you’ll very often see them in good lists.
There are many more good units out there, but these above are some of the top ones.
Tyranid leaders aren’t typically meant to “lead” but here are some options.
Next up, there are a few Leader-Combo units available for Tyranids:
“But what about Norn Emmisary, Tyrannofex, Tyrannocyte, etc etc.”
There are many strong and cool models out there and I’m not going to say they’re all bad. Especially in certain detachments and depending on how you build your army, there are so many ways to build a list where any unit could be good.
However, every unit has an Opportunity Cost in the form of points: could you have put in a better model for a near-equivalent amount of points?
After knowing what units are considered, the next question is “Which Detachment should I play?”
The answer: INVASION FLEET
The Tyranid default detachment is the go-to for several reasons:
Here are the other Detachments:
The Tyranid Hive Mind has “tendrils” with different names, personalities, and (most notably) different color schemes. The Hive Fleets used to be tied to the Detachment, but that’s no longer the case.
Practically, it’s just fluff: how you paint your army and the lore behind it.
Some notable Hive Fleets are:
Most players come up with their own custom-named hive fleet for their own color scheme. Examples include “Tiamet” and “Garmr”
The Norn Emissary is a bit more flexible in its attack profile, while the Assimilator is more of a surgical assassin.
Like many kits that can build two things, the best this is to use magnets to get both from one box!
For magnetizing heads and arm joints (e.g. Hive Tyrant and Swarmlord): 5x2mm and use a 5/8” drill bit
For magnetizing bases to a metal or magnet tray for easy carrying: 10x2mm
YouTube:
Before I post this in front of a bunch of pendants, I’m going to include some caveats: I intentionally did not go into every unit and combination across the entire Tyranid Codex b/c others have done this and I wanted to keep this as a quick overview for people new to Tyranids and to help answer commonly asked questions.
There are many ways to play Warhammer, from only what’s in a Leviathan Box to the most hardcore competitive lists. I assume that people reading this are wanting to enhance their starting army but cannot just manifest infinite dollars and plastic.
]]>This post goes over the Frequently Asked Questions about Genestealer Cults Rules. I plan to write one about the faction itself later; as in, what models are good etc.
This post focuses on the rules because one thing GSC do is effectively “break” many of the rules that most other factions follow, in particular, around Reserves, Deep Strike, and One-shot.
Context: Acolyte Hybrids have a weapon option Demolition Charges which are powerful but have One Shot. There are two ways that Acolyte Hybrids can “come back”:
tl;dr Answer: Only with Cult Ambush, when the full unit comes back do you receive a unit with brand new demo charges.
You do NOT get charges back when a model returns from a Cult Icon wargear.
Why? Technically, no model ever gets its bombs back! Instead, the way Cult Ambush is worded is that you’re “adding a new unit to your army identical to your destroyed unit”. So they’re not coming back; it’s a whole new unit.
Cult Icon doesn’t give bombs back to a model that spent them because it’s returning the same model; not creating a new one.
Think of Reserves as what it sounds like: it’s a container like a bucket or box, for all your units that are alive but not yet on the battlefield.
Reserves itself does not give any rules on how or when the units arrive. That’s up to the abilities of the units that are in Reserves. The two most important examples are Deep Strike and Strategic Reserves.
In the core rules, Deep Strike is a unit ability that allows a unit to start the game in Reserves and can come down during Reinforcements anywhere that’s 9” away from enemies Core Rules Ref
Nearly every non-vehicle unit in GSC has Deep Strike! So this is important.
In the core rules there’s no limit to what can be in Reserves; HOWEVER, keep reading.
There’s a specific kind of Reserves called Strategic Reserves. Think of this as a smaller box within the larger box of Reserves.
Any unit can start in Strategic Reserves, up to 25% of your army, but it’s restricted to when and where it can arrive. If a unit starts the game in Strategic Reserves:
Here’s a picture that I hope helps:

It has also been clarified that a unit with Deep Strike can arrive using the Deep Strike rules even if they’re coming out of Strategic Reserves. See the 40k app > Rules Commentary > “Deep Strike (and Strategic Reserves)”. Deep Strike units are so cool you cannot keep them contained in an uncool box.
So those are the Core Rules, but of course, well all play by Leviathan Chapter Approves rules for real games of Warhammer 40k 10th Edition. Leviathan adds a few key additional rules around Reserves.
First, No more than half of their army in Reserves, by points OR by units
And here we have our first GSC way to break the rules: Primus ability Decoys and Misdirection allows for GSC units to be redeployed, including putting them into Strategic Reserves, which allows us to break the limits of what’s in Reserves.
Primus redeploys happen before the roll-off for first turn because it specifically does not say it’s after it’s ruled to redeploy before the first-turn roll-off.
But there’s another paragraph of rules for Reserves in Leviathan, and it deserves its own section…
Leviathan Chapter approved rules have the following paragraph in Section 8: Declare Battle Formations
Reserves units cannot arrive during the first battle round and any Strategic Reserves or Reserves that have not arrived on the battlefield by the end of the third battle round count as having been destroyed, as are any units embarked within them (this does not apply to units that are placed into Strategic Reserves after the first battle round has started).
First, let me caveat: it is arguably unclear whether this parenthetical applies to the whole sentence or simply the last clause and GW has not given an official ruling. However, I’m restating what every major Tournament has ruled, which is that the parenthetical “this does not apply…” applies to the whole sentence. If it wasn’t meant to apply to the whole sentence, GW could’ve split the sentence into two. Just a reminder kids: it’s a game but also, don’t write run-on sentences!
Let me emphasize the part in parenthesis:
this does not apply to units that are placed into Strategic Reserves AFTER THE FIRST BATTLE ROUND HAS STARTED
This rule is so important to GSC that I created this handy link: https://tinyurl.com/LeviathanReservesRule
What this means is that if a unit is placed into Strategic Reserves AFTER the first battle round has started (which means it started the battle on the battlefield), then it:
This allows a unit, say a Neophyte Hybrid unit, to Deep Strike round 1 if the following conditions are met:
1 & 2 are clear from the “this does not apply…” part, but why does it need Deep Strike?
If the unit does not have Deep Strike, then it has to follow the normal Strategic Reserves rules from the Core Rules, which don’t allow Round 1.
Let’s see how this specifically works for GSC
First, see the sections above for the rules behind this and why. As a quick reminder, there are three conditions:
#1 is easy and obvious. Start with a unit (or two Battleline units) on the battlefield at the beginning of the game.
#2 is done with Return to the Shadows stratagem: 1CP, end of you your opponents turn, place up to two GSC Battleline units or one other GSC Infantry unit into Strategic Reserves. The units must have Deep Strike and not be engaged.
#3 is easy because Return to the Shadows only targets units with Deep Strike and every non-vehicle in GSC has Deep Strike!
Here’s how the timing works out. It only really works if the GSC player goes second.
If the GSC player goes first, then the opponent’s end of turn is just before round 2 and we could always Deep Strike on Turn 2 like normal.
Here’s the typical sequence, let’s assume two battleline units:
First, consider reading my original post on Advent of Code here
Assuming you’ve read that, here’s my update:
I finished year 2022 in surprise! Kotlin! You can find the code here: github.com/valbaca/advent-kt
Even though I didn’t even mention Kotlin in my last post, it’s the primary backend language that I use now for work. I ended up not staying at the startup that used Python, but I’m still a fan of Python. In fact, I even went back and finished 2021 in Python.
Kotlin
map followed by sum it will suggest just doing sumOf. So much better than memorizing all of Clojure’s sequence functions.when expressions, and data classesint, Clojure’s assoc-in and friends, and Rust’s matchPython
return a, b if condition else None I expected (a,b) | None, but got (a, b|None)It’s the classic Static vs Dynamic languages: dynamic languages require less up-front time but cost more in runtime and tracking down type issues at runtime; whereas, static languages have the opposite trade-off.
Now, there’s a language that’s further on the up-front spectrum: Rust.
Rust
I am more familiar with Rust now after reading and working through The Book, Rust by Example, and Rustlings.
As a means to better understand Kotlin’s coroutines by way of my prior understanding of Go’s goroutines, I wrote gotlin which reimplements the goroutine examples from The Go Programming Language book in Kotlin with coroutines.
In no way do the authors of “The Go Programming Language” endorse this or this use.
This post assumes you’re at least vaugely familiar with Go, goroutines, Kotlin, and Kotlin’s coroutines. If you’re not, here are some resources before diving in:
Coroutines can be challenging to understand, leading to potential issues when used incorrectly. I cannot cite examples here but I have reviewed the severe event retrospectives where, for example, the root cause was improper use of runBlocking within another runBlocking. This has lead some engineering orgs to have an irrational fear of coroutines and of Kotlin as a language as a whole. Concurrency is hard, but it’s not impossible and should be understood, not feared.
Because of this, I set out to better understand coroutines myself and I struggled as well. While watching a talk that demonstrated the use of Kotlin’s select it clicked that part of my misunderstanding of coroutines is that they’re very similar to Go’s goroutines. I was treating them too similarly in my head. While at the same time, I didn’t have many (any?) great practical examples of coroutines in use.
I set out to better understand coroutines by directly comparing them to the goroutine code examples in The Go Programming Language book. While I only occasionally use Go professionally, I think this book is absolutely top-notch; easily one of the best programming language books on my shelf.
Granted, this is targeted at a pretty niche category:
That said, the way to use it is:
There are more details in the gotlin README but here are some higher level things I learned
First, just like in grade-school, let’s compare and contrast the two:
I think this is the key point: Many of the differences between goroutines and coroutines come down to philosophical design differences between the Go and Kotlin programming languages.
Go emphasizes simplicity, practically above all else. For example, its runtime has a garbage collector, but very few ways to tune it. Of course it has for-loops, but no functional equivalents of map/reduce/filter. Go’s philosophy seems to be to prefer to remove what can be removed from the language and only add features when there’s been a clear demonstrated need over time. This is in stark contrast to many languages that absorb features quite easily, like C++. Which of course makes sense given that it was born out of dissatisfaction with C++. This explains why it took so long for Go to support Generics.
Back to goroutines, this minimalist philosophy shows up in how goroutines work:
go, as are channels. This allows them special in/out channel syntax and selectOn the other hand, Kotlin is anything but minimalist. I’d consider Kotlin a maximalist language with pragmatic defaults. Kotlin tries to provide what’s likely best for you in short reach (e.g. collections are immutable by default) but lets you run with whatever paradigm you’re most comfortable with among imperative, object-oriented, functional, or declarative (via DSLs). It leans toward immutable functional-spiced value-data-oriented programming, but it doesn’t impose a philosophy unto you. Much like its ancestor, Java, it provides managed functionality.
Along with that philosophy in mind, some distinctions around Kotlin’s coroutines are:
runBlocking and it’s important to not step through this bridge twice!select cannot have clauses send and receive from the same channel.launch and async return Job and Deferred, which allow for management of the child coroutines. This includes the ability to cancel, which Go does not directly support.I took on this project with two goals, both intentionally limited in scope:
I will have to wait and see if #2 is met, but I definitely met my #1 goal.
A large part of that was due to the very helpful expert PRs from dump247. Going into this, I expected it to be a self-study, code, then release process. I tend to run solo and I never really understood “study groups.” I didn’t even consider or expect anyone else to contribute, but I’ve learned more from his contributions than I would’ve on my own.
I’ve left room for additional enhancements.
Suggestions and pull requests are welcome! I continue to learn and welcome any constructive input.
]]>I’ve considered getting a letterboxd and/or a backloggd, but I would just rather have my own reviews written in my own markdown files that happen to post to a website via GitHub pages and DNS magic.
Bioshock was my personal gaming albatross: I’d tried and failed to play this game about three times. Similar to Transistor, it’s a game that I should have no problems playing and beating, but just like in Transistor when I hit the first non-trivial fight and was sent back to respawn with fewer resources than I had when I got beat…I fell off.
I knew the game is considered a masterpiece and by all other measures I ought to have enjoyed it: fps-horror with magic and dunking on Ayn Rand? Hell yes. So, I put it back into my backlog and floated it to the top.
So given that this game is nearly old enough to graduate high school, what’s left to be said? It was super solid and lived up to the hype, even after nearly two decades. The story was great, and even though one of the two major twists was spoiled to me, it did nothing to lessen the experience. The choices made led to lots of conversations with my lovely gaming co-pilot.
However, the biggest annoyance was the sound mixing and balancing. It was downright ruinous at times. I would be getting radio voice-over with crucial plot points but somehow the vending machine and slicer repeating the same lines for the billionth time a room away were somehow louder. Boss’s dialogues were similarly overly muted. And god forbid you try to hear anything while a bot alarm is going on.
Not nearly as bad as the sound mixing, but the weapon design was too much. Really the breaking point was getting a crossbow in the late game that somehow does more damage than a grenade. Just because there are 8 points on the dpad doesn’t mean there must be a weapon for each one (and each weapon doesn’t need to have 3 kinds of ammo). I felt like I spent more time in the weapon radial menu and saving the game than actually playing the game. Sure, the compulsive saving is on me, but the point stands. Another disappointment was how little the ice spell plasmid interacted with the environment. The telekinesis, lightning, and fire plasmids were so interactive but the ice plasmid couldn’t even freeze water!
The ending boss fight and cutscene left a lot to be desired. Not the worst, but not the best.
All that said, the game hits on nearly every axis: you feel fear as you worry if your bullets and Eve will be enough, you experience horror from the character’s actions (and even abhorration at your own choices), and excitement. The Resident Evil style of limited resources still hits. The political commentary (Objectivisn’t) is just as poignant as ever. I’ve never been so enraptured (ha!) by every poster and audio recording. Hearing the diary of a plumber was honestly some of the best parts of the game. I could just listen to a whole podcast of the tape recordings.
tl;dr: don’t judge a game by its logo
I thought this would be in the vein of Dear Esther or What Remains of Edith Finch. And can you blame me? Look at the game cover art; it follows the pattern perfectly: simple black and white diagram of some seemingly complex structure.
This game does not even compare though it obviously tries to. Within 30 seconds I’d figured out what it’s “about” (guilty grief) and it made it even worse to play the rest of the few hours we did play. The character walking is wobbly and nauseating. The main character is the boy/brother and not the character you control. He’s insufferable and it’s like the writers made him insufferable on purpose…as if to make what it’s “about” even more impactful or traumatizing I guess??
The whole game is about a heavy subject but then presented with graphics I can only describe as Jimmy Neutron but worse.
tl;dr: I liked the concept but this should’ve been a zine.
I was really excited about this. I thought it was going to be in the vein of Black Panther-esque Wakanda but for Latino/Mayan in a beat-em-up. And even when you start playing, it almost seems that way, but very early on they explain that their civilization only developed in the advanced fashion because of the Quezacotl god’s intervention, which really sucks the air out of the room.
The dialogue is cringy, the plot is paper-thin, and the gameplay isn’t fun. The “cutscenes” are poorly done. At one point one character just teleports back and around the room while having a conversation. I try to give this the benefit of the doubt given that it’s obviously a super-indie game but this got to be painful to play.
tl;dr: an absolute joy to play and fun to watch/listen as well
Cult does so much well, it just puts you into an entrancing gameplay loop. It’s in the vein of Stardew Valley in that a majority of the game is caring for your cult. While Stardew Valley has the cave-diving as a late-game “mode”, the roguelike runs of Cult are actually The Point. The runs themselves are really short, compared to nearly any roguelike, but that’s kind of okay. It doesn’t feel great to have a great run end so abruptly, but it also makes bad runs less bad.
The art style and music are immaculate. It wasn’t long before I started hearing the Cult music in true stereo in my house: once from me playing it and again from the other room as Amanda played the soundtrack on her speaker in the other room. The adorable bubbly rubber hose style juxtaposed with the subject matter of cults, demons, and sacrifices all blend beautifully.
The combat felt a bit unfinished and the game was quite short. Only the dagger and sword feel viable, and the latter levels are easier than the earlier stages. I hear a combat revamp is in the works. I don’t think it needs a full rehaul, but just a bit of tweaking could really help. As you approach the end-game, you know that it’s coming. But honestly, it’s not even an aspect I’m terribly upset about. It’s great when a game knows when to stop while it’s ahead.
tl;dr: An impressive soulslike. While it fell short of my expectations, it shows promise for the studio’s future.
This soulslike is most similar to Bloodborne, with some Sekiro elements, depicting an alternative world where steampunk porcelain automats determine the fate of the French Revolution. If Bloodborne is Lovecraftian London, then Steelrising is Steampunk Paris.
The game’s combat is pretty good. Your character was previously a dancing automaton, and that comes through beautifully in her moves. With any weapon, you amass an array of varying elemental attacks. While weapons are not quite as deep as Bloodborne’s (what could be??), they are reminiscent.
I’m not personally a fan of Metroidvania style of blocking off areas until you get The Necessary Gear, I’d say the way Steelrising does it is one of the better ways.
What’s Good: The really great part is the protagonist, Aegis herself. She’s just perfect. Her style, her sass, her character development; just A+++. Try to not fall in love with her, I dare you. Speaking of her style, the drip in this game is stunning. I normally couldn’t care less about style but I found myself checking the store at each “bonfire” for new outfits, just hoping I could get to see what next beautiful hat or blouse I might find. They fully channeled Fashionborne.
Screenshots (no spoilers)
What’s Bad: The level design is bad. The maps are far too sprawling. I understand they’re trying to depict an actual real-world city with limited resources, but what you get is lots of mostly-empty city streets. What is in the streets is the repeated assets. I know exactly how many dead citizen models and carts there are.
What’s Mid: it took quite a while to build up, but the NPCs whose names I could hardly tell apart in the beginning get to be close, familiar faces by the end. I thought I wouldn’t care about any of them but before I knew it, I was saying “Bon Son!” along with them as the story progressed. The story is a slow burn but it really pays off in the end.
What’s Terrible: the boss fights are a complete snooze. The entire souls-genre is centered around memorable, difficult (but usually fair). Nearly every boss fight (except ONE) in Steelrising was utterly forgettable or a complete snore. At one point I started playing with one hand. It was downright unenjoyable.
Overall, I generally like soulslikes. I know they’re not the “real deal” and am willing to give several concessions. Steelrising certainly demanded such benefit of the doubt in some areas (the boss fights) but rewards it justly in others (characters and style).
]]>What is Advent of Code? Well, go to https://adventofcode.com/
Okay, but what is it? Go to https://adventofcode.com/2021/about
Primarily, I’ve used Advent of Code as a fun way to keep my coding skills from atrophying during times where I’m coding less at work and it serves as a great way to learn new languages by forcing me to interact with typical things like:
Putting my progress into a single place to make tracking easier:

I think such writing prompts are really great, so I’m going to be using them to encourage me to blog more.
Here’s the first:
This one was easy: Logitech MX Master 2S Wireless Mouse
I’ve gone between many keyboards (and “my setup” is a topic for another post), but this one mouse is one I’ll probably never replace and should actually buy a pre-emptive replacement now, before it gets discontinued or replaced with something worse.
Here’s my use-case:
The Logitech MX Master 2S delivers all of that and more:


The only issues I’ve had are:
When this happens, the middle button goes back to its default setting of changing the mouse wheel scrolling from smooth to clicky.
This doesn’t at all interfere with how it functions as a normal mouse, just the “nice” button features, so I give it a pass. It also seems to happen if I use the Expose feature a lot with many windows. Maybe some kind of bad timeout handling? It’s definitely something broken in the Logi->MacOS calls.
As a workaround, quitting the Logi Options Daemon from Activity Monitor causes that daemon to restart and it works again.

I won’t even include a photo of what my mouse wheel looks like.
I’ve tried cleaning it with rubbing alcohol but the rubber finger-tread starting coming off. At some point it will be the part of the mouse that fails first.
However, given that I’ve used this mouse for well over 6000 hours (3 years 50 weeks / year 40 hours / week), it’s fair that some rubber parts would start coming off.
The rest of the mouse has held up incredibly well. Even the rubberized plastic coating, which in most electronics starts coming apart eventually, shows no ugly signs of wear; just normal smoothing from lots of use.
I love learning new programming languages. It’s almost an obsession. I think it came from the fact that I learned so many clunky languages at the very beginning of my programming life. My very first programming book was “C++ for dummies” (5th edition). In 2006 (high school for me) C++ was synonymous with programming, at least in the sense of “how do I learn to program.” Before that, I technically did a tiny bit of web-development in middle school, around 2002. It was just the absolute basics of creating a website. These skills would be really handy in the era of MySpace and being able to copy in CSS and JS and know what was actually going on!
Moving on…in college, I majored in electrical engineering and computers science. On the CS side, we mostly worked in C++ or Java or Scheme. On the EE side, it was mostly Matlab but also some C for microcontroller programming. I never really found a language I liked, but we also use a different language each semester so you didn’t really get any expertise in any of it. It was also rough because to be honest, none of these languages were very “friendly” to new programmers and some of the professors were just downright hostile to change. I remember our computer architecture professor refused to touch any machine that wasn’t running SunOS (in 2010!). But the languages we did use were geared toward the machine, not the programmer.
For me, the big enlightening experience was around 2011, at the peak of the Ruby on Rails hype. My last semester of college was one where I finally had some free time after four and a half years of dual majoring. I mostly spent time with my girlfriend (now wife!) and played lots Call of Duty (I was great!) and Starcraft (I was terrible!). I also messed around with learning Linux deeply and the Ruby programming language. It was beautiful. You can print with just one work puts or hell, even one character p. You could fit entire programs on a single screen. Your numbers are just numbers and the number type just automatically gets bigger when they need to. With Ruby on Rails, I built my own Rails website on Heroku. With a credit card mean for emergencies…I bought like four books on Ruby and RoR immediately.
(A short aside on books vs online learning): This would also kick off my love of programming books, especially the O’Reilly programming books. I’m going to date myself, but I still love learning the fundamentals of a language from a book. I think a major reason was that screen sizes were quite limited back then. You only had a single monitor or laptop screen, so having a book laid open was like a second screen. The editing quality of books is also higher than most written documentation and there’s no link rot. Books also tend to give more commentary on the why and best practices and is more conversational, whereas a website is just listing facts. All that said, it all depends on the language; some just don’t have a good book (Crystal) and/or have superior resources online (Clojure, Go, Rust).
Granted, there was so much at that time I didn’t remotely understand (ActiveRecords, metaprogramming), but it felt okay because it was because that was Advanced Knowledge and not just complicated knowledge (as opposed to needing to understand OOP for Java or Pointers and memory management for C & C++).
Of course, as the saying goes, beauty doesn’t last. I’ll never forget the moment of disillusionment as I worked through Project Euler problems in Ruby. Sometimes, it would be execute in a second and solutions would consist of a single-line of code…and other times, it would take hours to finish executing, meanwhile my poor Thinkpad X200s turned into a hot plate. I felt firsthand what people meant when they said Ruby was slow and inefficient. Obviously my Project Euler solutions were just toy programs, poorly written by a novice and I was only a math major, but we would soon hear similar stories in the large, like with Twitter moving away from Ruby as well.
With that last semester of college over, it was finally time to get to work. I went to work at Raytheon because they were literally the ones hiring. The Great Recession was officially over but it was still very rough to get a job straight out of college. Being a military contractor, they obviously weren’t on the cutting edge of web tech, but there were people really trying to bring Raytheon into the 21st century with Agile and Ruby. All I worked with was Java 4, J2EE, and some old-school IE6-compatible JavaScript. I actually did quite a bit of JavaScript because the “real” programmers were not willing to learn a “new and terrible” language. I hadn’t touched JS since building my Yahoo! GeoCities website in middle school, but saw that I could fulfill a role that the team needed. It was also the time that JS was getting more attention with Node. I still have my ebook “What is Node?” floating in my Kindle library from that time. Even at the time, it wasn’t clear whether Node was to be taken seriously or if it’s an elaborate practical joke on programmers. Somehow we were wrong and right on both accounts.
I actually cut quite a bit here… suffice it to say that I was happy to leave Raytheon and work at the quickly growing more-than-just-a-bookstore Amazon.com in 2013. However, in terms of programming languages, not much changed. Java and JavaScript still made up 90% of the code I would write for the next decade.
That was until I worked on AmazonSmile for iOS where I worked with Swift Objective-C. Since we had to write in ObjC, I took up the role of becoming an ObjC master and teacher for the team. Despite the crazy syntax and obscure nature of the language, the team grew a soft spot for the language. Stepping away from the absurdly complected world of Java, with Spring’s AbstractProxyFactories, Dependency Injection, and terrible build times (made 10-100x worse due to internal tools). ObjC built fast in Xcode wayyy faster Android Studio and the debugger actually worked, every single time. You could do neat stuff with “reflection” with hardly any runtime hit. Obj-C’s directness, speed, and reliability made Android’s Java look like a joke…but square brackets are too weird I guess.
That said, I completely understand why these companies choose Java. It was built scratch to be for enterprise use, not just because of things like Spring and Hibernate, but by the very nature of the language. Everything must be in a class and nearly every class corresponds 1:1 with a file. So everyone’s work is separated, reducing the # of files anyone works on at a time. This is all following the Single-Responsibility principle. But at the same time it reduces the ability to make changes that have cross-cutting concerns (like security and logging). So then we tack on things like AspectJ and Interceptors.
This may be my tin-foil hat, but I legitimately believe that part of the success of Java is the nature of the cult around “Best Practices” (of which I’ve been a part of!). Java was designed to be easy and familiar for C++ programmers to pick up and C++ itself was similarly designed to be easy and familiar for C programmers to pick up. So there are design decisions that trace all the way back to C and also new ones thrown in as well. While C & C++ have foot-guns, Java has foot-tazers? You can find them in Java Puzzlers . So before you can be effective Java developer, you have to first learn the basics of programming (variables, loops) and OOP (classes, methods, inheritance). Then, just when you think you’re ready, you also need to read Effective Java. At each step of the way, there’s some more senior developer eager to slap you on the wrist in your code review and remind you to use final everywhere. But the whole thing is that these things don’t make you a better developer, they just make you a better Java developer. What’s the difference? Certainly a whole ‘nother post.
There are complexities inherent to some domains and many problems in software engineering that are Just Very Hard, period; like CAP theorem and distributed computing. Then there are things in coding that are also Just Hard; like naming and commenting appropriately. Finally, there are things made hard in programming by the language. Again, Rich Hickey put it best. Please, if you take nothing else from this post, check out that video clip.
At this point in my career, I think I’m approaching a new level-up moment. I’ve dabbled in a lot of languages at work and many more at home. A glance at my bookshelves and bookmarks shows: C, C++, Objective-C, Rust, Go, Java, Perl, JavaScript, TypeScript, Python, Ruby, Scala, Kotlin, and Clojure. My brain is saturated with syntax and idioms and paradigms. At this point I’m mostly frustrated with languages with too many gotchas. But I suppose any language that actually sticks is one that sticks around long enough for those “gotchas” to actually be found.
I’m also frustrated by modern execution times. Java’s cold starts on AWS Lambda have been the bane of my existence for the past several years. The GraalVM is supposed to help in this regard, but with serverless, we really have to rethink our execution model. The idea that “it doesn’t matter how long it takes to serve the first request as long as the rest are fast” is old-fashioned; oh, and the “fast” second requests still aren’t even that fast. Why does every request to a Java server come with a 100ms minimum latency? It’s all just a tradeoff that we accepted to not have to deal with memory and pointers. And to be fair, Java held the crown for fastest enterprise language for a long time. Only recently did Go begin to usurp the king. And again, to be fair to Java, it practically allowed Amazon and other companies to be able to build out what they needed by tossing more developers at the problems. A mediocre junior Java developer can actually get a decent amount done. So I see why it’s still on top. I mean, look at me!
I’ll make this section its own post, but there are a handful of languages I’d love to work with at some point:
I look forward to writing about each of them.
In the meantime, my world is still very much mostly Java and JavaScript. Both are getting rock-solid upgrades with Kotlin and TypeScript respectively. I don’t mind any of them nearly that much anymore.

So what’s the point of learning so many programming languages if you only use really two languages? Because each language teaches a lesson, gives a different viewpoint via its paradigm, and shows what is possible in computing, but may just be tough in your language.
So to wrap this up, I’ve compiled a list of things I’ve learned, loved, and hated about different languages I’ve worked or played with, approximately in order of low-level to high-level programming languages.
Result<T, E> style returns with the ? shorthand for easy error-handling.java.util and Java’s interfaces like Iterator/Iterable/Runnable adapted very well to single-method-lambda functionsval keyword.npm is better than all of this nonsense. Also, I cannot stand the __dunder__ methods.fold/map/reduce and what metaprogramming looks like.Thank you so much for reading. If you have thoughts, questions, or articulated feelings, please tweet at @val_baca.
]]>