Development

Alliances!

We’ve added a great new feature we’re calling Alliances! An Alliance allows two or more Players to collaborate via real time chatroom. It’s a great way to develop a strategy for an attack, a plan for protecting trade routes, or just swapping game tips with each other!

To CREATE a new Alliance, you will need to be a Galactic Impact Premium Subscriber, but once an Alliance is established, any Empire in the Galaxy can be invited to join and enjoy the full benefits of this feature.

Empires who belong to any Alliances have an additional panel on their Diplomacy Page that allows them to access the Alliance Real-Time Comms Page. Send and receive messages in real time with the other members of your Alliance, communications carried across any stretch of Galactic distance in an instant.

Invite additional Alliance members as needed and those players can join the chat as well.

But! Keeping these subspace airwaves open and clear is not without cost — Alliances have a Galactic Credit upkeep cost each Stardate, based on the number of crosslinked subspace connections it supports between member Empires. Any member may pay into the Alliance coffers, but make sure someone is keeping on eye on the balance, because if the Alliance’s funds debit to zero, the Alliance is disbanded and the communications history will be lost!

So make sure to only invite those you really need as members of the Alliance, and avoid the upkeep cost becoming unmaintainable. Also, any member is allowed to invite any of their Diplomatic Relations to the Alliance, so make sure they’re trustworthy!

Enjoy!

Rubber Banding

A big question I get from folks as they’re signing up — “what’s to stop someone who has been playing for a while from coming in and stomping me as soon as I sign up?” — and it’s a very valid question. A 4X game, by it’s nature, involves a bit of exponential growth, population being one obvious example in Galactic Impact, but also sheer access to resources: finding a second planet, then another, then all those planets funding your fleet, to find more planets, there’s an intrinsic exponential growth. 2x.

Of course, if you join today, and I join tomorrow, and we’re on the same exponential growth trajectory in a game, I can literally never catch you, it’s mathematically impossible, which diminishes the fun for both of us. For me, I can’t ever “overtake” you, so why try? But also for you, because you have no meaningful peer competition.

Frustrated

So today was like the first frustrating day of this for sure. I ran into some shit with Rails associations that were really really tedious, and I’m a little angry about it, but I think I got to a good solution.

Some background basics of a 4X (at least ones set in Space), you send ships to star systems, where they either fight other ships, or land folks on the planet to grow a new Outpost, but at the same time, ships belonging to other players are also going about their business, and how do you know if you can see them or not? Star ships ostensibly all have sensors baked in, on the lookout for hostiles (or even allies…?) and new stars to expand our starcharts as we explore outward.

Starting Locations

One challenge with the old build of the game was instantiating ‘new stars’ for a new player to call home when joining the game. As a designer, you want them to have a little bit of a platform from which they can step up and take on the other players who have been playing a while, and have expanded out among the stars. But how to do that in a way that seems even remotely fair? The first time around, I used an algorithm to choose where the new player’s star would be placed, called the Archimedes Spiral. It took as input the number of previously-registered players, and made a somewhat galaxy-shaped spiral, expanding outward from a ‘galactic center’. But issues arose when it became more and more apparent that the stars were too close together, and there weren’t a lot of “other places” for a player to check out that weren’t already someone else’s homeworld. I could have tuned parameters of the spiral, but ultimately, the new stars were always appearing in a predictable pattern, so an experienced player could camp the end of the spiral arm with a Shipyard or a few heavy warships and make a quick PK on a new player as soon as they joined.

Mostly, I’m attempting to make the first pass at development a 1:1 replacement Ruby for Python and Rails for Django, but this was one area that I knew would be a problem as soon as beta testing began, so I chose to take on the challenge of re-imagining this as I rebuilt the new onboarding path.

This is an issue that has been gnawing at me ever since I put this game away 10 years ago (probably second-only to concocting ways of ‘rubber banding’ the exponential growth advantage of players who joined before you), so I had some ideas on how I might approach it.

Rolling Dice

Between working on Galactic Impact the first time in the late 20-aughts and today, I’ve done a lot more board gaming than video gaming, and that’s also where the bulk of my ‘game design’ brain has been. Comparing that world with video games is an interesting exercise, especially because there’s a lot of conversation about “app integrations” on the board game front these days.

This all came to mind as I was dove in to rebuilding “population growth” for Player’s “Worlds” in Galactic Impact. In the old version I did a blanket percentage growth calculation — for example, if the target was 1% growth, multiply the population by 1.01, save that as a the new population and call it a day. Got the job done, but was completely deterministic, which is somewhat unrealistic for population growth. (Also unrealistic when using that same calculation to determine the numbrer of deaths on account of hostile atmospheres).

Evolving 4X Terminology

It’s a core belief of mine that language is important — after all, if you and a listener don’t have a common language of some kind, you can’t communicate — so as I’ve been rebuilding Galactic Impact, I keep being struck by the word “Colony” everywhere in this type of game (Sending Colonists to another world… to Colonize that world when they arrive…).

Without doubt, the term is common parlance when we talk about setting up permanent human habitation on worlds in outer space, “a Moon colony”, “a Mars colony”, and beyond. In fact, NASA has entire articles about it. But in reality it’s a term rooted in a really horrific period of human history. It doesn’t often get this framing in History classes in the U.S., but Colonialism was a seriously fucked up era when entitled European empires showed up on foreign shores to kill, loot, and occupy as they saw fit. These actions redrew the map and world affairs in ways that are still visible four hundred years later, and lots of people around the world are still experiencing the negative downstream effects.

Template tags and partials

So the first big difference I’m running into between the Old Way (Django) and the New Way (Rails), is that Django uses a templating tool like handlebars or mustache (I’m not sure how to tell which from what I’m seeing in the code here), which has the nice effect of really forcing the developer to separate the logic from the view.

Note: Django’s pattern looks more like Model-View-Template in practice, because what a Raisld eveloper would call a Controller, Django calls a “View” which then renders a template, rather than a Rails Controller/Action rendering a View Template.

Using Django templatetags

The challenge is, that in order to force this strong separation of concerns, when a developer (me) wants to render something more complex in Django, it’s necessary to define a custom ‘tag‘ or a ‘filter‘ that the templating engine can then load and use. In the world of “basically all programming languages do the same thing“, this is really pretty equivalent in outcome to a Rails ‘partial‘, though the latter doesn’t offer any guardrails to prevent the commingling of logic and display, which can be a problem for debugging. But a sawzall doesn’t prevent one from cutting through a power line either… doesn’t make it less awesome of a tool. The user just needs to be cognizant of what they’re doing.

Data Driven Design and Component Architecture

Oh shit, I got access to the old database. Not really a surprise, but as I’ve been digging through models, I realize that I’d done a lot of things well (even this long ago!) by using data-driven design, such that they could be modified on the fly, for example if populations were getting out of control, or mines didn’t seem to be turning enough ore to resource or whatever, the ratios that drive those economies could be changed with a database value in a table called “UniversalConstants” — a notion I later carried over into Terraformist. Also, the ShipDesigns, the different classes of ships that could be built But as I’ve been starting the process of rebuilding the model classes, I’ve had this nagging worry that some of that was going to be missing or lost. But it’s not! Sweet.

Perhaps surprisingly in 2020, Data Driven Design was somewhat of a newish concept back in 2009 (or at least it felt like it), and not something everyone was doing in game design, but I had a friend and early biz partner Paul who was really keen on the idea, and had forced me to read a paper on the topic the year we attempted to found a gaming studio in 2005.

Let there be stars

Yesterday, I went through some of the basic object modeling — Stars, Planets, and some classification systems for both of those things. The Star classifications are loosely taken from the Hertzsprung-Russel diagram, and will give the map a bit of color by having the Stars show up differently, maybe down the road these will have various impacts on their planets’ resource generation. The Planets each have an “atmosphere type”, one of several arbitrarily chosen gasses, which can have major impacts on how suitable they are for living on, or for setting up resource extraction.

Kicking off

Normally, when I’m leading an engineering team, or consulting for one, I’m always firmly in the camp of avoiding a full re-write of your codebase. If you’ve got a functioning product, and customers, you just can’t press pause on development there, leaving current customers without bug fixes or improvements while the team spends 6-12 months rewriting everything from scratch… But I digress. Luckily(!?) in this case I don’t have a functional system or any existing customers… just a dusty codebase. In fact, I did a little infrastructural work this weekend, just trying to power some things on, I got a warning that a component I was using was deprecated… not that uncommon, generally, but this deprecation warning was SO OLD that the component it was recommending I upgrade to HAS ALSO SINCE BEEN DEPRECATED. That’s how old it is ????

(Cue joke about Arthur in Hitchhiker’s Guide searching for files in a disused lavatory)