Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Advanced search

1382355 Posts in 66042 Topics- by 58453 Members - Latest Member: MilkyTeaLuke

September 23, 2020, 08:13:48 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsCogmind (sci-fi robot-themed roguelike) - BETA RELEASED
Pages: 1 ... 62 63 [64] 65
Author Topic: Cogmind (sci-fi robot-themed roguelike) - BETA RELEASED  (Read 167605 times)
Level 9

View Profile WWW
« Reply #1260 on: December 03, 2019, 04:36:25 AM »

Our sixth annual review is up!

As usual this one is only available on the blog, and includes topics like dev hours talk, a quick overview of the major releases and special events this year, new milestones reached, and musing on finishing, or not finishing, 1.0 in 2020 (something we gotta do for every new year, right? :P)

There might be a hint of things to come, things in the not-so-distant future...

IndieDB is also voting for GotY again, so if you could, I'd appreciate if anyone can spare a moment to help Cogmind take its place in the Top 100 this year :D (might as well keep the five-year streak going!)

Level 9

View Profile WWW
« Reply #1261 on: December 13, 2019, 03:22:36 AM »

Movement QoL
[Cross-posted from the devblog here--follow link for better formatting and light-on-dark style.]

Movement is pretty convenient in Cogmind, an important goal to aim for since this is generally the most common action players will perform in a roguelike.

Four different methods are supported out of the box, the mouse along with three different keyboard-based methods (numpad, arrow keys, and hjkl).

Movement input preference distribution (*only includes those opting in to reporting).

About the same number of players use the mouse and numpad, with the remaining minority divided between arrows and hjkl.

Moving via mouse cursor is certainly easy to use--simply click somewhere to go there automatically, although the keyboard offers finer control so it's no surprise that in a tactical roguelike like Cogmind technically a majority of players end up relying on the keyboard for more or even all of their movement.

About one-fifth (21.3%) of players (including myself) even exclusively use the keyboard for everything, so for a while I've been mulling potential improvements and additional features for keyboard-based movement. According to the stats, newer players are more likely to start with mouse movement (unless already familiar with traditional roguelikes), but either way the chance of someone becoming a keyboard player goes up over time as they play more and learn how to do some actions faster that way, might as well continue improving the experience!

Keyboard Running
Although players new to the genre tend to assume "running" means a mechanics-relevant action where your character is actually "moving faster," in terms of roguelike input schemes it actually refers to moving multiple spaces in a (usually straight) line via a single command.

Cogmind has had running ever since the original 7DRL release, because it really saves a lot of time (also more specifically back then mouse-based movement wasn't a thing, so there needed to be some convenient way to quickly cover long distances!). At that point it was the dumbest implementation possible, though: "automatically move in one direction until something blocks the path." (okay it could've been dumber--it also immediately stops on spotting an enemy, but I'm only talking about layout detection for now)

Smarter approaches need to take more of the layout into account, stopping not only at obstacles, but also where the player might want to reconsider their direction, or perhaps take another action.

That's what I did for the alpha release, adding a new rule that the player should automatically stop running on reaching a location where the current cells immediately to the left and right are either doors or open space, and one or both of those adjacent to the previous position were not also open. This properly stops when arriving at doors/doorways, or arriving at a side-corridor while following a wall. It doesn't stop, however, when running straight into a narrow corridor, so that's a good thing.

Sample stop points from the original running system, demonstrating the direction from which the run is coming from, and the two points which are compared to trigger the stop.

At the time I left a note in my code that this could be better, but would get complicated fast and I wasn't sure what use cases we might need to address before it was ideal, so that's as far as I went.

Honestly if your running system gets too complicated it'll be both annoying and unpredictable. Predictability is important, since mistakes can get you killed and no one's going to be happy using a UI feature prone to "error" (where UI errors are defined by players as anything they did not expect/want to happen). Basically the system should stop as little as possible while still being as useful as possible.

There was definitely still room for important improvements, so that's one of the areas I was working on recently.

For one, the original system was only applied when traveling in cardinal directions. While this is sufficient for most use cases since corridors only travel in cardinal directions anyway, sometimes diagonal running through an open area might hit a layout where it should stop. Rulewise it's not really much different from cardinal movement, just looking at different cells.

Sample stop points from the new diagonal running system, demonstrating the direction from which the run is coming from, and the two points which are compared to trigger the stop (or in the special case of the door, that one is simply checked for explicitly).

Another improvement to address is the fact that the first diagram up there for cardinal running ends up being suboptimal! Although on reaching a corner you may want to move out beyond it in order to look around, there's also the chance you intend to simply round the corner without looking first, in which case you can move one less space by taking the diagonal, an option which is lost if the running behavior always moves out beyond the end of the corner as it was before. Same goes for arriving at doors--open them by standing out in front, or by stepping into the doorway? The choice should be yours.

Sample stop points from the new running system, which is like before only it stops one space sooner because it's looking for the same triggers out ahead.

Here's a sample of moving around using the latest iteration of the run command:

Automatic stops managed by the run command.

Other possible steps include automatically turning corners if moving down a narrow corridor that changes directions, although I think this is more suitable for other roguelikes (some have this feature), and not as common or useful in Cogmind. Of course QoL features always need to take a game's unique characteristics into consideration rather than blindly implementing them.

A more reasonable possibility is to mimic mouse-driven pathfinding's ability to optionally circumvent temporary obstacles like other robots. This is something that could theoretically be added for keyboard running as long as given the circumstances it won't change the distance of the path, although I'm not sure I want to go there because it could in some cases have negative consequences and maintaining predictability is important here. Not to mention keyboards are all about that fine control, so running to an obstacle then quickly choosing how you want to deal with it--maybe wait, or choose a direction to go around, is probably preferable.

Keyboard Pathfinding
One of the main features I wanted to tackle with this round of movement updates was keyboard-based pathfinding. Although a lot of keyboard users don't mind cellwise movement combined with a bit of running here and there, I always thought it would be nice if possible to choose a destination in keyboard mode and use a single command to move there via the quickest route, just like the mouse can by simply clicking on a location, regardless of how far away it is. So I've finally added it!

Using the mouse still has the advantage here and there were certainly some UX problems to work through, for example how to continue traveling to the destination after being interrupted--it would've been annoying to have to use examine mode to find the destination again!

To use this new feature, players have to be in examine mode (where you move the keyboard cursor around to inspect things) and simply press Shift-Alt-g (for "go") on the destination. The result is just like a left-click on that location.

Keyboard pathfinding demo (like using the mouse, holding Ctrl-Alt highlights the path).

Technically this exits examine mode for the move, but key to the UX is that the destination is remembered, so until another destination is set, any time Shift-Alt-g is pressed Cogmind will resume approaching the destination. This is essential for when passing by a move-interrupting hostile like a Watcher.

Keyboard pathfinding demo w/resuming.

Because it uses examine mode, keyboard pathfinding can also be useful when looking at items on the ground, e.g. while moving the cursor around to inspect salvage, if you find something you want a quick Shift-Alt-g brings you right to it.

For both this and mouse movement I've also finally made it so that setting an interactive machine as the destination automatically starts hacking it on arrival. After all, anyone who doesn't want this effect can choose an adjacent cell as their target instead, and most anyone who is clicking on the machine's terminal itself quite probably wants to hack it.

Pathfinding to a machine automatically starting the hack on arrival.

Adjustable Movement Delay
Another optional feature I've wanted to add for a while, one I'm quite curious if anyone will actually use, is to make the movement delay adjustable. "Movement delay" determines how long to wait before taking each move while traveling along a predetermined path, be it keyboard running or mouse/keyboard pathfinding.

Cogmind's default has always been 100ms, a balance between "getting there quickly enough" while still being just slow enough react to unexpected changes. Quite a few potentially dangerous (or at least important to stop and observe) situations in Cogmind will stop automated movement anyway, but moving too quickly is still somewhat dangerous for the same reasons autoexplore is a bad idea in Cogmind. Among them are situations that can't feasibly stop movement automatically, like threats on sensors changing directions, not to mention the high likelihood of wasting turns, which is generally bad in Cogmind since the passage of global time matters a fair bit.

Demo of fast movement with movementDelayInterval=10.

Running delayed by only 10ms is pretty crazy! (recorded before the addition of rules to autostop diagonal movement near some layouts)

As part of this update I also fixed the issue of the unreliability of stopping running/pathfinding in progress, even more important now that the speed is adjustable because the problem could have become more pronounced with lower movement delays. (Normally any input made while moving should immediately stop the move, but input is also generally blocked while actions are being carried out, and the way it was blocked happened to also sometimes be ignoring even input that should technically be doing the stopping xD)

Still, I don't really recommend changing this value from the default, I mainly just added it because it was easy to do and options are good, right? :P

Move Blocking
Stopping movement in progress, or even preemptively blocking a move before it begins, is an important part of roguelike QoL. (Technically this principle also applies outside movement as well, extending to other questionable or potentially dangerous actions, but this article is about movement in particular.)

I've heard players of some roguelikes (though not Cogmind, to my knowledge) argue that games shouldn't protect players from their own stupid mistakes, but I think of it as basic QoL because if anything this sort of protection allows for more efficient play without having to waste time thinking about avoiding stupid mistakes, instead focusing on in-game tactical decisions rather than fighting the UI itself.

Anyway, over the years I've been adding quite a few of these, and will keep adding more as necessary. Below are some of the movement-related blocks I've implemented (none of these are new)

Non-optional blocks:
  • New combat threats entering FOV
  • Ramming (this was one of the first new blocks added in early alpha, and I can remember how chaotic it was back then with players constantly ramming into non-combat bots while moving around)
  • Spotting a new hostile trap
  • Moving onto a known trap
  • Flying while overweight
  • Sudden system corruption effects like heat surge (sometimes responding with an immediate increase in dissipation might be necessary) and part rejection (don't want to leave some random part behind!)
Optional blocks (all active by default):
  • New non-combat enemies in FOV
  • Exiting to another map
  • Melee attacking a neutral target by moving into them
  • Melee attacking while flying (since the intent may be to simply jump)
  • Speed is very slow (>= 3 turns per cell)
The way temporary blocks generally work is they block the move and continue blocking movement for the next 500ms (while showing a warning message). This is important because movement is often a repeated action and players need time to respond to whatever it is they need to be noticing here, rather than just repeatedly mashing keys. Then once past initial warning period, there's a window of about 2500ms during which that same warning won't be shown again and the player is free to do that action (or maybe change their mind and do something else).

The one exception to the block window is spotting threats/enemies/traps, because those happen frequently and the main purpose there is to just block running/pathfinding rather than additional individual moves, so spotting a new enemy continues allowing movement freely.

What Else?
I'm sure more things will eventually pop up!

One internal movement-related feature that needs work is the pathfinding heuristic. The current pathfinding is actually pretty wasteful, and is one of the main processing bottlenecks for the game, but I've already done a few rounds of optimization as necessary and it's fast enough, so that's still been sitting by the wayside for if/when we need more performance improvements.

In its current state pathfinding (for all the AIs, mind you--just pathfinding for the player is negligible) doesn't cause problems under normal circumstances, though the heuristic is clearly off when looking at how it searches for a path, checking more cells than should be necessary:

Pathfinding heuristic at work :/

Anyway, I tried before and couldn't immediately find any way to effectively improve it (the obvious solutions weren't working for some reason xD), but there are also other ways to optimize pathfinding besides the heuristic ;)

Level 9

View Profile WWW
« Reply #1262 on: December 16, 2019, 04:02:06 PM »

Introducing "RPGLIKE", this year's Winter special event and all-new optional way to play Cogmind, with a completely different progression system and other significantly game-altering mechanics!

Raise levels, select permanent upgrades, repair your core and parts--keep your build :)

This mode plays with the concept of making Cogmind a little bit more like other traditional roguelikes, though combined with Cogmind's unique content opens up quite a few new strategic horizons.

For the full release notes and feature demo images, see here.

Cogmind Beta 9.3 "RPGLIKE" (191217) changelog:
  • NEW: Special event for Winter 2019, automatically activates between 12/17 and 1/1 (inclusive) for anyone who has played at least 10 runs
  • NEW: Command line argument "-forceMode:Winter2019" (or "-forceMode:RPGLIKE") to enable the Winter mode from 2019, regardless of system date
  • NEW: [RPGLIKE mode] Cogmind does not evolve, instead uses leveling mechanics with an XP system enabling free-form assignment of permanent upgrades
  • NEW: [RPGLIKE mode] Gain XP by exploring and/or raising the alert level
  • NEW: [RPGLIKE mode] Start with much higher core integrity, but only one of each slot type (can upgrade immediately in Scrapyard)
  • NEW: [RPGLIKE mode] 90% of incoming damage to parts instead transferred to core, thus losing parts is relatively rare
  • NEW: [RPGLIKE mode] Use Protomatter to restore integrity of core and parts
  • NEW: [RPGLIKE mode] Storange units do not exist and Cogmind starts with no base inventory, optionally expand capacity with level upgrades
  • NEW: [RPGLIKE mode] Dynamic build type analysis always shown above parts list, even before activating showBuildType advanced.cfg option
  • NEW: [RPGLIKE mode] Fewer Relay Couplers spawn, but all that do have double their normal value
  • NEW: [RPGLIKE mode] Extra "RPGLIKE" section in scoresheet containing mode-specific stats
  • NEW: "Alternative Rules" section of manual describes all previous special modes/events and how to access them
  • NEW: Mouse movement pathfinding and running via keyboard both stop on spotting a hidden door or phase wall
  • NEW: Keyboard mode pathfind to cursor (Shift-Alt-g in examine mode to set, same key outside examine mode to continue approaching if stopped)
  • NEW: Ctrl-Alt in keyboard mode also highlights path to most recent keyboard pathfinding target, if still valid
  • NEW: Pathfinding directly to an interactive machine automatically initiates hacking on arrival
  • NEW: Scan window shows faint map label buttons while no object info loaded
  • NEW: Item labels outside FOV remember which are Faulty or Rigged, include this status in label name
  • NEW: Item labels both within and outside FOV also reflect the "Non-functional" status (marked as "Broken")
  • NEW: Option to always close robot/item info windows instantly rather than animating the close (advanced.cfg: disableInfoWindowCloseAnimation)
  • NEW: Option to adjust movement interval for running and pathfinding (advanced.cfg: movementDelayInterval)
  • NEW: Option to have parts list always sort destroy-on-removal parts like Processors to the top (advanced.cfg: partSortSeparatesDestroyOnRemoval)
  • MOD: Running via keyboard stops before reaching corners and doors rather than continuing one space past them
  • MOD: Running via keyboard now supports layout-based autostopping on diagonal movement as well
  • MOD: Removed disablePersistentScanInfo/disablePersistentAccuracyInfo advanced.cfg options, both now default behavior by necessity
  • MOD: Keyboard running behavior matches mouse pathfinding when approaching stairs, allowing a run to exit a map if recently confirmed the exit action
  • MOD: All Gyrokinetic Inverter overweight penalties increased from 30 to 40
  • MOD: "Perfect Aim" achievement description specifies accuracy bonus from utilities only
  • MOD: Class name modifier "Mechanic" renamed to "Machinist"
  • MOD: Unidentified parts no longer display their integrity in Scanalyzer lists
  • MOD: Sorting inventory by type or integrity groups all unidentified parts together
  • MOD: Allies reactivated via Datajack no longer recalled automatically for subsequent "attacks"
  • MOD: Updated some major NPC parse text
  • MOD: Temporary allies gained via streamctrl_ hacks no longer follow to other maps
  • MOD: Dormant bot systems no longer accessible for RIF hacking purposes
  • MOD: High Security dispatch composition expanded to deal with a wider range of threats
  • MOD: More time to explore W base, tweaked composition of later attacking squads
  • MOD: [Pay2Buy mode] Hotkey for opening Cogshop change from '0' to '9'
  • MOD: [Pay2Buy mode] Cogshop windows displaced from bottom/left edges of map view to avoid covering intel markers and exit labels
  • MOD: Special game modes now override challenge modes, rather than the other way around
  • MOD: Toggling special modes or challenge modes via command line or advanced.cfg will not apply the effect unless game started for a fresh run (no saves)
  • MOD: "-forceMode:" command line argument's mode name no longer case-sensitive
  • MOD: "Challenge Modes" list in manual moved under new section "Alternative Rules"
  • MOD: Simplified Hacking immunity context help accessed via robot info page
  • MOD: All achievements are allowed to be earned regardless of active challenge modes or special modes
  • FIX: Holding cursor stationary while using 'f' to retarget a previously targeted robot that moved displayed incorrect base hit chance [Valguris]
  • FIX: Ejecting Relay Couplers from a just-opened Garrison Access might not be able to create the Couplers in some layouts [Valguris]
  • FIX: Any type of damage that didn't destroy a door could cause a malfunction, instead of just EM [Valguris]
  • FIX: Unpowered/Broken bots could still have active parts which might cause side effects [Valguris]
  • FIX: Controllable ally names might be the same if allies of same class acquired on different maps at the same depth [Valguris]
  • FIX: 0b10 Decoders attached to a hostile could give Cogmind info [Valguris]
  • FIX: Crash while pathfinding to a distant location and using keyboard to order nearby drones to RETURN and have a Drone Bay with free space [Valguris]
  • FIX: Hostile Programmers assimilating Protectors converted them to non-threat faction, causing Cogmind allies to stop targeting them [Valguris]
  • FIX: Warlord outpost in caves might have two Commanders, both of which could offer an escort in rare cases [CaptainWinky]
  • FIX: Crash in rare layouts while closing hacking window when that target machine is indirectly destroyed by the hack itself [CaptainWinky]
  • FIX: Abominations update began allowing Cogmind to use autoswapping to swap in unidentified parts [core_nxt]
  • FIX: Crash during a certain special event if player had specifically muted Prop audio levels, or had system audio off at the time [MitchellFJN]
  • FIX: Terminal dynamic key increased difficulty of hacks with negative chances of success, sometimes noticeable with hackware or Operator allies [Joshua]
  • FIX: Part autopair validity may not always be checked correctly, potentially even crashing on attempting to leave the map [Driana]
  • FIX: Becoming enemies with Zion after imprinting could still allow for terminal network hard line cut in 0b10 [Finestep]
  • FIX: Post-streamctrl_high behavior of Operators unusual [Benjamin]
  • FIX: "Winner's Signature" achievement was still possible if scanned by any Researcher, rather than only in a certain map [sideriver81]
  • FIX: Comparing different Datajacks showed a numeric difference next to their effect even though irrelevant to player [aperiodic]
  • FIX: Any potential [C]-type Relay Couplers unattached but in inventory on acquiring Crosswire RIF ability became usable from inventory [Pimski]
  • FIX: Crash on a Worker following deconstruct_machine orders on a Network Hub [Xii]
  • FIX: Beta 9.3 prerelease bugs hunted down by: [Terminus, Zyalin, NikolayAg, Tone, Xii]
  • FIX: Stopping a running/pathfinding movement in progress was not completely reliable
  • FIX: Potential crash if a Core Expander used while any info window open
  • FIX: Temporary allies gained via overwrite_iff hack or Autooverride RIF ability would follow to a new map if exited quickly enough after hacking

Level 9

View Profile WWW
« Reply #1263 on: December 29, 2019, 04:05:53 PM »

Leaderboards and Player Stats: The Old Way

[Cross-posted from the devblog here--follow link for better formatting and light-on-dark style.]

It's the end of an era! From May 2015 through October 2019, Cogmind used the same architecture for score uploading and leaderboard compilation that I'd patched together a few months before releasing the first alpha. That's all changing as of Beta 9 and the introduction of a revamped "Ultimate Roguelike Morgue File," so I thought I'd use this opportunity to share a rundown of how the old system worked before diving into the new one.

I must admit the old system was pretty dumb. I'm generally a proponent of brute forcing things using just what I know or can easily figure out and taking the simplest possible approach unless that really won't work, and it happened to more or less work here, so I took the path of least resistance and it stuck that way for years.

Being terrible at web dev and and having trouble wrapping my head around networking and databases and whatnot, for this period I opted for a human-in-the-middle approach that can be summarized as:
  • 1. Copy scoresheets submitted by newly completed runs from the temporary directory to where they'll be referenced by the leaderboards (the earliest versions of the leaderboards only offered name, location, and score, but this was expanded to link directly to the full scoresheet)
  • 2. Download all the new scoresheets to my local machine
  • 3. Run analyze_scores.exe to read in all the scoresheets and output the HTML data for the leaderboards
  • 4. Upload the latest leaderboards HTML file

I'm sure some combination of scripts could've handled this process automatically (and I did investigate and consider the possibilities), but I also justified keeping this workflow for years because having me in the middle for less than a minute each day at least allowed (forced) me to keep an eye on progress like how many runs were being completed each day, while also remaining vigilant in case something went wrong (this happened several times over the years as occasional bugs popped up, and I was usually able to respond before anyone else saw them because anything out of the ordinary had to make it past me first :P).

So literally once every day for 1,620 days I did the file copying and ran analyze_scores.exe on the data to produce the latest leaderboards. There were a couple days where I forgot or wasn't able to update on time, but they were few and far in between.

I appreciate the many offers of help I got over the years (since a lot of experienced web devs happen to play Cogmind :P), but I wasn't ready to take on help in this area when there was clearly lots more development to happen and changes to be made, and making these modifications alongside someone else would significantly slow the process.

I wanted to wait until closer to the end of beta when the scoring data was more stable and the format was finalized before doing something about it. "Doing something" being automating the process and making the whole architecture a lot more robust. For me, if long-term efficiency is the goal this sort of thing is best done once the specifications are clear and we're past the point of making sweeping changes.

So Many Scoresheets
Over the years using this method we accumulated 89,904 scoresheets, a total 1.0 GB of raw text data.

Cogmind scoresheet submissions per release, ordered by count (2015~2019).

Organizing the data chronologically probably tells a better story...

Cogmind scoresheet submissions per release, ordered chronologically (2015~2019).

A number of factors affected uploads over the years and across different versions, contributing to a lower number of scoresheets than we'd have otherwise. Here are some of the more significant ones:
  • There were a few weeks in early alpha where I'd forgotten to actually save the scoresheets to my own records before wiping the server data for a new release, so while those leaderboards are still available, the underlying scoresheets have been lost to time.
  • We lost maybe a couple thousand runs shortly after the Steam launch in 2017 with Beta 3. Here I learned that storing this many individual text files on a web server is not something you're really supposed to do, because they generally have a limit of 10k files in a single directory xD. I ended up having to quickly patch in support for multiple subdirectories, although this only affected by own analysis and data organization, not the game itself which could continue uploading to the same temp directory.
  • Score submissions were originally opt-in throughout Alpha, then later changed to opt-out when we joined Steam (to collect data from a wider group of players and get a clearer picture of the real audience), but then not long after we had to switch back to opt-in again starting with Beta 6 due to the new GDPR concerns.
  • The other reason behind the large drop heading into Beta 6 is that uploads were previously accepted from anonymous players, a practice that also ended with GDPR. Of all the scoresheets collected, 37,547 were anonymous (41.8%), though normally anonymous uploads accounted for two-thirds of the total within a given release, so if we were still accepting them now I'd expect to have about three times as many submissions from recent versions as we do now.
  • Earlier this year during Beta 8 the server went down for a couple weeks and wasn't accepting score submissions, and even after being fixed there was still an issue that prevented some scores from uploading.

In terms of getting a clearer picture of the changes over time, even the chronological graph is somewhat distorted because it's built on a per-release basis, even though some versions lasted only a month, while others persisted for several months or more. (Leaderboards are reset with each new release, rather than on a set time schedule.) Here I've compiled the monthwise scoresheet data, and annotated it with the above factors:

Cogmind scoresheet submissions per month (2015~2019) (open for full size).

The compound effect of launching on Steam while also changing all new installs to upload stats by default really blew up the data, and it was interesting to collect and analyze some aggregate player metrics.

Of course the reverse happened half a year later upon switching back to opt-in and ignoring data from anonymous players. It's true we could legally continue uploading anonymous data if it removes all unique identifiers completely, but to me data in that form is a lot less useful anyway, so for now I figure it's best to just ignore it all rather than bloat the data set. Maybe later...

Uploading Files with SDL_net
On the technical side of things, how did these scoresheets actually get on the server in the first place? Again this was a big hurdle for me since for some reason this sort of stuff feels like black magic, but at least I found some resources online and was able to slowly patch together something that eventually worked.

Cogmind uses SDL (1.2.14), so when possible I tend to use SDL libraries for features I need. In this case SDL_net is the networking library so I added that in early 2015.

The solution for uploading a file ends up being pretty simple (once you have the answer xD):

The basics for getting a file uploading via SLD_net. (You can download this as a text file here.)

That's on the game side, but the server also needs a way to actually create the destination file itself and write the content to it, which is handled by a little PHP file targeted by the upload.

All that's required on the server to accept the text data and use it to create a file locally (source, the extension of which would need to renamed).

And that's it, just drop the PHP file in the target directory, and from the game call something like this:

Http connection("www.gridsagegames.com","/cogmind/temp/scores/upload.php");
bool uploadSuccessful=connection.upload("filename_here.txt",DATA_GOES_HERE);

This process ideally needs to be run in a separate thread to keep it from hanging the rest of the game in case the connection is slow or has other issues.

So there you have it, that's how nearly 90,000 text files made their way to the server from 2015 to 2019!

The analyze_scores program is nothing to be proud of, that's for sure. It was technically implemented within Cogmind itself as a special mode, making it easier to reference all the game data, structures, enums, and constants as necessary. Of course it wasn't integrated throughout the game, just sitting there in its own file waiting to be ripped out one day.

By the time it was removed for Beta 9, it had bloated its way to over 6,000 lines, including lots of legacy code, unused features, bad organization, and confusing naming... basically a complete mess. I never bothered refactoring or designing it well in the first place because I knew it was going to be entirely replaced later on, though I guess at the time I didn't realize "later on" would come over four years later, and in the meantime whenever I needed to go back and make modifications or additions it was a real headache to even make sense of whether I was doing it right or sometimes even what I was looking at.

Anyway, bad code. Good riddance.

By comparison the recently implemented replacement is both elegant and easy to follow, with all static data properly condensed into an external text file. I'll be talking about that and more in a followup article (now available here).

Since I was stuck with it for a while but really didn't want to actually rewrite the thing, an increasing number of features were just tacked on in place, some of the more notable ones including:
  • An external settings file. This was added so I didn't have to actually recompile whenever I wanted to make minor changes to the program's behavior.
  • A banned player list. I eventually needed a way to ban players by ID, so there was a text file against which the files were checked before analyzing any player data.
  • A file of alternate names used by a single player ID. I didn't really need a file for this, but was mainly curious and added it anyway when finally implementing the ability for the leaderboards to detect and rank players by ID rather than name. The earliest iterations were based purely on names, which meant players could easily spoof other players, or individual players could easily occupy multiple places on the leaderboard by simply changing their name. Not very many players actually changed their name, and messing with the integrity of the leaderboards isn't a big worry with a community like Cogmind's, but it's better to head off the inevitable.

A big part of the early bloat came from the  "Alpha Challenge 2015" tournament/event. For that I put together pretty broad-ranging "achievement" ranking system based on scoresheet data, so in addition to regular score-based leaderboards, players were also ranked in 66 different categories.

Sample achievement results from AC2015. At first not all of the achievements were publicly defined beyond showing their name, so players weren't entirely sure how or what they were calculating until the event's conclusion, which helped prevent players from gaming the system which would've been easy (and therefore boring and unfair). Plus it was fun for players to guess what some of them might mean as they followed the event's progress :D

I wasn't sure whether I'd do another tournament like that, but I definitely wanted to, so the code stayed and it just sat there wasting time and space...

It was a lot of fun and I'd always looked forward to doing it again after first holding a similar mini-tournament in 2012 with Cogmind 7DRL, though in both cases we had a relatively small group of players so it was easier to manage, and "benefited from" no one being particular good at the game yet. Although I'd like to hold more competitions, there are two main roadblocks:
  • 1. A lot of the same people would win anyway--you can almost guess who they'll be :P
  • 2. It's not feasible to combat cheating, and there are enough players now that it would be a concern (especially if I offered real prizes, which I'd love to do as before).

There are some ways around these roadblocks, but various solutions comes with their own issues.

Anyway, back to analyze_scores.exe, it outputs a lot more than just leaderboards!

Files mostly created by analyze_scores.exe

Aside from the HTML file dropped onto the server, it also generates the materials to facilitate... you guessed it, analysis.

The userscores.csv file contains the complete contents of all submitted scoresheets for a given period, making it easy to examine the data in a single spreadsheet. There's also the _best version containing each player's best run so that each player only occupies one row, useful for different kinds of analysis.

Sample _userscores_best.csv data.

Two other CSV files contain precalculated stats based on userscores data, organizing select factors that I wanted to keep an eye on across versions, and for easy conversion into graphs.

Sample _stats_best.csv data. "Best" stats are useful for exploring user preferences, since there'll be only one set of data per player.

Although the userscores and stats analysis system were originally created for the tournament back during Alpha 3, it wasn't until later starting with Alpha 8 that I decided to report on stats with each new major release. This is useful for keeping an eye on the general status of the community, and more specifically how recent changes have affected the game (and how players are interacting with them). Plus some players just enjoy having access to this information as well.

Stats have been published 14 separate times so far, all of them in this thread on the forums.

History stats as linked from the leaderboards alongside the relevant period's scoresheet archives.

I'm not sure how we'll be doing stat analysis in future versions since analyze_scores is no longer a thing under the new system, but since from here on out we'll have all the scoresheets collected in a brand new protobuf format rather than a trove of text files, it shouldn't be too much trouble since presumably there is software out there we can use to run the analysis on that collection of data. More on that later!
« Last Edit: December 29, 2019, 04:17:21 PM by Kyzrati » Logged

Level 9

View Profile WWW
« Reply #1264 on: January 10, 2020, 01:08:05 AM »

Special Mode Design: RPGLIKE

[Cross-posted from the devblog here--follow link for better formatting and light-on-dark style.]

Banner image from the Beta 9.3 "RPGLIKE" release.

This winter holiday season I released Cogmind's seventh special mode, "RPGLIKE," and quite unlike other events which have not necessarily been designed as permanent parts of the game to promote going forward, this one definitely is, and serves a specific purpose in that regard.

A number of people are interested in the world of Cogmind, but find that it's extremely unique mechanics don't click for them, most specifically the rampant item destruction, heavy item management requirements, and generally decent level of tactical prowess required to succeed. There are difficulty settings to somewhat mitigate these aspects, including even more recently the ability to quick save/load in all but the hardest mode, but those still don't change the fundamental nature of adapting to loss and dealing with natural attrition, characteristics that permeate the normal Cogmind experience by design.

So I thought I'd try an experiment in attempting to convert Cogmind gameplay into an optional experience more similar to other traditional roguelikes. This means a number of things, most importantly a system for permanent progression, the ability to heal yourself, and items that don't break.

Early Concepts
The earliest ideas for this mode were even more extreme than the final result (which is itself a pretty extreme departure from regular Cogmind :P). They assumed your parts would be completely immune to damage, and that you could simply heal either by "resting," or gradually over time--basically your usual CRPG/roguelike mechanical tropes.

However, the design went through a number of iterations before implementation even began, because as I tried to run the numbers and make sure there would be some semblance of balance (also taking into account likely player strategies given each scenario), it became apparent said tropes in that form really couldn't exist in the world of Cogmind and keep the game fun at all. I mean sure they'd be fun insofar as it can sometimes be fun to just run around practically invincible destroying everything, but there would basically be no challenges unless I also put a lot of focus on changing the nature of the existing challenges.

But with a mode already planned to be this big, it wouldn't be reasonable to take on yet another huge amount of work on top of it, just for a special mode, so those starting points inevitably had to be scaled back... but we'll get to that later. The implementation really started in earnest with one of the less questionable aspects: gaining XP and using it to choose permanent upgrades.

Instead of the usual evolution effects with each new depth as Cogmind approaches the surface, even basic stats like slots, max core integrity, and heat generation would be gained as XP-earned upgrades. But this being "RPG-like," we definitely need more stats to modify on level up...

I started with a broader and longer list of factors the player could theoretically be given control over as they leveled, but pared it back to below 26 because I wanted them all to fit in a single window, visible without scrolling, while still being entirely accessible via letter keys. (This is yet another of the many cases in which Cogmind's design is guided by UI restrictions, rather than prioritizing content over ease-of-use, but that's honestly the best way to go about it because there's plenty of design space within even much tighter restrictions, so usability should generally be the priority.)

The internal enum listing all valid upgrade types.

Notice that many of these upgrades overlap with existing item effects, at least in part if not entirely. This honestly isn't an ideal way to build this mode, which would benefit more from having every single upgrade provide or improve a unique ability unable to be acquired via any other means. But the better alternative would be a huge undertaking, whereas basing upgrades on existing systems and code is fairly quick by comparison--altogether it took a couple days to build the upgrade UI and get it hooked in with the game's data that it could modify.

Having some overlap does, however, enable the player's progression strategy to emphasize one of flexibility (more slots, like regular Cogmind which is maximum flexibility) or safety/consistency (using permanent upgrades), especially in cases where the functionality they're after can come from either a part or upgrade. Upgrades are naturally also the more accessible of the two options, since they only require XP and can be obtained at any point, rather than finding the relevant part (and better versions of it later).

You can actually graph when it's more effective to have a part for a given effect vs. the upgrade, to a certain extent, weighing the cost of the upgrade vs. the cost of evolving the required slot, but the calculations change over time depending on the necessary part's precise effect, and how many slots the build already has, since the latter get increasingly expensive. Trying to optimize these decisions can be complicated yet further by additional requirements in some cases. For example increasing raw energy generation is a simple straightforward way to get more power, but power sources can do the same thing and also come with more storage capacity for surplus energy, though also produce heat, require additional mass support, and occupy an additional power slot (yet another upgrade).

Relative costs are clearly the most important balancing factor here.

XP is used to increment upgrades, and each has a base cost, a modifier (a static value for the amount of stat increase per upgrade), and a cost modifier (a static value for the amount of increase in cost for each additional time an upgrade is incremented). For example, the first upgrade to sight range costs 100, increases by 1 per upgrade, and each upgrade after the first adds 200 to the cost (e.g. 300 to upgrade it a second time).

RPGLIKE cost upgrade graph for sight range. (Cogmind's base sight range is 16, so its first upgrade brings it to 17.)

The result of this system is a linear increasing cost for repeated upgrades, essentially adding to the cost of specialization. 1,500 is the amount of XP available to spend at each new level raised, so according to the graph the 8th sight range upgrade, from 23 to 24, requires an entire level's worth of experience! At that point (or even before) it's probably more cost effective to add another utility slot and attach a part that extends sight range, depending on how expensive utility slots are getting :)

As for where the raw numbers for different upgrade costs came from, I wanted to start with a base cost of 500 for a single first slot upgrade, and use that as the basis for all other costs. This makes sense since slots are central to Cogmind's balance to begin with. The particular value of 500 also 1) gave enough room below it to fit the other lesser upgrade base costs and 2) wasn't too long in terms of digits (even after the intended increase in costs over time) to mess with the planned upgrade UI layout. As usual, before starting any of this I'd already mocked up the UI:

Early WIP mockup of the RPGLIKE mode upgrade menu (incomplete). Created with REXPaint.

To be sure relative costs were about right without needing much actual playtesting, I built a spreadsheet in which I could drop in different base values, cost increments, and stat modifiers to see how they would affect the progression and player abilities at each level, especially in comparison to other upgrades.

Interactive chart for testing relative upgrade costs in RPGLIKE mode. Variables go in the cells with colored (non-white/gray) backgrounds towards the left and everything else is calculated automatically, including some useful automated formatting to highlight various aspects.

Without an interactive chart something like this would take forever, and although I spent a good couple hours poring over these numbers, once it was done and I went in to actually playtest, very few changes were necessary afterward.

One of the big questions early in the design was what to do about inventory capacity? Too large an inventory would be both boring and also doesn't really contribute much since in RPGLIKE you don't need to carry spare parts to combat attrition like you do in the regular mode--seeing as your parts won't be destroyed, you just need a little space for the occasional consumable, or a handful of alternate parts for special situations.

Thus I decided it would be better to fold inventory capacity into the upgrade system and have each slot be very expensive, while starting with no capacity at all!

On the technical side, we already have the Pure Core challenge mode (no inventory allowed), which automatically converts any Storage Unit you step on into matter, but that was more of a janky solution which feels weird for the more "serious" tone I wanted to retain for RPGLIKE, since it's obviously not realistic and you can still see Storage Units as parts, and on other bots which use them.

For RPGLIKE I went a step further and made it so that Storage Units essentially don't exist. On startup, all robots equipped with Storage Units have them removed and their base inventory capacity is increased by a corresponding amount, changing the underlying game data in the process. Then of course I had to make sure it still wasn't possible to get them via other means, like through fabricators, schematic hacks, or any kind of random spawning, and at first that seemed like it was going to take ages considering all the possibilities...

Then I remembered I could just use an existing "item distribution" setting and automatically convert all storage parts to "unique parts that can only be placed manually by the game", as if they belong to the ranks of very high-rating special gear, and just like that they won't be accessible through any other means :)

Of course this approach cannot handle cases in which Storage Units are actually manually added to the map via prefabs, so for those I fell back on the Pure Core method and just convert them all to matter, which is fine because the player will never actually see them as Storage Units to begin with.

With such low inventory sizes, Relay Couplers were also given special consideration. Builds focused more heavily on bothacking will want to carry spare couplers, but even at the high end inventory sizes in RPGLIKE are generally going to be only between maybe a quarter to a third of what you normally might have, so all Relay Couplers have their value doubled.

I prefer to avoid capping upgrades if possible, but there are some upgrades which would simply be too powerful without some kind of limitation. Technically we can enforce a more "natural" limitation by having those particular upgade costs scale very quickly, but because I decided to have costs scale linearly, trying to put later levels out of range would also put even earlier/mid-level upgrades out of range, so that approach wouldn't work as well.

Instead I had to put an artificial cap on those upgrades which would be far too powerful if players focused on them, namely damage resistances and damage modifiers.

Example of upgrade caps in action.

(continued in next post...)

Level 9

View Profile WWW
« Reply #1265 on: January 10, 2020, 01:08:27 AM »

(...continued from previous post)

"XP" for applying towards upgrades is made available in chunks, one per level, where each level raised both requires and provides 1,500 XP.

Because I decided to have earned XP translate directly to the value used for upgrading (i.e. there's no additional/separate unit of value awarded at each level to use for upgrading), and upgrade costs increase with specialization, thus it makes the most sense for the amount of XP per level to remain static. Yes we lose the option of having inflationary XP-per-level thresholds often seen in RPGs, but it keeps things simpler both on the inside and outside :)

Target approximate XP gains per depth, with corresponding values.

The total XP target for each depth comes in handy for balancing costs and XP gains. To make sure the numbers would work out, I put together a separate "build theory" table with some sample slot arrangements likely for a given depth in a regular (non-RPGLIKE) game, and had it automatically tally what this build would cost in terms of XP:

Build theory calculation table, as used for balancing RPGLIKE mode.

Because basics like core integrity increases and minimal heat dissipation would no longer be included as benefits of Cogmind's natural evolution, I also tallied the total cost including those corresponding upgrades (including also base inventory capacity) to arrive at the true XP cost of a regular build. By comparing the total XP cost to what a player would likely/hopefully have at a certain depth, and taking into account the cost of optional upgrades, I could see how much leeway there would be for builds compared to the regular mode and adjust for a desirable progression and power level that way.

Sources of XP
The latest April Fools mode, "Pay2Buy," had a system one might liken to XP in the form of earning CogCoins for purchasing parts from the store. It was based entirely on accumulating alert, since alert in Cogmind already translates to difficulty, by design, so the more trouble you cause, the more you earn, and therefore the more you also have to deal with the consequences of your actions.

For RPGLIKE I wanted to use that same system, relying on alert increases to award XP, but because this was to be more than a little temporary event, the system needed to allow for a greater variety of play styles, and therefore required a somewhat wider variety of XP sources.

I thought of possibly adding very explicit sources of XP unique to RPGLIKE, such as certain enemies or special locations, but again, variety is better here and my eventual conclusion according to my notes was that "XP needs to be from whatever actions we want to incentivize, so it should really be a combination of things."

So in addition to alert, which already encompasses a range of actions that tie into creating mayhem, I also decided to award XP for all sources of bonus points. Most of these resemble "XP bonuses" you might find in an RPG for plot-related encounters, and also tie into ally-caused destruction, allowing allies to help you earn XP as well just like they help raise your score (important especially for those builds/runs that frequently rely on help from allies).

But the largest single contributor to XP, or at least on par with alert-sourced XP for combat builds, is actually a separate category: Exploration. One of the defining factors of regular Cogmind progression is that your core improvements come from "evolution" automatically as you approach the surface, meaning you don't have to grind out levels or worry about accomplishing specific tasks to remain effective. This leaves a lot more room for freedom to try a huge range of play styles, so I decided that exploration is far too important to pass up as a source of XP, since anything else would end up limiting creativity.

Simply visiting different maps gives significant XP rewards, where main maps are worth an entire level's worth of XP, while the value of branch maps varies, but is always at least a third of that for each map. A few special (or especially dangerous) maps are even worth more than one level.

After playtesting with it I was very happy with the result, and from sample runs I've seen by other players in RPGLIKE mode so far, regardless of style their progression tends to be at least somewhat close to the intended targets outlined above.

Level Curve
That observation can also be explained by a built-in XP adjustment that tries to maintain a tighter "level curve." (Level progression itself is indeed linear, although if we graphed the XP levels reached by different players at a given depth it would of course result in a curve.)

To keep players from getting too far ahead of the curve, diminishing returns on XP gains are applied beyond a certain point (specifically the "target max level" for a given depth). It's not a huge immediate falloff, and one can still get some levels ahead, but the returns do get smaller and smaller until hanging around on the same map farming alert for XP is really not worth it, not when you can head up to the next depth and earn those same levels much more easily.

I also wanted to prevent some players from falling behind the curve, but decided this wasn't necessary in Rogue mode (the hardest difficulty setting), so in Adventurer and Explorer difficulties the reverse of the diminishing XP formula is applied to XP gains by players who are below the minimum target level, allowing them to more easily catch up if they've somehow fallen too far behind.

(Here I'd like to share some sample graphs of level curves from our data, but sadly although the data has been collected, the leaderboard system to access it has not yet been completed...)

The upgrade menu is accessible at any time.

I originally thought of doing upgrades during Cogmind's normal evolution process, but realized 1) this would require two new UI windows and be more complicated to implement and 2) was clearly thinking too much "inside the Cogmind box." I mean it should be like most CRPGs where you can get your new goodies at any time, right? :)

So in RPGLIKE, whenever a new level is hit there's a notification and the menu is always right there. XP can even be saved for later, accumulated for an upgrade that's become too expensive for a single level, or for other strategic purposes.

Starting Conditions
Naturally for a mode as different as this, it makes sense to have unique starting conditions. It's also an opportunity to add a bit of CRPG-like "character generation" right from the start.

Players start with a chunk of initial XP (more for lower difficulties) that can be spent immediately on upgrades to start defining their build. The base amount in Rogue mode is set at just enough to create what is more or less a normal starting loadout:

A Rogue mode RPGLIKE start with upgrades defining a standard starting build (7 slots + 4 inventory), minus one inventory slot since they're quite expensive in this mode but also not nearly as important.

Starting core integrity is higher than usual, since that's what takes the brunt of attacks instead of parts, unlike the normal game.

The base starting build before any upgrades is only 4 slots! This is the first time a Cogmind build has the option to only ever rely on a single Propulsion/Utility/Weapon slot. (Because I was curious and wanted to try it out, I actually did a complete

recently :P)

There's also no inventory capacity by default, but again it's not as important in this mode, so most people will/should start with fewer than 3 upgrades there and reallocate the significant XP savings elsewhere on multiple cheaper but effective upgades.

The upgrades UI appears in the same location that Pay2Buy did, and resembles it in some ways, but because the latter's expanded form actually made use of a generic list class that I built for use throughout Cogmind, while the upgrading would require many more unique interactive features, I had to write this new one from scratch. No problem, I do rather enjoy designing and building interfaces :D

First, because it could be easy to miss the fact that you've raised a level in the first place, especially because it often happens when other things are going on, aside from the inevitable message log event there's also extra feedback in the form of a unique sound effect and blinking indicator above the level/XP summary. I don't want any of Cogmind's notifications to be modal or anything quite so interrupting/in-your-face/immersion-breaking, so that's as far as I went.

Demo of raising a level and assigning a few upgrades with the mouse.

As usual I always want everything to be fully accessible via both mouse and keyboard, and in the case of the latter there are even three different input schemes. The standard Cogmind approach is of course lower/upper case characters for increasing/decreasing their respective values. Also with lists like these it's nice to be able to navigate directionally, so both arrow keys and numpad can be used to move the selector up and down, with left and right incrementing and decrementing the current value.

Demo of pure keyboard control in the RPGLIKE upgrades interface.

As you can see references for key commands are built into the interface itself, making them easy to learn. The "Up/Down/Left/Right" in the corner isn't really attached to anything, but players will generally intuit that it refers to key commands and try them out, seeing the effect it has on the UI.

Probably the biggest challenge with a UI like this is that upgrades cannot actually be applied until confirmed, but before that point it's still necessary to show their state, modified cost, limits, etc. given the desired upgrade(s). This can get somewhat complicated, and also potentially require a fair amount of duplicated code for various purposes.

In the end I used a solution that simply retrieves direct memory references for respective stat values, which can be used to both query the current base value (and temporarily modify it as necessary) as well as apply each modification later once confirmed. The amount of code involved ended up being quite small, but could have been larger if the upgrades were more complicated than simple integers (and integers where positive values are always good, at that!). I did actually remove one planned upgrade partway through implementation because it would break the elegance of this system :P

Character classes are a staple feature of most RPGs, but at odds with Cogmind's normal free-form build-as-you-go approach. This being "RPGLIKE" mode, it sure would be nice to fit classes in there somewhere...

Fortunately Cogmind already had a built-in feature that would help here: the automated build classification recently added with Beta 9. It analyzes your current build and assigns it a base class name with maybe a special modifier, but must be activated manually (doesn't appear by default) because that particular feature didn't really fit with the type of immersive atmosphere I wanted to create for Cogmind. Regardless, it's certainly appropriate for a mode like this, so I made it active despite whatever the advanced config file says. A fair number of people who didn't know about it before will probably even think it's unique to RPGLIKE :P

Sample "Skirmisher" class, a combat bot supported by infowar utilities. Se more samples and a breakdown of how the system works in Building the Ultimate Roguelike Morgue File, Part 3: Mid-run Stat Dumps, under "Build Categorization."

The classification system does take into account the effects of RPGLIKE upgrades when deciding on a class, which took a while to merge with the classification system and wasn't even present in the earliest prereleases since I wasn't sure I'd have enough time to get around to it, but I'm glad I did because I think it's pretty important for accuracy purposes given that many of the upgrades would be taking the place of various slots/parts.

Compound class types from a Cogmind run as they appeared in the Dominant Class section of the scoresheet.

(continued in next post...)

Level 9

View Profile WWW
« Reply #1266 on: January 10, 2020, 01:08:41 AM »

(...continued from previous post)

Exactly how to restore core integrity would be a pretty central point of RPGLIKE gameplay, but I still hadn't even figured out how it would work while already building the UI and setting upgrade costs. Since the first "purely RPG" ideas like resting-to-recovery or gradual recovery couldn't really work balance-wise in Cogmind, it seemed I'd have to wait for a better solution to pop up, and at least there'd be spare time in between working on the other features to mull over different possibilities.

Healing over time would have clearly been boring in so many ways, not unlike it can be in some other roguelikes! But at least these other roguelikes are specifically designed around individual encounters, where you're often at full capabilities for each one and when you go into a given battle, it's you vs. that current enemy/enemies which you'll probably either squash or which might have a chance to kill you if you make too many mistakes (maybe even just one mistake xD).

Cogmind has always been more about attrition and tactics vs. a much larger complex and numerous potential enemies, which individually don't really pose a threat to you. So that whole central aspect of the game (and all the content and balancing associated with it) would have to change for rest/gradual-healing to be feasible, and as I mentioned earlier that's outside the scope of this mode, and also unnecessary anyway since there are other methods.

Another problem particular to healing over time is that Cogmind doesn't have the consumables most other roguelikes do in order to handle short-term variance, consumables like... health potions! It's from here that I started taking a new approach to the idea of integrity restoration, and realized we'd need a whole new item to do it.

Thus Protomatter was born, a whole new item permanently added to the game for a special mode, and in that sense the first of its kind. (One other event, the holiday mode from 2018, also added items, but that mode no longer exists so neither do the items associated with it.)

Protomatter is basically like a health potion, dropped randomly by some combat-capable enemies instead of regular Matter, and used to restore core integrity (or if one's core is already maxed, it repairs any damaged parts).

I definitely didn't want it to be like health potions in other CRPGs where you can simply chug them when in danger for an instant boost of HP, possibly even up to full. Having it take time to use would be more appropriate for Cogmind, and add a bit to the tactical decision of when and where to use it.

The original implementation (that patrons[/url] tried out in the first prerelease) was simpler but quite funny: It determined how much of the Protomatter was required for a full heal (or to use all of it even if not enough for a full heal), then calculated the required number of turns to do that, and applied it all as a single uninterruptible action. That was by far the easiest way for me to implement it rather than spreading its use over multiple turns, but the way the numbers worked out this meant you could in some cases end up sitting there applying Protomatter for 15 or more turns! One can imagine the potential consequences of such a long action--enemies you didn't even know were there yet might round a corner and start shooting you to pieces :P

Instead I ended up having to take the more complicated route and have it apply on a turn-by-turn basis, with pacing determined by the player who could simply wait while standing on top of it in order to apply the next batch. Some of the complexity came from the application process itself (mainly where it involved attached parts), but also simply from properly handling the messaging system so it would show the desirable results once you'd finally finished applying Protomatter, rather than spamming the message log with too many individual messages.

At first I wasn't sure what to call this item, but it soon became obvious it should be related to Matter because:
  • Protomatter would similarly be a pretty fundamental item throughout a run
  • Protomatter would sometimes be dropped as salvage (instead of regular Matter) (note that to avoid destabilizing the existing balance, all Matter drops were increased a bit as well)
  • Like Matter, it's affected by salvage-modifying attacks (although unlike Matter it can never have its amount increased by a positive net salvage modifier)
  • I would need a tile for this new item, and the Matter tile would be a good choice here since it's otherwise only used once and doesn't fall into any other category

An enemy Programmer dropping salvageable Protomatter instead of regular Matter.

At the same time, I wanted to also differentiate it from matter because it not only has a different purpose but would also have different fundamental behavior, so I gave it a unique naming scheme, "Protomatter-XX" (e.g. Protomatter-56, where 56 is its remaining amount).

Protomatter behaviors that differ from Matter:
  • Can be picked up as an item and held in inventory (not in containers like Matter), important for allowing some backup repairs depending on how much inventory capacity you have and want to devote to this purpose.
  • Suddenly decays randomly, disappearing from the map (unless in inventory or currently under the player), as it's important to prevent stockpiling Protomatter on the map itself, since in the right hands that just makes it easier to become invincible.
  • Cannot be merged or stacked, because that would also make it too easy to stockpile unless some kind of arbitrary limits were put in place, but may as well do with that altogether since it just unnecessarily complicates things.

On the topic of naming, the first options considered for a moment then thrown out were to just jokingly call these Health Potions, but even though it would be really in theme for this event, RPGLIKE is meant to be a more serious mode so I had to come up with something better. "HP Kit" or "HP Unit" were similarly passed over :P

Protomatter info.

Damage Transfer
While working on the new "healing" mechanics, I decided this was an opportunity to change the initial idea that all incoming damage would go straight to your core, practically doing away with item destruction entirely and behaving more like your average roguelike with RPG-like progression.

Reducing the role of item destruction is definitely one of RPGLIKE's primary goals, but completely removing the risk of that happening felt like it would unnecessarily gut a lot of the feeling of Cogmind--your parts always appearing in perfect shape would be fairly awkward, and we can get the anti-item destruction effect without going to that extreme, by just redirecting most of the part damage to the core, instead of every last bit. This also helps retain some of the coverage-related balance inherent in Cogmind's part stats (there is definitely noticeable destabilization, however--that's unavoidable).

So 80% of damage to parts goes instead to the core (it's funny because there's actually a part in the regular game which has this exact effect, although naturally the strategic implications are quite different there due to the lack of frequent core restoration). Even though it seems you don't really lose many (or any!) parts in this mode, it still feels more natural if they're taking a bit of damage from attacks, and it could still come into play if you're playing very poorly or incorrectly managing Protomatter reserves and acquisition.

Honestly I think we could probably do with a lower percentage than 80, at least for Rogue mode, and it would make RPGLIKE more challenging while still retaining its uniqueness., but that's a slippery slope that leads right back to the default Cogmind experience ;)

While on the subject of healing, I should mention that several times I considered allowing XP to be used to repair current core integrity as separate from the current/max integrity increase that it ended up as, but ultimately decided against allowing that since upgrades were meant to be instantaneous and that would be just like the "emergency chugging of potions" I was trying to avoid.

As a more permanent official mode recommended for some players, RPGLIKE also got exclusive treatment as far as the scoresheet is concerned.

The history log records slot upgrades (since they'd normally be reflected in evolution messages but those won't happen in this mode), as well as each level gained (since that aspect of progression is pretty important to the mode and can be interesting to see in the context of other events along with the turn counter).

Excerpt from an RPGLIKE run scoresheet's history log, showing level raising and slot upgrades.

RPGLIKE also gets its own section in the scoresheet, recording many other details on a per-map basis.

Sample of a dedicated RPGLIKE scoresheet section.

What's Next?
Could RPGLIKE mode be better? Yes, in many ways! I mean this is no surprise given that it's a mode designed on top of another game and basically turns it on its head :P

I do plan to still do some more work on RPGLIKE mode, or at least tweak it. Precisely how to improve it also really depends on the goal of doing so, since what constitutes an "improvement" is subjective, and in its current form it's most definitely not the primary way I would want to play Cogmind.

I mean I've been having a lot of fun with it, as you can see from the already several streams I did in this mode:

  • - An introduction to the new mode plus a relatively quick but complete run based around one of the overpowered EX-tech parts I'd never used before (spoiler: we torch 0b10)

  • - No FarCom, no RIF, no imprinting. Just a pure kinetic combat build out to shoot anything that gets in its way.
  • RPGLIKE 4-slot limit "Babymind" run - No slot upgrades allowed, just 4 slots total straight to the end. We go mostly melee, a bit of hacking, and using allies to do much of the fighting. (Several big guys fight on our side because FLK :D)

An introduction to the new mode plus a relatively quick but complete run based around one of the overpowered EX-tech parts I'd never used before (spoiler: we torch 0b10)

But it's far too easy. For the first iteration this was intentional though--I guided it towards the easy side for a couple reasons:
  • It's a holiday event! For something like this it's better to aim for fun over anything else. After all, it's optional and not like it removes the regular mode, anyway.
  • In games there's often a fine line between too easy and too hard when you have a healing system, certainly much finer than Cogmind's usual death by attrition and an accumulation of long-term mistakes rather than one or two recent mistakes. Designing a healing system that can ride that line more closely would take a lot more theorizing and playtesting than there was time for. Heck it might even be impossible given Cogmind's other mechanics.

My personal main goal for RPGLIKE's theme was to add a system of permanent progression and all but eliminate part destruction, and it satisfied those goals well. It will never be heavily balanced like the regular game--that would require too many changes, but it's still fun either way, and at least the challenge level can be tweaked. Those who enjoy this mode aren't necessarily looking for complete balance anyway, at least it doesn't sound that way from all the feedback :)

Bonus: RPGLIKE Strategy Notes
While playtesting RPGLIKE I was noting down various strategies and/or observations for later reference:
  • It seems to get easier over time, as is generally the case with other "RPG-like" roguelikes but quite the opposite of regular Cogmind (which tends to get harder as you progress)
  • That said, you also gain levels very quickly at the start (plus have extra XP to spend on upgrades you normally wouldn't have) and as long as you can ensure you don't destroy most of the Protomatter out there, it's unlikely you'll actually die.
  • Either way, you generally feel a lot more free to be reckless because damage can generally be repaired, and mistakes aren't going to be as costly in the long run like they normally are.
  • Inventory capacity is going to be low throughout the run, but that's okay because you don't need spares. It becomes more of a simple storage for items needed in alternative situations, or even consumables ("health potion" Protomatter, and in one of my runs I had a PSU Rigger so I just kept filling my limited inventory space with nothing rigged power sources :P)
  • Can use more/different types of items you might not otherwise normally keep attached, since they won't break! This is especially useful for unique parts that cannot normally be replaced.
  • There's little reason to use anything slower than hover unless you want siege mode or other tread benefits, because propulsion is much more protected in this mode anyway, and even mass support can be gained via upgrading.
  • Repairing core and parts is separate, and core is often more important, so it can be advantageous to save your Protomatter specifically to repair core rather than worrying about parts, which can be replaced, after all. However if you've upgraded core integrity quite a lot and then lost much of it, getting enough Protomatter to repair both core and parts can become difficulty, putting attached unique parts at risk.
  • Because you generally have few to no spare parts (since you don't normally need them, or can't spare any inventory space), cave-ins are extremely dangerous, even more so than usual. To a lesser extent the same goes for other effects that remove and/or directly damage parts such as Blade Traps, Saboteurs, etc). The most dangerous effects are technically avoidable, though.
  • Honestly in it's release state it's kinda like a wizard mode for testing the effectiveness of builds, at least in an offensive capacity, since you can try them in different scenarios without fear of inevitably losing them after a period.
  • Can save XP for later when you really need it, either to buff some ability that will be of immediate use, or to increase core integrity in a pinch.

Some of these may no longer quite be as applicable after updates, but they're relevant as far as the Winter 2019 event goes ;)

Addendum: Beta 9.4 Updates
Not long after this article went up I released Beta 9.4, mainly as an update for RPGLIKE mode. It didn't involved any sweeping changes, and you can read about some of its other tweaks in the linked release notes, but here I did want to at least mention that the role of armor-type parts as protective gear was restored for Cogmind.

The solution was to simply have armor absorb more damage than usual (40% instead of 80%), turning it into a sort of consumable in the RPGLIKE world of otherwise far less consumable parts. This means builds can use armor as a way to avoid the need to rely on acquiring as much Protomatter.

Further changes will contingent on the size of RPGLIKE's post-event player base and the data we see from these runs.

Level 9

View Profile WWW
« Reply #1267 on: March 03, 2020, 05:24:30 PM »

Special Mode Design: Battle Royale
[Cross-posted from the devblog here--follow link for better formatting and light-on-dark style.]

Every good game needs a Battle Royale mode, right? Okay maybe that's something you'd be more likely to expect from an actual online multiplayer AAA title looking to jump on a bandwagon, rather than a traditional roguelike :P

Nonetheless, I did build one for Cogmind! It was going to be Cogmind's next April Fools Day event, with the idea originally sparked by a player's "what if"-style comment on Discord earlier this year.

If you're not familiar, "Battle Royale" is basically free-for-all survival of the fittest gameplay across a shrinking play area filled with random gear. So here you'd basically be up against a bunch of other Cogmind-like bots trying to survive. I'd never actually played any of the staple games in this genre, my first and only relevant experience coming during 7DRL reviewing for 2019, when I played B-Line, a take on the BR genre within a traditional roguelike framework.

I say "was going to be" the next AFD event because although it reached a playable and somewhat fun state, I ended up cancelling it! I'll talk more about why later on, but first let's look at the development process and its challenges and solutions...

Like many ideas, as a pure concept "Cogmind: Battle Royale" sounded pretty interesting, but I wasn't sure just how feasible it would be on a technical level. I mean sure it's doable, but would the cost be worth it? A pair of very important questions needed to be answered first, so development started with an exploratory phase directed at answering them before actually building this as a special mode.

The first question had to do with factions. Cogmind's whole relationship system is based on a limited set of hard-coded factions, and there are only 10 of these internally. How to build a system to support free-for-all hostilities between numerous robots? The most straightforward solution would be to dynamically create a unique new "faction" for every single robot. What might this break? I had no idea, since lots and lots of assumptions had been made and reinforced since development began in... 2012 for 7DRL xD. I wasn't sure how flexible the faction system was, but this was a natural place to start since it would be much easier to test than question #2 to come. I simply created a bunch of extra factions and dropped a single Grunt in each, heading off the few problems that might result and sure enough, each one was running around shooting anything that moved and otherwise behaving as expected. Yay!

Grunts successfully wreaking havoc on -10/Materials, and each other.

The second question would unfortunately be much much harder to answer. It would take a while to explore the feasibility of an AI with Cogmind-like behavior, having the ability to put together and maintain a build from found and salvaged parts, and also manage inventory.

Now if I was just doing this purely for a short special event then I'd be less willing to venture into complex AI territory, essentially because it's an endless time sink (!), but I liked how this little detour could bring me one step closer to another project I've thought about off and on over the years: Having a bot that can actually play Cogmind.

So it was worth a shot and I spent some days hacking together an AI much more complex than anything else in Cogmind (robots normally have relatively simple and predictable behaviors unique to their class, where interesting scenarios are produced by interactions with numerous AIs at once rather than especially smart and capable individuals).

AI Development
Technically I wasn't starting from scratch on this AI. Quite conveniently there was already another smaller stepping stone in place: Abominations from last year's Halloween event.

Abominations in that mode are capable of gathering parts to build themselves, but do so very haphazardly and take a lot of shortcuts, being capable of telekinetically attracting any parts they see and pretty much ignoring balance because they don't need to worry about energy or heat and always have a permanent form of natural propulsion and built-in backup weapon. For build management purposes, architecturally there's a pretty big difference between an AI allowed to both decide on and complete an action in a single moment, and one that makes a decision then follows it up over multiple turns in a changing environment.

In short, Abominations are a far cry from a true Cogmind-like inventory management AI. But they did require repurposing the player item autoswap feature for AI use, which would form an important backbone of the new AI. As small as it was, at least that bit was already done. To recap, back in Alpha 5c (2015) I added the ability to use a series of simple and predictable rules and to automatically perform obvious inventory management actions on request.

The original diagram I made to explain the smart/automated inventory management system back when it was first added.

Nearly all the same logic could be used by AIs as well, so we have a pretty solid foundation to work from!

The new AI clearly still had a wider range of needs, though, so at this point I didn't actually start creating the new mode or a Battle Royale map, instead basic AI testing simply happened in a regular Cogmind map. In the first phase of development, I added the following features in this order--the AI could:
  • use core hover (normally all robots other than the player are immobile if they have no external propulsion)
  • switch to different faster forms of propulsion if more efficient
  • collect parts to fill empty slots and also upgrade existing attached parts (however, because this is the AI rather than a player, it can take even more liberties with the swapping, for example removing inactive propulsion that doesn't match the current movement mode to make room for more of the active type)
  • manage mass vs. support, for example avoiding adding so much mass it goes past a desired overweight threshold, and tries to shed heavier parts if it's suddenly gotten heavier due to build changes, to maintain speed
  • wander the map while improving its build without fleeing under fire (since it needs to prioritize searching for and collecting weapons if it's been disarmed)
  • seek out Matter and Protomatter

The first-ever AI to pick up its own parts, when I first started the project.


A slightly less stupid (but still very stupid) later version.

Here I also considered adding ramming to their basic abilities, so that like Cogmind the AI could also have a useful attack while disarmed, but found there were too many complications so although I figured out how it would be possible, ultimately decided it wouldn't be worth it for this event.

I didn't get into personalized behavior of any kind, like AIs with a preferred style, since there's already plenty of randomization and variety coming from the many many parts and their conditions at a given time. This would be a natural future step for a more involved project, however.

The complete non-combat portion of the AI can be summarized with pseudocode like so:

Cogmind Battle Royale AI pseudocode (non-combat state).

Once the Battle Royale AI reached this stage, it had started getting complex enough that it was really annoying trying to fine tune it while working in regular Cogmind/0b10 maps where there are too many distractions. About time to make the new map!

The Arena
The idea behind this mode was that there'd be only one map, the first ever Cogmind mode to pare down the game into such a small "world." Initial plans set it at 200x200, the same size as Factory/Research, based on my experience designing maps of that size relative to movement speeds, the ranges of sensors and weapons, and perhaps most importantly the total number of participants. 30 seemed like a good number.

At first it was going to be like a typical Cogmind room-and-corridors style map, with a final central room on which the last living bots would naturally converge as the accessible area shrank. Here I was just starting out getting the map generator building out from the central room:

Early WIP Cogmind Battle Royale map layout sample with central room.

As I was fooling around with trying to get it to do what I wanted, a different better idea popped into my head: What if instead of using the normal subterranean-style maps we instead directly converted it to a sort of overland map where rooms are instead "structures"?

This would significantly open up the map, creating additional pathways and a sort of "organized chaos" in the form of a little town without clear straight roads, but all locations are still accessible.

Sample Cogmind Battle Royale map layout.


Sample Cogmind Battle Royale map layout.

I like it! Some of the strategy implications of this approach:
  • makes it much easier to navigate and reach the center (if necessary one can technically even just blow through walls to reach the center once you have orientation)
  • makes it easier to escape if you're faster than a pursuer, harder if you're slower (and harder to give chase if you're slower)
  • easier to spot enemies and be spotted because generally more open
  • less likely to get unnecessarily trapped by the closing circle of death

Plus it's also kinda neat just to have a different kind of map to play around with.

I called the map "Wartown."

(continued in following post...)
« Last Edit: March 03, 2020, 05:34:33 PM by Kyzrati » Logged

Level 9

View Profile WWW
« Reply #1268 on: March 03, 2020, 05:24:50 PM »

(...continued from previous post)

Mechanics and Features
We've got a basic AI and a basic map, next up are features!
  • Everyone spawns in their own room, usually out near the edges of the map.
  • Everyone starts with the same base stats and slot count, but completely randomized gear. It's more interesting to be forced to adapt, but rather than having players gradually collect their parts from around the map, that entire process can be sped up by simply starting with it. This is more appropriate for Cogmind anyway, because one or two parts alone isn't enough for an interesting or fun build--you really need a larger collection to be at all effective or to more quickly convert into something effective.
  • Random parts are also scattered across the map (some items found in the regular game are excluded, however, generally things that wouldn't make sense in this mode).
  • There is no Matter cost associated with attaching parts. This rule change was partially put in place to make inventory management a little easier on the AI (no need to consider Matter waste alongside repeated build tweaking), and also to speed up gameplay in general because it would otherwise be easier for players to run low on or out of matter.
  • Attacks enforce RPGLIKE-like damage redirection where some part damage is transferred to the core, but in this case the rate is only 50% (and armor transfers only 25%). I wanted parts to still take plenty of damage and be destroyed, but at the same time didn't want too much damage focused on target cores because otherwise bots wouldn't last long enough in a confrontation, at least not long enough to allow for some tactical variety.
  • Cogmind's parts do not have their usual high-integrity critical strike protection, and no bot can have their core automatically destroyed by a critical strike.
  • All bots use the normal player-Cogmind rules for increasing system corruption when his with EM damage (so it's no longer as much of a threat to other robots as it normally is).
  • In addition to salvageable parts, destroyed bots drop both Matter and Protomatter, the latter of which does not decay and is applied in full each turn where necessary/available just by standing on it. Borrowing Protomatter from RPGLIKE mode was essential in maintaining balance because without a way to repair, attrition would inevitably lead to death after one or more confrontations.
  • On destroying a target, the attacker gains a new random slot (awarded on the following turn). This allows for a form of progression, ensuring it's less advantageous to simply hide from everything and pop out at the end to kill the last remaining enemy, since whoever they are they're quite possibly more powerful by then.
  • Ambient heat slowly spreads from the four corners of the map towards the center. This is the so-called "circle of death" mechanic important to Battle Royale games in order to force players into eventual contact with one another while keeping it from getting boring. I like the idea of using heat rather than damage to achieve this goal because it builds gradually as it approaches and builds with good dissipation can afford to stay near or in the hot area for longer, not to mention heat has different kinds of side effects. In the end no build can withstand the full intensity of the heat, of course, it just allows for more or less flexibility in that area. The AI is aware of the heat area and acts accordingly.
  • Once only a single bot remains, an exit appears in the center of the map.

Heat encroaching on the map's center room.

The heat's color effect is achieved via additive RGB based on the actual ambient heat per cell, so maximum heat actually appears yellow (although the animation still plays out for all hot locations so it's not a constant yellow).

Full heat has filled the map, though it cannot enter the central room.


Catching the heat mid-glow after it's covered the map. AKA making procedural art.


Recorded bird's eye view of heat expanding from one corner over time.

Each player is also assigned a random name with their player number attached. For this I wrote up a list of hundreds of Cogmind-relevant words for use in compounds.

Sample generated Battle Royale "player names."

Normally I would've cancelled an idea a lot sooner in development than this (like the real-time arcade version of Cogmind I never even wrote about here but released to patrons at one point :P) but due to the investment required to develop the necessary AI, it took a while to reach an MVP state so I didn't get to testing whether it was actually a good idea for a while xD

As soon as it was semi-playable I immediately realized it wasn't quite going to work, at least not without a huge amount of additional investment that just wouldn't be worth it for a special mode.

In the end, Cogmind's mechanics and gameplay weren't designed to be all that compatible with 1v1 fights between equals, which is what Battle Royale tends to boil down to--you have a bunch of essentially identical players all vying for the win, but Cogmind is meant to be a more tactical one vs. many game (or many vs. many, with factions) in which most bots die quickly and the situation keeps changing as a result, rather than just sitting in one position pelting enemies, which is often what BR mode using Cogmind mechanics ends up as. Certainly you can do a fair amount of stationary farming in regular Cogmind, too, but there's still a lot of thinking that goes into the plan before the fighting even starts, and that determines how the fight will be likely to go--this is something the AI can't really do on an equal footing with the player, and it ends up being less interesting as a result.

In BR mode, AIs spot a target and then sit there doing their best to pummel it to death if they're capable of attacking. Without a much smarter tactical AI that can come up with environment-related tactics and exercise more forethought and better react to spacial disadvantages, it just doesn't work well.

In hindsight this all should've been obvious or could be realized via thought experiment alone, but I was clearly hyperfocused on the AI development aspect and really wanted to give it a try anyway :P

But Playable!
Before stopping work on BR mode, however,  I actually put some more hours into it so that it'd be a more complete and fully playable prototype for patrons who'd like to try it out, and feedback was actually decent! (maybe I was too harsh on the mode and should bring it back one day with a bit more development? :P) The heat mechanic, among some others, is an example of a feature that wasn't even implemented yet when I first decided to cancel--I admit I also really wanted to see what it might look like :D

I released a special Battle Royale build on Patreon here[/url], and since then have updated the build several more times (in place on the original page) to address bugs and further improve the AI.

A rather quick and explosive skirmish in BR mode.

Features missing from this mode, as released, but that I would have addressed later:
  • prefabs (including special stockpiles and especially better treatment for the center area)
  • more attention to machines (all I did was throw some random machines into the mapgen pool, where ideally the types and compositions would be selected for both better gameplay and atmosphere)
  • message log details about who is destroying who
  • Haulers that teleport in and carry lots of great gear, and everyone gets a ping of their locations (works as a mechanic to force confrontations and give extra rewards those who succeed)
  • different enemy colors to reflect their state
  • different game over screen, a leaderboard ranking all the "players" (unique scoring system) and showing their build classes
  • even better AI :P
  • a more balanced experience overall, or at least "balanced" to maximize FUN

Fortunately most of the work that went into this mode didn't go to waste. Cogmind Battle Royale may have been cancelled, but the AI lives on! I've continued to improve on it (vastly!) for use in a different special event, and there is at least one part of the regular game where I'm interested in incorporating just such an AI. So I'd consider this project a success overall.

This side project also resulted in some general AI improvements and even discovering and fixing one relatively new AI behavior bug that hadn't yet been reported.

I'm not sure whether I'll ever get to that AI can reasonably play the game, although the next little step towards that goal is only barely beyond what we have now--just take the first exit spotted ;)

Level 9

View Profile WWW
« Reply #1269 on: March 31, 2020, 03:15:18 PM »

Multiplayer Cogmind is here!

Are you stuck at home?

Want to play some Cogmind but with extra social interaction?

How about taking on Complex 0b10 with a friend! Don't worry, NO REAL FRIEND NECESSARY, we'll provide one for you!

Welcome to Cogmind Beta 9.5...

This April 1st, just fire up a run and leave the Scrapyard to join forces with Player 2 on the adventure of a lifetime :D

Use the superior firepower of TWO COGMINDS to teach the Unaware that they should've stayed a safe distance away from you.

Your brand new friend comes with
  • new AI behaviors
  • most of your same capabilities and will evolve and manage their own build and inventory
  • over 600 lines of situational dialogue to keep you company on the way

For the full release notes and feature demo images, see here.

Cogmind Beta 9.5 "Player 2" (200401) changelog:
  • NEW: Unique AFD mode for 2020, automatically activates on 4/1 for anyone who has played at least three runs
  • NEW: Command line argument "-forceMode:AFD2020" (or "-forceMode:Player2") to enable the AFD mode from 2020, regardless of system date
  • NEW: [Player 2 mode] Join forces with Player 2, another Cogmind with most of your same capabilities
  • NEW: [Player 2 mode] Adds a special interface displaying Player 2's class and movement data, with persistent access to their loadout (toggle w/'9' or LMB)
  • NEW: [Player 2 mode] Cogmind and Player 2's core integrity levels are linked
  • NEW: [Player 2 mode] Multiple smarter AI behaviors for Player 2
  • NEW: [Player 2 mode] Over 600 lines of situational dialogue
  • NEW: [Player 2 mode] 1 new unique superweapon
  • NEW: List of item schematics during manual hacks darkens any that are already known
  • NEW: Option to block achievement earning while in challenge modes and special modes (advanced.cfg: onlyRegularModeAchievements)
  • NEW: Manual "Difficulty" section includes explicit subsection for Rogue setting
  • NEW: Manual part list data visualization descriptions further clarify meaning of heat mode values
  • MOD: Part autoreplacement feature compares items based on based on current integrity rather than percent integrity remaining
  • MOD: Part autoreplacement feature never swaps in known faulty or broken parts
  • MOD: Advanced option "ignoreAscendConfirmation" no longer prevents warnings about leaving allies behind
  • FIX: Size 36 fonts had become unusable on 4K screens [mudshark]
  • FIX: [RPGLIKE mode] Pressing '0' with an open ally order list would open RPGLIKE upgrade menu [NikolayAg]
  • FIX: [RPGLIKE mode] Protomatter might have a negative value under some conditions [Terminus, Rumbl3]
  • FIX: Part autoreplacement feature was sometimes making undesirable swaps with regard to relative integrity [sunqingyao]
  • FIX: Automatic waypoint recall for guided weapon attacks had stopped working [Valguris]
  • FIX: Changes for RPGLIKE mode broke Sensor Arrays and Visual Processing utilities, allowing them to stack [Kerapace]
  • FIX: Beta 9.5 prerelease bugs hunted down by: [CaptainWinky, Xii, lsend]
  • FIX: [Pay2Buy mode] Hotkey for closing CogShop was still '0' rather than the newer '9'
  • FIX: New "Broken" prefix for non-functional parts did not automatically update until part changed in some other way
  • FIX: New "Broken" prefix for non-functional parts was included in log messages regarding that state change
  • FIX: [Abominations mode] Abominations more effectively switch between propulsion modes when more than one available
  • FIX: Since AI modifications to support autonomous weapons, disarmed combat bots might continue chasing targets rather than fleeing after loading a save
  • FIX: Regular map exit warnings were not displayed if attempting to exit while somehow already on top of stairs
  • FIX: Starting XP for RPGLIKE mode was added to score data even outside that mode

Level 9

View Profile WWW
« Reply #1270 on: April 13, 2020, 02:48:29 PM »

Cogmind Beta 9.6 is out, now with a new and improved Player 2!

For the full release notes and feature demo images, see here.

Cogmind Beta 9.6 "Core Friends" (200414) changelog:
  • NEW: [Player 2 mode] Added dedicated "Player 2" section to scoresheet with 15 new entries
  • NEW: [Player 2 mode] Player 2 better understands the tactical use of launchers when conditions permit it
  • NEW: [Player 2 mode] Player 2 can now swap parts from ground into a full inventory to improve type and quality of spares
  • NEW: [Player 2 mode] Player 2 much less likely to stack utilities that won't benefit from it
  • NEW: [Player 2 mode] Player 2 tendency to use heat sinks as armor toned down
  • NEW: [Player 2 mode] Player 2 part loss also contributes to alert level reduction, as per the Cogmind mechanic
  • NEW: [Player 2 mode] 2 more dialogue situations (total = 83)
  • NEW: [Player 2 mode] More dialogue lines (total = 660)
  • NEW: AI-controlled bots with a large energy-based volley may proactively deactivate one or more weapons if it will enable them to fire immediately
  • MOD: [Player 2 mode] Player 2 no longer considers wasting turns on smaller integrity upgrades when rebuilding from salvage
  • MOD: [Player 2 mode] Increased frequency of Player 2 dialogue
  • FIX: Beta 9.6 prerelease bugs hunted down by: [CaptainWinky]
  • FIX: AS-neutralizer No. 17b applied effect across entire map rather than limiting to specified range [Valguris]
  • FIX: Scoresheet "Unauthorized Hacks" tally higher than intended [Valguris]
  • FIX: Part info comparisons with a part using a manual tag misaligned the values by one row [Pimski]
  • FIX: Scoresheet history log message for bump-rewiring detected and displayed incorrectly
  • FIX: autoActivateTreadsOnAttack option caused inactive treads to appear active on automatically switching back to core propulsion on a move after attacking
  • FIX: [Player 2 mode] Potential load issue under certain conditions
« Last Edit: September 13, 2020, 11:51:40 PM by Kyzrati » Logged

Level 9

View Profile WWW
« Reply #1271 on: May 19, 2020, 02:39:21 AM »

Developing Multitile Creatures in Roguelikes
[Cross-posted from the devblog here--follow link for better formatting and light-on-dark style.]

Creatures/entities that occupy more than one space in the grid-based world of a roguelike still aren't all that common, although in the development community this is an increasingly popular topic. Many of these discussions revolve around how to solve various technical and design issues associated with this type of entity, and while I've provided input in a number of these conversations over the years, it's really about time to collect some of these experiences, observations and advice into a single article for better reference :)

I gave "multi-tile robots" cursory coverage back when I was first spinning up Cogmind as a commercial project in 2013, but all I really did there was give a basic description rather than look into the nuts and bolts underpinning this feature.

I've been working with multitile creatures since 2011 when I first added them to [email protected]. As I wrote about there, it was quite a headache because I didn't include them from the very beginning, but it was both necessary to do considering the primary source material (X-Com) and also definitely adds a lot of character to these creatures, so very much worthwhile.

The famous example of a big 'D' dragon occupying only one space, the same tactical unit as a tiny adventurer, is great in its own way (elegant!), but there's something to be said for the psychological impact and mechanical implications of an actually physically larger creature.

An adventurer faces off against... count them... five dragons in this room :P

I guess there's also the realism argument--although complete realism isn't usually a good goal in games, it's always nice when you can both embrace it and get some benefits in return.

"Holy... look at that thing! We probably can't take it on at this point, but if we escape down this narrow corridor it probably won't be able to follow us... We'll find another way around."

Types and Examples
Technically the concept of "multitile" creatures can be subdivided into a number of different categories, not all of which I'll be covering in detail here.

For example a number of roguelikes have stationary multitile creatures, like Ivy Creepers in Ragnarok.

Ivy Creeper wiki data from Ragnarok. (It'd be nice to get a shot of them in action, but they're rare in that game, and unlike with other games the internet lacks a good variety of screenshots of this very old roguelike!)

Although stationary, sometimes creatures in this category can also grow outward, like the various Ivies in HyperRogue.

Hacking away at Mutant Ivies in HyperRogue.

Overall these are fairly easy for developers to work with, it's just a case of whether you want/need something like this in game.

There are also snake-styled multitile creatures which can move, but where the body essentially follows whatever path the head has taken, so also not all that hard to manage.

A Long Worm in NetHack, where only the head ('w') can attack, but attacking it in the body ('~') may cause it to divide into two worms.

HyperRogue also has several snake-like multitile creatures, including Sandworms.

The genre also includes amorphous area-based creatures like DCSS Krakens, which consist of a single body tile and send out tentacles which essentially behave as individual creatures (although their range from the body is restricted, and damaging them also damages the Kraken).

Encountering Krakens in DCSS.

For the purposes of this article, to keep the scope in check (and more importantly to cover the especially challenging areas where questions usually arise) I'm really only interested in the most generic type of multitile creatures, those where the entire creature is a "connected solid blob" that is present on the map and moves as a unit like other single-tile creatures.

Probably the most extreme example of this category would be Dumuzid, a 7DRL explicitly designed around the concept of size, so it's not surprising that you can end up with a massive sprawling body that moves as one.

Defeating enemies to expand your own body in Dumuzid, often eventually finding it difficult to fit through various areas, or the right angle to attack an enemy. This is just the start--your body can get quite expansive, and you might need to intentionally shave it down sometimes as well. It's even possible to lose by getting stuck!

Some more typical examples, all coincidentally reflecting the theme that multitile creatures are often used for especially challenging or awe-inspiring enemies like bosses:

Fighting Baezl'bub in POWDER.

Fighting Xiatol in Cardinal Quest 2.

Lost Flame has quite a few types of multitile enemies (and not just bosses, either!) which meld well with the game's heavy focus on telegraphed attacks and tactical positioning.

For [email protected] I went all in on the multitile units, branching out from the original requirements for X-Com. It's fun to drive a tank through walls and watch the building collapse :). It's also fun--but scarier--to watch huge enemies rampage through buildings, knocking down walls and crushing furniture! X-Com itself only had units up to 2x2, but when putting in place mechanics like this, may as well make the size arbitrary! Back then while recording a video demonstrating sound testing there was a 5x5 Colossus at the end, which you can see below starting from 3:50:


Having inherited its architecture and even some mechanics from [email protected], Cogmind also includes a number of multitile entities for their shock and awe factor. Although there are slightly more obstacles to overcome when moving from a more open surface environment vs. the subterranean environments more typical among roguelikes, for me it's worth the trouble.

A Cogmind Behemoth in the wild. (Uh oh, all hell is about to break loose and those machines are explosive...)

IVAN reportedly also has 2x2 monsters that can usually destroy walls in order to move around (or are simply stationary), but I couldn't find any good resources or images on those.

I'll be sharing more examples from Cogmind and other roguelikes below where applicable to the topics we'll be covering.

Note that as discussed here multitile creatures refer to those of an actual larger size when it comes to mechanics and the number of grid spaces they occupy, not just cosmetic size, which a number of games do as a simple way around implementation issues, but as a result also don't fully realize their potential.

There are a number of different ways to depict multitile creatures on the map, some of which might need to get creative if limited to ASCII and/or traditional grids with an otherwise uniform cell size.

For Cogmind's ASCII mode I chose to repeat the single character across the area currently occupied by the entity. The usual opposition to this concept claims that it becomes impossible to distinguish whether it is a group of entities or a single large entity, but in practice that's not really much of an issue since based on the game content it's otherwise extremely rare to have individuals matching that letter both adjacent to each other in a uniform shape and also moving in perfect formation. Not to mention when examining such an entity all the spaces are highlighted together, and labeling (or for example in other roguelikes listing what is currently visible) only does so once for the entire thing, rather than for every constituent cell. So this isn't really something to worry about unless there is something else specific to the given game's content or mechanics that might lead to confusion.

Highlighting and labeling a large robot in Cogmind's ASCII mode.

A fire-breathing dragon from an early build of Ultima Ratio Regum.

Incursion offers another potential approach for ASCII-based roguelikes, linking the creature's character to its surrounding occupied cells with a separate representative character, in this case using '+':

A Huge Viper in Incursion--the 'R' surrounded by '+'.

Under a very strict grid-based system like that often used in ASCII games, it's technically still possible to draw multitile creatures using a sprite that extends over more than one cell. Cogmind's engine in particular doesn't even support drawing anything that doesn't match the grid size, so the only way to draw a multitile object is to do it piecemeal, one cell at a time. For example, the 2x2 Behemoth consists of four separate cells, appearing as such in the sprite sheet:

Cogmind sprite sheet excerpt--Behemoth cells. The first is the top-left, followed by top-right, bottom-left, and bottom-right. The same system is extrapolated for even larger entities.

Many roguelikes using modern engines don't necessarily care about this sort of thing, and are instead able to simply draw any sprite, large or small, at any position. Zorbus offers a good example of multiple different methods for drawing large creatures when there aren't any architectural restrictions.

Various dragon representations in Zorbus. While most of these are purely stylistic differences, important to note is the ASCII version demonstrating yet another approach: Just make the letter bigger :P

Partial Visibility
A number of roguelikes (including Zorbus above) might display multitile creatures simply using large characters, highlighting another consideration when working with multitile creatures: partial visibility. Field of view in roguelikes is almost always handled on a cellwise basis, so what does the player see if only one or more pieces of a multitile creature are visible?

In terms of ASCII and Cogmind's default approach of repeating the same character throughout every occupied cell, seeing only part of a creature doesn't make much of a difference since every cell contains the same representation. Perhaps the main concern here would be that a player might not be able to immediately distinguish whether a single 'B', for example, is a corner piece of a large Behemoth or a single-tile Brawler-class robot. This is where it helps to have those automated labels demonstrated earlier--the question is answered immediately on spotting them!

A partially visible Behemoth has its top-left corner labeled on sight.

To demonstrate another scenario, we can use a graphical Cogmind mod recently released by Ape, which converts the default multicharacter style to instead use large characters like so:

A large-character multitile Behemoth as it appears in Ape's graphical Cogmind mod. So imposing! I love it. (This particular ASCII mod also uses the tileset specifically for walls.)

So what happens when this only the corner of this particular Behemoth is visible?

A partially visible Behemoth assuming large characters are used for multitile entities.

Again the autolabeling will help here anyway, but the top-left corner of a large 'B' character actually looks like an off-center 'c'! And of course each other corner, or side, will have its own unique appearance. Partial visibility doesn't work so well with this approach as far as quick visual parsing goes (usually one of the advantages of using ASCII in the first place).

Based on this info, with multitile creatures we might want to break the mold of displaying only the cells that a player can currently see, and instead allow the player to know and see the full extent of any multitile creature they can at least see part of. This could apply to both ASCII and tilesets. Either show the entire creature normally if any of its parts are visible, or show it all but consider fading those cells not currently in FOV, since it can still be important to know when certain subsections are technically out of view.

Examples of what it would be like to show the full large-character Behemoth even though only its corner is visible (A), or perhaps fade those sections which aren't themselves in view at the moment (B).

For cogmind in particular I decided against showing parts outside FOV (which is an option even if separate characters are used for each part!) because it would complicate a lot of the UI features in my case. I imagine it would work fine for a lot of other roguelikes, though.

(continued in following post...)

Level 9

View Profile WWW
« Reply #1272 on: May 19, 2020, 02:39:42 AM »

(...continued from previous post)

Handling relative position data for entities is fairly straightforward when each one can only occupy one cell at a time, but what do you do for those with a larger footprint? Some people get hung up on this question. The answer for a given roguelike could depend on other needs and architectural concerns, but here I'll share what's worked well for me.

This is rooted in the format for general map data, so here's a diagram of how Cogmind map objects are structured:

Diagramming the relationship between common object types on a Cogmind map.

This diagram includes some superfluous info because I pulled it from a broader discussion, but the concept to pay attention to here is that 1) an entire map/floor is represented by a two-dimensional matrix of Cell objects, and 2) within each of those cells is an Entity object. "Entity" refers to an actor/creature/character/mob/whateveryoucallit, where the Cell stores its occupant's handle (sorta like a pointer) or simply null if no Entity is currently present at that location.

Although I do also have a list of all the Entities in existence (technically managed as a separate list for each faction), and that format clearly comes in handy for some types of operations that need to iterate over all Entities, I find it very useful to have an actual 2D space across which to perform spacial searches and apply effects etc. For performance reasons this is especially important in Cogmind where there are hundreds of Entities at once.

So what does this mean for multitile Entities? Well... just put their unique handle in every Cell they occupy :)

It's not like the Entity object itself is actually copied anywhere--it's just a little handle, so there's no serious waste of space, but definitely a serious bonus to convenience. Processes checking who's occupying any one (or more) of those Cells will be pointed to the same Entity. Whenever the Entity changes position, it just moves its handles from all of the original space(s) it occupied to the new ones.

Each Entity itself also stores a list of all the map coordinates it currently occupies. While it's true that for most/single-celled Entities this list only contains one coordinate, implementing the system like this makes it easily scalable. At the same time, although for most roguelikes you could generally extrapolate these additional coordinates if you know their reference position and size, that's pretty slow to be doing all the time!

In my case I chose the Entity's top-left corner as their "reference position," the first to appear in its list, where any additional coordinates are added in row-first order (notice how the indices here will conveniently mirror offsets in the sprite sheet shown earlier ;)). The idea of a reference position will come in handy later.

(Although most devs there don't make mention of multitile entities, regarding map object architecture you might find other inspiration in the previous relevant FAQs over on r/RoguelikeDev.)

Before we go any further it's important to talk about shape as it relates to multitile creatures.

By far the most common multitile creature in a roguelike, if there are any at all, is the so-called "2x2", occupying a total of four cells. As a square this is fairly easy to deal with because it doesn't have any convex or concave elements to complicate movement or interactions.

Non-square shapes (even just rectangles!) are problematic since then you likely have to deal with the logic and consequences of rotation, among other issues. With multitile creatures already introducing enough of their own complications, most roguelikes don't venture into other shapes. (Something like Dumuzid is of course an exception here, since its a small game where the central theme happens to be size manipulation. Interestingly, it does not allow rotation, either.) Rotation suggests an explicit facing, anyway, and most roguelikes don't have facing mechanics, so multitile creatures that imply multiple orientations are often avoided.

Whenever the topic of multitile creatures pops up in the roguelikedev community, there's a good chance it's someone asking about pathfinding. In a game where every actor occupies exactly one space, moving them across a grid seems a lot more straightforward than managing those which need extra space to move around.

For the purposes of pathfinding for multitile creatures we're going to be ignoring these less common scenarios and, again, creatures outside this article's scope:
  • non-square shapes (and by extension any rotation involved with those--CDDA has rotating multitile vehicles of various shapes if you want to look into that, for example here)
  • snakes (longer are especially challenging, since they can block themselves!)
  • amorphous creatures
Still, if you're working with any of the above, it's mainly a case of picking a primary reference part (of the creature in question) on which the pathfinding is based, and extrapolate positions for other connected parts as it's moving, which is actually akin to what we'll be doing here in a moment for regular square multitile creatures.

Method 1: Static Approach
One method I haven't used before but have seen others use is to explicitly map out the spaces available to large creatures, and use that map for pathfinding. Taking the most common 2x2 creature as an example, you can make a copy of your map and block any otherwise open spaces that have a wall or other impassable obstacle to their south, east, or southeast.

A basic sample map next to its precalculated movement map highlighting all the spaces our 'D'ragon can access and occupy (green background). This representation assumes the creature's reference position for pathfinding purposes is the top-left corner of its square.

So as per the above screenshots, pathfinding algorithms would rely on two separate maps, one used for standard-sized actors, and another for 2x2 creatures:

Comparison of movement/pathfinding area available to 1x1 entities (left) vs. 2x2 entities (right).


Our dragon is on the move! See how its top-left corner always stays in the green areas, although the rest of its body might extend into the black.

However, this approach works better for static maps, since changes to the map due to terrain destruction or other factors would require recalculating the pathfinding map(s) (or at least parts of it). I love rampant terrain destruction in my roguelikes, so this approach won't really work so well in my case. As you'll see below, an alternative dynamic approach can also take into account more factors, anyway, creature size being just one of them.

Method 2: Dynamic Approach
The dynamic approach starts getting more deeply into how you build your pathfinding system architecture. Amit's got great resources on A* pathfinding over at Red Blob if you want to read up on that common algorithm for more background. I'm not going over basic A* here, instead looking at how to best apply it so that it can specifically account for creatures of arbitrary size.

For all but the simplest roguelike worlds you'll often want to have creatures actually examine each potential cell along a path and weigh it in terms of various relevant factors, for example terrain movement costs (which can differ by creature type and terrain?), or the creature's own capabilities (able to swim? fly? open doors? some other form of environmental interaction?). One nice way to compartmentalize this feature: Callbacks.

In simple terms, when a creature wants to find a path from point A to point B and calls the game's pathfinding function, it also provides a callback function that essentially contains instructions for how to value cells along prospective paths. A* pathfinding operates by assigning "cost" values to cells until it finds the sequence of moves that can arrive at the intended target for the lowest total cost. So the callback's job is to just return the cost for a given cell in order to facilitate those calculations.

Cogmind's pathfinding callback object.

As shown above, Cogmind's primary movement pathfinding callback that's sent to the algorithm is actually an object holding multiple methods, originally virtually defined by the base class associated with the pathfinder itself (Cartographer2D). I found it more efficient to split out into multiple methods some of the checks that a callback might need to handle, e.g. isValid() is used to tell whether the goal is a valid movement position, which is probably important to know before bothering to start :P. (Cartographer2d also supports pathfinding via cell-enabled teleportation, but Cogmind itself doesn't feature that kind of teleportation so the callback object doesn't define the necessary method.)

Where does this accommodate multitile creatures? First of all, remember that the reference part of the creature is what's being used to calculate their path--the beginning of the path matches their top-left corner, and the end of the path will be the final location of their top-left corner.

A sample path for our multitile dragon, based on its reference part.

The isValid() function* just needs to be sure to check not only whether the reference position at each cell along the path is valid, but that all other relative parts of the same creature are also valid (*and by extension getMoveCost(), which is what checks isValid() before calculating and returning the cost for a cell).

For reference, here's the actual source for those methods as used in Cogmind, with some of the very game-specific code left in for demonstration purposes (some of it was temporarily removed to skim down the size and avoid overcomplicating the example). Note how isValid() checks the validity of all constituent parts for large square creatures (of arbitrary size) assuming it's standing at a given coordinate location.

This dynamic approach doesn't require precalculating or maintaining any other pathfinding maps, can take into account any number of other factors (regardless of whether they're changing all the time!), and is clearly just what we need for allowing multitile creatures to move around while also considering whatever else they need to consider.

In summary you get a lot of flexibility by using callbacks for pathfinding. We can add whatever absolute checks we want to isValidCell() and they'll be applied to any cell the creature might think about occupying, or add checks to getMoveCost() for moves that are allowed but might have a different cost than moving into/through a normal cell. Cogmind doesn't make especially heavy use of these features, though as you can see there are conditions determining whether or not an entity can use different types of hidden doors, and the cost of pathing through a known trap or area prone to cave-ins is higher (making it less likely).

Aside: The popular roguelike library libtcod (which I recommend in my How to Make a Roguelike talk/article) includes support for pathfinding callbacks! In fact, using libtcod in my early roguelikedev days is actually where I learned about them in the first place :)

(continued in following post...)

Level 9

View Profile WWW
« Reply #1273 on: May 19, 2020, 02:40:05 AM »

(...continued from previous post)

Having gotten the primary technical concerns out of the way, there's also the design side of the equation when it comes to multitile creatures. Surely you can't just drop them into a world made for your typical 1x1 cell-sized creatures and expect everything to be okay :P

Environment-based Factors
Naturally more open maps are better suited for these large creatures, since terrain is the biggest obstacle to their movement. Although roguelike maps tend to have a lot of tight spaces, even subterranean maps can also be made more hospitable for large creatures if there are at least some open areas for them to comfortably occupy.

For example Cogmind's most common 2x2 unit, Behemoths, aren't located in random rooms, but instead specifically placed in areas where multiple rooms and corridors have converged to create a larger space.

According to the mapgen rules, in Cogmind multitile entities (in this case somewhat scary and destructive mobile weapons platforms) might be defending any of these areas.

This ensures they'll have some room to maneuver and engage threats without being overly restricted, and while it's true they'll not always be able to stray too far out of the area they're defending, they still present interesting challenges when compounded with other factors to complicate situations, like a player fighting a running battle through such an area, or encountering other enemies at the same time and finding it difficult to disengage.

Other challenges arise when there's no easy way to circumvent a large creature and a confrontation is almost guaranteed sooner or later. This also starts to suggests the idea of "multitile creature as boss or miniboss," where their extra visual weight signals that they're not to be trifled with (hopefully with stats and abilities to back up this assumption!).

Since multitile creatures can be problematic for map layouts, it makes sense to limit their overall number in the first place, plus having fewer of them enhances their wow factor anyway. Again: boss material.

On that note, another way around some of these issues is to design special areas explicitly for multitile creatures, like their home/den/native habitat. "Waste" is an example of one such place found in Cogmind, where chutes from Factory zones send scrap for disposal, and mobile Compactors mill about crushing everything.

Compactors are each 2x2 multitile entities, and all corridors in randomized Waste layouts are exactly four cells wide, just barely allowing two Compactors to pass each other. This of course presents a problem for players who have attracted the attention of more than one Compactor, since they can form an oncoming wall of death, so maneuvering to prevent or undo such a situation and slip by can be a useful skill if without the firepower or other means to actually take these chunky bots down.

Sample "Waste" map layout with multitile Compactor occupants.

Since we were talking about multitile creature representations earlier, here's an alternative look at the same scene:

Sample Waste map revealed in ASCII mode.

Garrisons are another example of a Cogmind map type in which multitile entities have influenced the design, where there is often a 2x2 Behemoth guarding the central room and double-width corridors extending outward to all four access points.

Sample Garrison layouts with central open room (potential Behemoth defender!) and wide corridor spokes.

There are still small access tunnels mostly hidden behind walls that might be useful in avoiding a confrontation with the Behemoth in a Garrison, but overall it's quite a game of cat and mouse if you're not ready to engage them head on, since due to the layout and Garrison mechanics it's likely you'll have to pass through the central room more than once from different angles before being able to actually leave.

Creature-based Factors
Aside from external factors like map design, we can also examine this issue from the other side: What about giving multitile creatures more control over how they can maneuver through, or manipulate, the spaces around them? This is where various mechanics and creature-specific abilities come into play.

Seemingly the most common approach here, and the one that makes the most sense (because, I mean, they're big creatures, yeah?) is to simply let them crush obstacles and smash their way through terrain! Whether or not this will work for you can of course depend on the environment and other circumstances, but it serves as yet another source of wow factor when some creature practically ignores walls that block normal-sized foes and just comes right through them.

The multitile creature demo in the [email protected] video I shared earlier happens to show it smashing through walls, although much of it is out of view while doing so. In that game the system is generalized such that different materials require a different amount of force to knock down/through, so while a soldier can relatively easily jump through a glass window, or a bigger alien can possibly stomp through a fence, it takes a tank or huge alien to smash through walls of brick or stone.

A tank driving through a house in [email protected] You can also see it pushed back (and later to the left) due to displacement from falling debris from the second floor after it loses the support of some walls below it.

While pathfinding, A* callbacks can help determine 1) whether a given unit is even able to take a "shortcut" through a given material and 2) whether the potential cost(s) of doing so are not greater than going around it (if possible).

[email protected] pathfinding range comparison between a soldier (center blue triangle) and the multitile tank next to it. Notice how the soldier's range doesn't include obstacles, and isn't able to quickly make past the tall hedge to the north, whereas the tank has the option to just crash right through so it can reach almost all visible locations in a single turn. (Aside: The soldier's potential path area includes a brighter green portion, which is actually up on the second floor of the house they're in, via the '<' stairs around the corner just inside from the garage. The tank can't use the stairs, so its path is restricted to the ground level here :P)

[SPOILER ALERT: If you're a spoiler-averse Cogmind player, you might want to just skip this paragraph.] Although not nearly as detailed, Cogmind has a similar mechanic specific to a certain entity. It's a fairly rare encounter, but players might at some point discover an experimental "Superbehemoth" capable of disintegrating terrain around it, effectively tunneling through it if necessary to get somewhere.

As mentioned earlier, I've heard that IVAN also has 2x2 multitile creatures that can destroy terrain in order to move, thereby sidestepping one of the tougher challenges with this type of creature.

Very much in the theme of ASCII and turn-based grids and all the things that speak to a "limitations breed creativity" mindset, in trying to integrate multitile creatures into a roguelike you can always experiment with other forms of movement and enabling mechanics, too.

Maybe a multitile creature can temporarily reshape itself to squeeze through narrow areas and unexpectedly pop out on the other side? Maybe they can teleport or use some kind of network of gateways? I still haven't actually done it, but one of the ideas I think would be fun to implement is a giant robot that can dispatch a bunch of tiny engineering drones to excavate pathways on the fly when it needs to, and they rebuild walls and terrain behind it after it's passed.

Another approach here is to allow multitile creatures more flexibility in how they can attack, essentially projecting their sphere of influence beyond their movement range. Early in Cogmind development this was actually one of the first ways I made Behemoths more formidable than they started out, since they are otherwise huge lumbering bots that could be evaded by keeping obstacles between yourself and them. Well they already have powerful enough weapons, so I just made their AI much more aggressive, willing to fire their cannons through machines and terrain to get at targets.

Behemoth says we aren't going to get away so lucky. Double bonus when the machines they're shooting through are explosive :)

So if the mechanics/environment/theme are suitable, consider giving multitile creatures the ability to attack and destroy terrain, or even just attacks that can penetrate terrain and other objects.

Or maybe they send out other attackers to engage targets? This could force the player to come to them in order to the deal with the source of the ranged threat, not unlike the stationary dispatchers of POYLBOT-7.

Miscellaneous Issues
You'll no doubt discover more complications stemming from the introduction of multitile creatures, some of them specific to your mechanics and needs.

Origin vs. Target
One of the more common ones you don't normally need to think about in a roguelike is the specific origin or target of an attack, in cell terms, considering that creatures might occupy more than one grid position. Perhaps if you have an odd-dimensioned multitile creature (e.g. 3x3) you might want to use its center point for this purpose. Or if you have special mechanics and a facing component there is/are actually a designated point on the creature where its attack(s) originate.

MechRL, a 7DRL from 2020, has you building your mech from visible parts that could easily use their respective locations to serve as the origins of attacks.

In my case, for the origin I always select the point on the attacker that is closest to the defender, and have it target the nearest point on the defender. That's for AI-controlled units, anyway--the player has more freedom to select any cell occupied by the target, making it somewhat easier to acquire a clear line of fire on partially obscured targets. It would be better to allow the AI to target any visible cell as well, but I felt it wasn't really needed, or worth adding that complexity, for my purposes.

If you've got area-based effects like explosions, as many roguelikes do, that'll be something else to consider. Should multitile creatures take extra damage/effects separately for every one of their tiles within the radius?

Having larger entities take more AOE damage like this is an option if you think it balances well given your mechanics, and players may even sometimes assume it in tactical games with a heavy emphasis on grid-based play (in my experience it's not an entirely uncommon question among players).

Personally I think it makes balance much more difficult to achieve when it comes to Cogmind mechanics, so I prevented that from being a thing--regardless of size, a single unit can only be affected once by a given AOE attack.

Sorry big explosion, you can only hit that Behemoth once.

I simply keep a record of all the entities already impacted by each active AOE effect, in order to prevent further segments from applying the same effect. As per the map object architecture I shared earlier, each Cell occupied by a multitile Entity stores a handle pointing to the same Entity, so marking the first one affected by an expanding radius naturally makes all the others "immune" to the same event.

In the original X-Com (and therefore [email protected]), explosions separately impacted every segment of a large target within their radius, like this 2x2 Cyberdisc. They have high resistance against explosives to compensate and won't generally die if only a small part of them is hit.

I ended up needing to take the same precautions for Cogmind's penetrating weapons as well (capable of piercing a target and going on to affect additional targets behind it)--I didn't realize until 2017 that these weapons were disproportionately effective against larger targets, since they could pierce one section and then hit one or more additional sections, affecting each separately. Now this does make logical sense, sure, but balance-wise it's not so compatible.

In theory this shot could penetrate two separate pieces of the Behemoth (but only affect the first) before hitting its target (which might also itself be penetrated :P).

You might also need to consider how multitile creatures interact with various types of terrain. Like what happens if they simultaneously occupy locations with different or even incompatible effects? How are variable terrain-based movement costs applied?

For this and other reasons, it's a good idea to add this kind of creature early in development so that you can take them into consideration throughout the process. Introducing them later could be quite problematic since you have to uncover and resolve all these issues retroactively rather than building each consideration into the system bit by bit as you encounter it.

Cogmind doesn't include many terrain-based factors, although one example I can provide here is traps.  Chute traps, which suck units down into the ground into another area (the aforementioned Waste!), only occupy a single space, so they essentially ignore larger entities that "wouldn't fit" :). Most other traps however, like those of an explosive nature, are triggered normally for every cell the entity steps on, meaning it's possible to set off more than one in the same turn.

Few roguelikes take advantage of 3D grid space, but while we're on the topic we might as well cover some points regarding adding a third dimension to our multitile creatures.

Earlier I talked about square shapes being by far the easiest to work with when it comes to multitile creatures, though the z-height of such a creature doesn't necessary need to match the other two dimensions. A 3x3 creature with a height of 2 isn't going to operate significantly differently from one of height 3. We are, however, assuming that height is uniform across its area. You can easily have 3x3x3 cube-shaped creatures, flatter 3x3x2 creatures, or even tall and narrow 1x1x2 creatures.

In most cases you'll be able to simply extrapolate everything we've already done for multitile creatures into the third dimension--like our pathfinding callback needs to check not just two dimensions, but three. I did this for [email protected], where I added 3D creatures and used the top-left corner of their lowest/base level as their reference point.

A multitile Colossus in its 5x5x3 glory, showing the three z-levels it occupies next to a house, and with its reference point highlighted.

And although a full discussion of how to represent a 3D space in a top-down 2D map is beyond the scope of this article, it's worth pointing out that with creatures like this it can be beneficial to allow a way to see them from the side as well. I first talked about side views back in 2011 when I implemented this feature for [email protected], and later shared how this can be applied to viewing 3D multitile units from the side as well.

Here you can see the Colossus being viewed from the side as well, in a popup window that appears across the top there to display the line of sight from a different angle. That's a lot of @ :)

This makes is easier to visualize targeting their different z-levels in case there are obstacles blocking line of fire at a given height.

I've covered a lot of the main multitile creature topics here, but it's a big one (haha) so feel free to ask about related issues or anything here you'd like clarification on!

Level 10

View Profile
« Reply #1274 on: May 19, 2020, 04:43:57 AM »

I think I'm going to have to sit down for this 9-course smorgasbord of information before I'm ready to ask any questions  Cheesy
Level 9

View Profile WWW
« Reply #1275 on: May 19, 2020, 01:07:38 PM »

Cheesy Yeah it's a lot to digest, and probably easier to come up with questions if you're one of the devs who's had issues with this sort of thing in the past/now on a project of your own.

Gotten so many questions over the years that it's nice to have a place to point to see most of what I have to share on the topic, or at least a good starting point for exploring what it takes. And sure enough when I started posting this around recently it even turned out to be timely for the portion of people who are working on this sort of thing right now, because there always seem to be some Tongue

Level 9

View Profile WWW
« Reply #1276 on: June 14, 2020, 03:42:35 PM »

Building Cogmind's Ambient Soundscape
[Cross-posted from the devblog here--follow link for better formatting and light-on-dark style.]

I first introduced Cogmind's ambient sound system back in 2014 during the pre-alpha days, as it was initially developed for Cogmind's predecessor ([email protected]) in the years before that, and sound would continue to play an important role going forward. It wasn't an especially long post like the ones I tend to write these days, but it did touch on the basics of propagation, sound dampening, and falloff models.

Since then I've also written a number of articles about sound effects and audio in general, but now it's finally time to address the relative lack of ambient audio in Cogmind! I'd been putting this feature off for a long while and it sat at the end of the pre-1.0 roadmap for years, at first because it made more sense to work on all that content after everything else was complete, but then later due to my concussion leading to hearing issues, which only after a couple years finally reached a point where they wouldn't be a significant roadblock.

Here we go!

Technical Overview
For relevant background to help better understand this article, here's a quick review of the ambient audio system's features...

There's a whole lot of sound-related values defined in Cogmind's data files. Above is an excerpt combining various sections, both ambient and non-ambient from a range of categories, to give a sampling of the variety (the full file contains 1122 entries :P).

Each sound is defined along with a "minimum" radius representing the distance before its "falloff" begins (i.e. the volume begins decreasing due to distance), and a maximum radius indicating the furthest distance out to which the sound travels as it's fading. A given sound can use one of four different falloff models depending on its needs, either linear, logarithmic, reverse logarithmic, or inverse.

Demonstrating the relative volume of audio emitted from a given source (the machine at the center) using different falloff models, alongside rough approximations of the graph representing each.

The above examples all have a minimum radius of 2 (and max of 15), so the different results come purely from changes to the falloff, but by adjusting the other values a huge range of options become possible. For comparison, here's a logarithmic falloff with a longer plateau (radius 8~15):

This falloff sample has a longer plateau than I generally use, but it can come in handy for some purposes.

On every player move, or with any action that might have affected the amount of sound reaching the player's location (terrain destruction, machine toggling, etc), the audio sources potentially within earshot of the player pathfind to the player to determine how far away they are for volume determination purposes. The final new sound profile for the player's current location is compared to the any sounds that were playing from the previous state, and the old state fades into the new state, which might involve simply slowly adjusting the volume of the same set of sounds, adding new sounds, or gradually removing those that are no longer in range.

Visualizing the sound paths from each nearby audible machine, paths which are used to determine the final volume at the player's location.

Using a system like this is both quick and makes it pretty easy to account for dampening effects of the path successfully passing through materials, like the doors in Cogmind which block 50% of the volume. You can see the effect of doors in the falloff samples from earlier (it's most noticeable in the reverse log demo), but here's another still shot using the sound path visualizer in which you can see the volume dropping quickly when passing through doors.

Doors to two rooms lowering the volume of the machines heard within.

So that's the underlying architecture we're working with here, let's move on to where the soundscape actually takes shape.

Audio Style
Naturally a lot of games tend to use music to fill the role of "continuous audio," which when done well is instrumental in conveying the desired mood, and possibly atmosphere as well.

It can also be great to just enjoy out of game. I personally love VGM, having listened to it for the past 30 years (I guess since before listening to VGM was a thing many people really did :P), and in the early years recorded the music from console games on my TV to create OSTs and mix tapes. Later on importing OST and arrangement CDs from Japan became a thing, so I did a lot of that, too, and still listen to the original rips I made to this day...

So yeah getting a Cogmind OST by a proper composer would be pretty damn awesome, but at the same time developers need to choose for their game the type of audio that will best achieve the vision for its world.

The audio style discussion has played in some form or another, in some place or another, pretty much every year of Cogmind development so far as different players ask about it, or I bring it up myself when planning for the future. It was once even the topic of a post here on the blog, back in 2017. Over the years I've certainly been collecting a list of interested composers, or others that I've become interested in, and analyzing whether or not I think they'd be appropriate for this particular job if it came to that. Many have also approached me asking about Cogmind, including a number of players.

For now though, music is probably not right for Cogmind. With an emphasis on immersive atmosphere, and a semi-realistic dark sci-fi one at that, I think environment-driven ambient audio would better fit the role. Even if it doesn't work out the way I envision it (spoiler: it does), considering that the architecture for an environment-based ambient audio system already exists and the only further need is to add the content, and doing so involves fewer challenges and commitments than working with a third party composer, it makes sense to start with this approach and experience the results to hear for ourselves. Let the machines and other objects of the world dynamically create the soundscape, and if that works then we're all set.

Then there's the additional benefit of this approach: it's heavily focused on sound effects and loops, which I'm familiar with after working with them for many years, and is also something I can manage on my own, which in my book is always a plus over bringing in outside help. It means that iterating is faster, and I have more direct control over making sure each step along the way is successfully integrating with my vision. Also of course when I inevitably need more content I'm always available to add it :P

That's what the rest of this article is about--the process behind pulling that soundscape together.

Machine Loops
The main focus of the ambient audio is Cogmind's machines, of which there are over a hundred.

Technically before reaching this part of the development process, in previous years I'd already added loops for 17 special machines and other various sources especially meaningful to the plot or mechanics. At the time I didn't want to wait on those since in some cases they're quite important, so it made sense to emphasize their impact with audio as soon as possible. "Fluff" machines could wait, but not things like machines capable of significantly changing the entire run :P

With such a large number of machines, providing sound for all of them is a rather daunting task, so we do what we do with all daunting tasks: break it down! I first roughly identified the different categories of machines in Cogmind from an audio perspective. (Technically Cogmind machines were already divided into themes for map placement purposes, but those categories do not always align perfectly with what kinds of audio you might get from them, hence the need for alternative audio-specific categories.)

Here's the breakdown as reflected in the ambient loop directory structure, including the number of loops in each as of this writing (there will no doubt be a few more added in the near term, but most everything has audio at this point):

The current tally of Cogmind's ambient loop files. Ambient audio is sourced from "props," which are anything in the environment that is not a cell, item, or entity (robot)--generally machines for the most part.

"Interactive" refers essentially to terminal types, all of which were originally using the same placeholder loop, but now every faction has one or more unique sounds for their terminals. They look and operate differently, so it only makes sense to differentiate their sounds, too :D

"Prefab" includes machines I draw directly into hardcoded map sections via REXPaint, those with a unique name and possibly function as well. (Read more about prefab development here.)

The "Theme" directory contains all the machines that are procedurally inserted into maps. A majority of these are fluff, though in particular the "Special" subcategory includes all the explosive machines and a few with unique functions. Among the Theme machines I did that group first to ensure they got first pick from the audio resources I was working with, since they're more important.

In terms of actually creating the sounds, I've already covered that before in the sound design how-to article I wrote in the early years of the project. Reminder: I don't do this from scratch, instead using existing samples and editing them as necessary.

I spent a couple weeks going through lots of samples looking for what sounded like my vision for each machine in question. Obviously since it's sci-fi there's often a lot of leeway for interpretation, but still important to be consistent. Working with a single category/subcategory at once, I'd use Audacity for looping all the tracks, adjusting or mixing some of them for better effect.

Editing Cogmind's machine loops in Audacity.

As each category's loops were completed, I'd fire up Cogmind's sandbox mode to hear them in game and adjust sound propagation values as appropriate. The sandbox contains one of every themed machine, making it more convenient to do this than actually finding them in game.

Cogmind's development sandbox, which has grown incredibly messy over the years since it has continued automatically expanding itself based on game content, but I don't really use it much anymore--it was instrumental in early development but barely gets loaded up these days.

However, the machines in the sandbox are also quite close together, which would interfere with the task of making machine-specific adjustments (although the proximity does come in handy when testing out overlapping audio from different machines!). So right away I needed some new debug features to make this job easier.

Enter audio toggling. It was suddenly important and very useful to be able to toggle all ambient sources across an entire map, as well as toggle them individually by source. This functionality would also be of help once we get to the stage of testing ambient audio in regular map environments.

Toggling ambient audio sources in the sandbox.

Now I could more easily hear any given machine in isolation, and test how its audio propagation settings worked for its particular sound. I started everything with reasonable default propagation values, and adjusted from there. These values are set in the external data file shown earlier, a file which requires a game restart in order to load any changes. So while at first I was determining final values by listening to each machine and making educated guesses about what it should be changed to before restarting, this approach is slow and incompatible with the sheer amount of content being worked with here.

Time for another new debugging feature!

Rapid iteration is important, so I added a way to dynamically adjust a given audio source's min/max radius and falloff using the debugging console, making it possible to immediately experience the results of any change and easily experiment with different possibilities.

Adjusting machine audio propagation settings dynamically.

This continued for more than 100 machines until everything seemed to have suitable values...

Of course with all this audio content going into the game at once, it's about more than just editing loops for individual sources--we'd also need to take a look at the atmosphere as a whole and ensure it's properly balanced, and I'd need new tools to facilitate that process as well.

First of all, as I walked around real maps it became apparent that the default linear falloff model I'd been using for most machines didn't actually work that well when applied to all machines across the floor. I'd started with that type because it happens to be what was used all these years for the special prefab machines added before this new undertaking, and it works there because those tend to have longer audio ranges and I wanted them to be pretty clearly identifiable shortly after they come into earshot. Not so with all the generic machines scattered about. (When applied to them, a linear falloff makes the ambiance feel more confusing with a greater number and variety of sounds quickly fading in and out as you move around.)

To experiment with a new default falloff model, I added a console command to simultaneously switch all machines to a different model, eventually settling on logarithmic as the default:

Testing a couple of different falloff models under the ambient audio visualizer.

Another factor to explore was the extent of silent gaps between areas of machinery on various maps. Technically we could fill an entire map with machine audio if the ranges are long enough, although this would also mean more overlapping and general cacophony. Still, to test the size of gaps and see how changing average audio ranges might affect the experience, I also added the ability to simultaneously adjust the range of all sources:

Adjusting machine ambient ranges across an entire map at once.

When the majority of machines had ambient audio, I did a dev stream to demo the intermediate results while talking about the process and exploring what maps sounded like at that stage. Still very WIP at that point, but it was exciting to finally hear the soundscape taking shape!

One thing clear from walking around was the lack of normalization--some machines are clearly too loud relative to others (some also seemed too quiet, but we'll get to that later in the section on mapwide ambience). So the next thing I worked on after the stream was addressing that issue, starting with yet another console-based convenience feature: the ability to reduce the base volume of individual machines on the fly, in game. Commence rapid iteration!

(Normally I'd show you a gif of realtime volume adjustment here, but the ambient visualization system only reflects relative volume numbers rather than absolute volume, so it wouldn't be much use since nothing appears to change when this setting is modified :P)

After confirming this would give satisfactory results, I made it a part of the architecture, i.e. machine audio samples could have their base volume reduced via settings in the game data. This means it would be possible to avoid resampling all the associated audio tracks, which would be pretty time-consuming by comparison. In all, I lowered about half of the machines' volume by 50~75% through this method in the week after that stream.

(continued in the next post...)

Level 9

View Profile WWW
« Reply #1277 on: June 14, 2020, 03:42:50 PM »

(...continued from the previous post)

Mapwide Ambience
A soundscape composed primarily of the humming, whirring, buzzing and clanking of machines is great, though there are always going to be some gaps, places where machine audio doesn't reach. The idea is to fill those with a general ambient track, preferably a different one for each unique map type.

To demonstrate the gaps relative to the areas from which machines are heard, in these images I've used a separate color (blue) to highlight gaps, or any location reached by absolutely no sourced ambient audio:

Audio gaps (blue) compared to sounds emitted by machines (orange), in part of a Factory map.


Audio gaps vs. machine audio in a sample Garrison map.


Audio gaps vs. machine audio in a sample small Materials map.

Although sometimes silence is a good thing (and put to use for that reason), it's not great in areas that are otherwise brimming with machine activity, since repeatedly passing between louder and completely silent areas can be unnecessarily jarring and weird.

So we've gotta fill those gaps with something. Enter mapwide ambience.

We've actually had a couple of mapwide ambient tracks in the game for years now, originally labeled placeholders and essentially added to test out the system and also let players know this is a likely feature to be expanded upon. The one with which players will be most familiar is in the cave areas, a spooky organic drone that many commented on as being quite fitting for the area, and still others said they'd never even noticed xD (because technically I set the sample to quite a low base volume, and whether or not certain players could hear it might depend on their audio setup).

To fill gaps on other maps I wanted to expand on this idea, for the most part just using very low-key synth drones to act as a bridge between areas with sourced audio and set the overall tone with your average sci-fi background fare. Overall the tracks I'm using are relatively dark and mysterious, fitting with Cogmind's general atmosphere.

Now instead of 2 mapwide tracks we have 26 Smiley

I might go on to add additional random faint sound effects as necessary to serve as "accents" for the generic loops to liven the audio up just a bit, although I haven't done that at this phase yet, and even if it were to happen it probably wouldn't be until after Beta 10 releases with all the new audio, in order to leave time for broader feedback.

One issue that popped up with the mapwide tracks is that their desired volume level in otherwise silent areas could easily drown out some fainter or deeper machine sound effects when applied at the same level across the entire map. The answer seemed pretty obvious: Just lower the mapwide ambient volume when around other machines. Cogmind dynamically reduces the ambient volume by 50% of the loudest foreground loop's volume. For example if the player is passing near a machine they're hearing at 80% of its max volume, then the mapwide ambient audio is set to 60% volume (100-(80/2)). This seems to work quite well!

Visualizing only the volume level of the mapwide ambient track as it varies across a section of Factory map (as usual darker represents quieter).

As of this writing and the latest prerelease build I released for patrons, Cogmind gained an additional 117 sourced ambient sounds over the previous release and the soundscape is really coming together. It adds to the atmosphere without generally being too overwhelming despite the number of possible sources. There's usually no more than 2-3 different types within earshot of each other anyway, if that.

Visualizing the variety of machine audio across a Factory floor, where each unique sound is associated with a random color.

These plus the 24 new mapwide tracks did, of course, expand Cogmind's disk size--a clean install now weighs in at 43.5 MB, a 45% increase over Beta 9.6. The audio samples went from comprising 46% of install size to 63%. Overall still pretty lightweight considering the massive number of samples included (by indie game standards), but Cogmind is certainly getting a bit hefty since its 3 MB 7DRL days Tongue

To see the latest WIP version of Cogmind's soundscape in action, check out my first Beta 10 prerelease stream where we'll explore the audio while fooling around and kicking butt:

In the next article we're going to take this whole thing to the next level by adding a closed caption-like feature in the form of an audio log, so you can get the full tactical advantages of this audio system even with the sound off! (Actually you can already see it in action in the stream recording above, but I'm going to go into detail about its design and the challenges I encountered in building it.)

Level 9

View Profile WWW
« Reply #1278 on: August 25, 2020, 01:11:52 PM »

Cogmind leaderboards are back in action!

The highly detailed new scoresheets introduced for Beta 9 finally have a centralized home :)

You can read more about them in the full announcement.

Leaderboards linking to detailed run stats have always been a great way to increase community engagement (among their many other uses), but were out of commission for a while as a new system was being built.

Level 9

View Profile WWW
« Reply #1279 on: September 14, 2020, 02:30:49 PM »

The full ambient soundscape is here, and it's not alone! Cogmind Beta 10 is a major release that also comes with expanded bothacking abilities, two more alternate endings, many more types of drones, and of course lots of other features to improve the overall experience.

For more details and demo images check out the release notes on Steam or the forums. (Only the latter has the entire changelog in text form, though, because it's huge and vastly exceeds Steam's character limit on news announcements xD)


Pages: 1 ... 62 63 [64] 65
Jump to:  

Theme orange-lt created by panic