• About
  • My Games
  • My Stories

a little bit of everything all of the time

~ Thoughts on stuff and things.

a little bit of everything all of the time

Category Archives: QA

Succor Postmortem

15 Tuesday Apr 2025

Posted by abc in Game Design, Game dev, QA

≈ Leave a comment

Tags

game creation, Game Design, Game dev, game review, gamedev, games, gaming, postmortem, video-games

WARNING! SPOILERS FOR THE GAME INCLUDED IN THIS POST!

I’m quite excited to share this postmortem! 

 I’ve finally returned to Succor, a game initially made in a jam, and given it a major overhaul and update. I feel comfortable with where the game’s state is (though there’s always going to be a temptation to tinker more) and I’m happy to call it a finished, polished play experience. Most of my game creations are jam experiments, so it feels particularly nice to be able to put a stamp of “finished” on a game – one step further down the road in becoming a proper game dev!

Background

This game in particular feels a bit emotional to finish. Not only does the game cover rather deep and dark topics about trauma and memory, it’s my first coding project in nearly a year after struggling with major health setbacks. For many months, I couldn’t even sit at a computer, much less wrangle my brain into coding or writing extensively…but the final word count is around 20,000 words! Phew!

The original jam game was a small experiment in how traumatic memories can be sparked by things as mundane as reading a menu and encourages players to battle these demons by making either constructive or destructive choices. The new version has expanded on this concept, with many more additions to content.

Code and Design Updates

As this was a project created fairly early in my game dev journey, a lot of this code was a MESS and I spent a decent chunk of time focusing on behind the scenes things, such as creating widgets (Twine’s versions of functions) to streamline creation. Some old code I merely tinkered with a bit, as I didn’t want to get caught up in too much refactoring, as I didn’t want scope to run away from me. At the end of the day, this is an experimental text game, so “good enough” works for many things.

One major change I added was creating a function to track the game’s demons and adjust how demons were assigned to appear though the game. Originally, demons were simply tied to menus: browsing the menu for a bakery spawns a demon for addiction, for example. Our wonderful artist had created several additional pieces of artwork and I wanted to include these as well, so I ended up expanding out the available menus to give each demon one they were tied to. However, I felt simply adding more menus to the table would be a rather dull play experience, so I instead added several “hidden” menus players can find through cleaning the house, as well as some lurking demons triggered by the act of cleaning itself – and then to give the game a bit of replayability (because there are multiple endings and achievements), I decided to shuffle around where they were each new game.

<<set $demonsToDo = Array.from(setup.demons.list)>>
<<set $menusToDo = Array.from(setup.menus.list)>>

This code creates an array of all the potential choices for both demons and menus at the start of the game (storyInit as well as a resetVars widget which runs when the player returns to the main menu at the end of the game). It pulls these values from javascript objects.

setup.demons = {
    list: ["insecurity", "humiliation", "addiction", "loneliness", "abuse", "rage", "regret", "envy", "lethargy", "paranoia"],
...
}
setup.menus = {     list: ["indian", "pizza", "french", "sweets", "bbq", "italian", "chinese", "grill", "turkish", "cajun"],
...
}

It then plucks (randomly removes a value from the array) , creates different menu details and removes the demon associated with that particular menu. So if “sweets” was plucked, it would pick one of the random names for a restaurant (eg “The Sweet Tooth” or “Toothsome Temptations”) and also set the associated demon. 

<<set $menu1 = $menusToDo.pluck()>>
<<set $menu1name = setup.menus[$menu1].random()>>
<<set $menu1Demon = setup[$menu1].demon>>
<<run $demonsToDo.delete($menu1Demon)>>

NOTE: This code is one example of the “good enough” type of coding I was talking about above – if I were to continue work on this game, it would definitely be much more efficient to create a loop for this assignment, as well as a much better set of relationships for how I’m handling these values, for example something like an object to store all the different information about each menu. Since this was a continuation of a very old game when I was a lot newer at coding, I decided it was easier to just be a bit sloppy and finish the project using some of the existing framework instead of getting lost in the weeds optimizing.

Once the menus were built, the first 3 were assigned to the main table in the game. 4 more were tucked away to be found when the player finishes cleaning different parts of the house (for example, once a cupboard is fully clean, the player discovers a menu tucked away in the back), which leaves 3 more demons to spawn at random. The following code basically tracks how many actions the player has done and if they are above 20 actions, we spawn a demon:

<<widget "demonspawn>> 
    <<if $demonstodo.length > 0>>     
        <<set $movecount += 1>>     
        <<if $movecount > 20>>         
            <<set $movecount= 0>>         
            <<set $currentdemon= $demonsToDo.pluck()>>            
            <<dialog>>             
                <<print setup.demons[$currentdemon + $currentroom "1"]>> 
                <br><br>
                <<print setup.demons[$currentdemon + $currentroom "2"]>>             
                <<close>>       
                <<onclose>> 
                    <<goto $currentdemon>>    
            <</dialog>>    
        </if>> 
    </if>> 
<</widget>>

I then used this widget in any room/passage for activity where I wanted a demon to potentially spawn. For example, since there’s a menu hidden in the cupboard, I didn’t use demonspawn in those passages and instead just manually added to movecount. If I were to optimize this, I’d probably split the movecount and the spawning into 2 different widgets or make javascript code to apply to click events/passage navigation and just exclude the places I didn’t want it to run.

Some feedback I got from the early version of the game is that people didn’t realize there were variants of text for descriptions of items, as I had just been pulling text using .random, so I changed many of these messages to cycle, using the method of creating an array I outlined above. Halfway through changing all this over, I realized I could be a bit lazy and use this process to also cycle through the cleaning process. The code below will check for the size of the array and if it’s empty, it will set the bed to cleaned and execute cleaned logic (giving willpower, checking for an achievement for cleaning everything, etc). If there are still values left in the array, it will shift the array to remove the first element and display that.

setup.bed = {
...
clean: ["You begin by stripping the pillows and sheets - judging by the rather...err...ripe smells, it's far past time they were washed. You've just been so exhausted and haven't had the time, but now that you're doing it, you find yourself looking forward to having a chat with neighbors when you bring the laundry down tomorrow.", "You rummage in your tiny closet for spare sheets and pillowcases, dislodging an old box of photos. You spend some time glancing over better days and set aside a few photos from travels with old friends.", "You wrangle with the fitted sheet, starfishing on the mattress until you triumphantly manage to tuck in all four corners.", "You give your pillows a hopeful fluff and toss them atop the made bed. It's not the most luxurious sleeping arrangement, but it definitely looks a lot more inviting and restful than when you started."],
...
}
<<set $msgBedClean = Array.from(setup.bed.clean)>>
<<if $msgBedClean.length == 0>>
<<set $bedClean = 1>>
<<cleanDone>>
    <<dialog>>
<<include bedMenu>>
    <</dialog>>
<<set $msgBed = Array.from(setup.bed.cleanDone)>>
<<else>>
<<clean>>
<<print $msgBedClean.shift()>>

UI Updates

My goal with the UI update was to lean into the hand-drawn art’s sketchy style and create the impression of the images and text being words in someone’s journal (especially since a journal is an interactable object in the game, where you can even add custom entries!). I browsed the internet and found some useful codepen examples for the stacking pages and tape corners and tweaked those until I was happy. 

Original UI:

Updated UI:

This is another “good enough” moment. I could keep improving the UI, but then I’ll end up down the CSS rabbithole for ages, so I basically had to stop myself and say “it looks fine.” I might go back and add a color-blind mode as I definitely think that might be a problem :/

Art Updates

The artist for this game had previously sent me some extra art they had done which we didn’t have time to add to the project during the jam, due to running out of time. I really wanted to be able to showcase these pieces, so I added in more ways for players to find demons as noted above. 

One issue I ran into is that our format for the menus used a header art image, so creating new menus without those would stand out a bit. 

Example menu page:

I first went through the existing art to determine if I could double-dip on any of the image. For example, the image of an outdoor grill for a bbq restaurant also worked great for a burger joint and by cutting out the distinctive pillars of the Taj Mahal (for our I ndian restaurant) I was able to have a mosque that kinda looked like the Hagia Sofia (for a Turkish restaurant). I began to run out of choices, however, until I realized the French image could make an easy shift to a logo for a cajun restaurant!

All I had to do was crop the fleur de lis, copy it and rotate the copies to flank the main one and ta-da! A quick little logo conjuring up New Orleans:

I also wanted to add some visual progress to the images of the house so players would see the image changing as they cleaned (eg the bed would become made). The artist had originally given me one overall finished image for the main room, but I needed to create steps for each element as well as create updates for the kitchen. For the main room, I copied each side of the room from the finished artwork. I then pasted each on top of the messy room and used smuge, blur and a very diffused paint tool to help make the lighting match. I also created some photographs to paste on the wall around to bed to reflect text about the player hanging them up. I used the blur tool on these to soften them and make them match the sketchy art style of the existing art. I also added a few dots to represent stars in the now-open window.

Original messy room:

Bed made, couch still torn (there’s an equivalent for couch repaired and bed still messy):

Final cleaned room:

For the kitchen, it was a lot easier. I just carefully erased away the dishes in the sink and drew in an arc to represent the bottom of the basin, and erased smuges on the stove. I added the same photos that were hung around the bed along with some basic shapes to represent magnets, and tada, fridge was transformed.

Some similar tweaking was done for the final page before the ending, where the player faces the final demon: their own reflection in the mirror. I used the existing image from the TV achievement (which is…a TV screen), filled in the outline around the screen, erased the antennas, and added some parallel diagonal lines to represent light reflecting off the mirror. It’s not amazing, but it’s functional enough to do the job!

Audio Updates

I added a few more songs to the playlist, retaining the theme of classical piano. Finding these gave me a nice mental break between working on other parts of the project.

I also found several different audio snippets of pages turning, to have the sound match the new “journal” style UI. The code below defines the names of the audio events and randomly shuffles plays one whenever parts of the game are clicked.

setup.audio = {
  pageturn: ["pageturn1", "pageturn2", "pageturn3", "pageturn4"]
}
$(document).on('click', 'button, a, .clickable', function () {
    Wikifier.wikifyEval('<<sf>>');
});
<<widget "sf">>
<<set _click = setup.audio.pageturn.random()>>
<<audio _click volume .3 play>>
<</widget>>

Writing Updates

A large chunk of time was spent on this. Our original game was very black-and-white (teehee) in how we portrayed the player’s relationship with their mother. She was basically this flat, one-dimensionally evil character – but that’s not how real relationships or people are, so I spent a lot of time fleshing out nuances of the relationship through memories. 

I added a dad and obliquely hinted that he had passed away, which changed the dynamic between mother and player and led to the shift in the mother’s behavior. I enhanced this by using seasonal references to indicate what part of the memory timeline the player is recalling, cycling from summer to winter and back into summer as the player left home to try to find their own happiness at culinary school.

  dolmaMemory: [“You remember how one summer all of you took a family cooking course. Dad had roared with laughter as he watched the mess you made trying to roll dolma together with your chubby fingers, before scooping you into his lap to help guide your efforts. Mom had kissed him on the head and tenderly squeezed your shoulder…You suddenly find the thought of the dish unappealing as you imagine some other kid learning to make it, some other child having what you lost.”],

 breadMemory: [“You are struck by a bittersweet memory of making bread with your mother. That day was one of the few great ones you can remember with her. It was autumn, the air chill and crisp, before dad’s test results kept getting worse. You slathered the crusty slices with butter and dunked them into a hearty chicken soup, a cozy meal against the gathering storm. Was it your fault that everything changed?”],

  beignetMemory: [“Snowflakes mounded soft as sugar outside the hospital that day near the end and the sky was a blueberry bruise. You reflect on how the ugly can nestle among the most beautiful moments – the discordance makes your head spin and you catch yourself nervously glancing towards the window, as if reassuring yourself the day outside is appropriately gloomy.”],

lemonTartMemory: [“You’ve always loved lemon desserts. There’s something about the light citrus that is always refreshing. You remember one sun-drenched spring day, not long after dad was gone: your group of friends rode bikes to the store, pooled pocket money, bought a box of cookies and gorged. Powdered sugar smiles beneath cotton-candy clouds – worth the stomach ache that night to forget the feelings for the afternoon.”],

  eggrollsMemory: [“You can’t help but crack a bittersweet smile, remembering one group outing after culinary class let out for the summer break when a crowd of you went out for dim sum and bonded over boldly trying everything on the menu. Cart after cart rolled by, depositing steaming baskets of dumplings, fried morsels, delicate desserts, and your stomach swelled, aching from overeating…but moreso from laughter. It was a good day.”],

The overall goal was to create a deeper, more emotionally rich story with room for sympathy for the maternal figure while enhancing the pathos for the player’s character.

Overall

All in all, I’m happy with my updates!

I think one important takeaway is recognizing scope and limiting it where needed to ensure something complete is produced, instead of endlessly tinkering. This is, at the end of the day, an experimental art project – it’s not something I’m going to sell so it doesn’t need rigorous polish or expansive gameplay. It’s updated enough to look slick and the gameplay and story have been expanded enough to tell a well-rounded, self-contained narrative.

Could this be better? Sure, but what I’ve produced is definitely a clear sign of my progress in both my health/brain recovery and in my growth as a dev – which seems pretty fitting, given it’s a game about moving past trauma through constructive choices. I certainly did some constructing! 

Check out the game here: https://loressa.itch.io/succor

Share this:

  • Share
  • Click to email a link to a friend (Opens in new window) Email
  • Click to print (Opens in new window) Print
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on X (Opens in new window) X
  • Click to share on Tumblr (Opens in new window) Tumblr
  • Click to share on Reddit (Opens in new window) Reddit
Like Loading...

QA Thoughts

06 Saturday Oct 2012

Posted by abc in Development, Game Psychology, QA, Uncategorized, World of Warcraft

≈ Leave a comment

I started out playing MUDs (text-based MMOs) and developed a knack for breaking games. I quickly became a go-to playtester, which I then transitioned into QA work with first SCEA/PlayStation and then third party work for Microsoft Game Studios.

Playing this expansion, and previous expansions, has been fun and exciting, but there is always a jarring sense of removal from the immersion or a frustrating barrier to gameplay when a bug, glitch or issue is encountered. This may be as trivial as a typo, and it may be as far reaching as the gyrocopter issue the Alliance faced at the launch of MoP. I am referring specifically to issues covered by the QA department, versus the design or balance teams.

This issue is hardly unique to WoW. I can’t play GW2 without encountering a crash every few hours due to a glitch involving instancing with parties. Hell, when I played MUDs, I once found a way to use the game’s mail system to physically mail myself to an admin. There are always bugs that go live. However, the QA department’s role is to ensure as few of these happen as possible. Beyond that, their job is also to ensure that the most LIKELY scenarios are all fully tested.

QA teams use a process called test casing to cover these most common potential circumstances. They can’t blindly, blithely and happily prance around the game just checking out what suits their fancy. Sure, in the early stages of a game’s development, most testing is exploratory, but, as it gets closer to release, testing is narrowed down to systematic examination of various elements. Test cases direct QA teams to rigorously check off functionality for a variety of conditions.

For a highly simplified example, a test case for Warsong Gulch might be broken down into various components such as joining the game, winning the game and losing the game. Test teams would then check the various conditions applicable to each category. Joining might include testing joining the game solo, with a party, with the game thumbed down, via random queue, via specific queue, etc. This structured testing ensures that all of the likely scenarios are fully tested for functionality before the game goes live, versus just assuming it will work in a party because it worked solo.

OH GOD WHERE DID THE WORLD GO

This is not good QA.

I explain all of this so I can make it very clear that video game QA is not a fun and games job. There is a lot of work involved, including time spent planning out the testing before the QA team even sees the game elements they will be working on. This is a serious career and talents beyond just “leet gaming” are required. A good tester should be meticulous, pay close attention to detail and be capable of looking outside the expected norms of gameplay.

Unfortunately, the video game industry suffers from its own history. What was once a cowboy industry started in basements is now one of the most profitable aspects of the entertainment industry; millions of dollars are spent on video games each quarter. Video games showed INCREASED revenue during the recession, while other aspects of entertainment suffered from a decline in sales.

The internal structure of the video game industry, however, does not seem to recognize its own success. Video game QA practices are outdated, following the same model initially developed out of need: toss a bunch of low paid “testers” at the product and hope their enthusiasm for the industry itself balances out all of the downsides inherent in the job. A decade ago, this practice was not only money-savvy, it was necessary. Video games were not a serious industry, so you had to hire what you could and scramble with the resources that gave you. This meant that, inevitably, you ended up with a crunchtime environment as “showstopper” bugs (ie, issues that made the game nigh unplayable) emerged only in the very latest stages of testing.

When you aren’t working with a highly experienced test corps, major issues can lurk undetected until late in the game, and then overtime is requisite to iron out these bugs, as the testers need to regress bugs, that is, test the issues again to see if the bugs have been fixed. Here is a good (if slightly outdated) blog explaining why this is inefficient (and fiscally wasteful):  http://romsteady.blogspot.com/2006/04/testing-hidden-costs-of-testing-at-end.html

Tsk

This is also not good QA.

Having worked in QA, I know that it’s more than just inexperience that results in these kind of lurking issues. First, many QA departments pick up speed later in the test cycle and then have the bulk of their work staffed by entry level testers, versus retaining a smaller fulltime team of more experienced testers. Many companies claim it saves money (again, see the breakdown in the link above), but it really does seem to be a relic of the earlier days of the industry. Not only do you have to deal with the initial acclimation and training period, this sort of mass hiring (often through a staffing agency) picks up a…wide…caliber of applicants. But why should video game QA teams expect anything else? The industry’s focus on late-cycle testing means that unskilled hires are more desired because they are cheaper…and skilled testers end up migrating outwards to other QA fields. This also means that the workload demand for non-sustainment games (eg games like console games that don’t have ongoing development) fluctuates from a trickle to a flood – ie very little work (sup, unemployment) and then way too much for a small team to handle. In essence, there is very little career mobility in video game testing, and the initial hire process is inclusive enough, often due to to not distinguishing between stellar applicants and mediocre ones.

Here are some numbers to illustrate this (all income is done with location based in Los Angeles, as SoCal is a large gaming hub):

Salary.com:
Software QA lead $50k/yr
Video game QA lead: $15/hr (unsalaried)

Payscale.com (using 0 years experience, BS for both):
Entry level software QA tester: $47k/yr
Entry level video game tester: $31k/yr

This drastically lower pay for video game QA combines with the inevitable crunch time to make the job undesirable for workers on an actual career path. Why take constant overtime when you are getting older, perhaps starting a family – that is not ideal for a skilled tester who wants to maintain a career. Due to these factors, many solid, skilled testers eventually transition to straight software QA.

One of the biggest problems, however, is the job hiring process itself. The video game industry, while profitable beyond belief, still has a very silly stigma applied to it. When jobs – like tester jobs – are outsourced, the hires are often done by HR people who don’t really work in the industry, so they advertise the job as “cool” and “fun” rather than focusing on the skills you will develop. This will inevitably lead to a certain type of employee, and it’s not the one who is doing the best work. In my opinion, the best QA testers are the ones who are unfamiliar or don’t have a direct passion for the project – they won’t be sidetracked by just playing the game for fun or get caught up in how the game “should” be and fail to see the forest through the trees. True, the employees who are slacking off and just playing around may eventually get fired for not doing the job well, but think of the wasted time hiring/training/firing them takes, when it could have been avoided from the outset with proper recruitment.

So, to bring this post to a conclusion…

I’ve been on the test floor. For years. I know what goes on there. Sometimes it’s testing. I am not pretending to know the full extent of all the QA department’s hiring practices, but the Blizzard employment website does make it clear that testers are contract workers, so it’s implied it’s quite similar to other large video game test companies. I know PlayStation is the same.

In that case, the fact is, the amount of GOOD testing you get is miles away from what you COULD get. I’ve seen how test passes ACTUALLY go. Factor in everything: the low pay, the lack of career mobility, the poor recruitment, and here is the truth – testers lie. Especially low paid, recently hired, unskilled testers. I’ve seen an incredible amount of bugs in MoP and I doubt any of them are the fault of the QA leads. For example, if two teams reach max points in Silversong Mines at the same time (one through escort, one through capture), the battleground bugs out. Forever. People have been in matches that have lasted nearly 2 REAL LIFE days. This is a win condition that a test pass would have testers checking, no question – but, oh man, getting the timing right is so HARD, so you get them just passing it as functional.

This is best QA.

This is best QA.

Maybe I’m entirely off-base. Blizzard is fairly close to the chest with its internal affairs. But, like I initially stated, I’ve worked in QA and I’ve seen, firsthand, a frustrating level of unprofessional behavior and goofing off from employees.

I like working in video game QA. It’s a constant challenge and the job makes me think. I do, however, lament it sometimes when I see stupid bugs that I know should not have made it past testing. I can only hope that one day we’ll see changes to the industry itself that create an entirely new QA system for video games – and maybe we’ll all see the benefits. Hell, maybe some of my friends will be the ones implementing them. I think the effects would be profound for the video game industry.

Share this:

  • Share
  • Click to email a link to a friend (Opens in new window) Email
  • Click to print (Opens in new window) Print
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on X (Opens in new window) X
  • Click to share on Tumblr (Opens in new window) Tumblr
  • Click to share on Reddit (Opens in new window) Reddit
Like Loading...

YAY! I WRITE STUFF!

A blog for random discoveries, musings, feedback and ideas about gaming, fantasy and life. And probably kittens. I love kittens.

Just type in your email and get it all in your inbox. SO EASY OMGYAY!

Join 21 other subscribers

RECENT POSTS!

  • Fodder October 3, 2025
  • Sleeping Body September 25, 2025
  • Revolution of Sound September 25, 2025
  • Microwave September 25, 2025
  • Eternal Teaparty September 25, 2025

ORGANIZATION AND WHATEVER!

TYPE IN WORDS HERE TO FIND THINGS!

VISIT THE PAST ARCHIVES! OOOOOOH MYSTERIOOOOUS TIMEY WIMEY STUFF!

PEOPLE SAYING THINGS IN COMMENTS!

Shanthi's avatarShanthi on Back to MoP
abc's avatarabc on Back to MoP
Unknown's avatarDisc Priesting for T… on Spirit shelling your way throu…
Shanthi's avatarShanthi on Back to MoP
Unknown's avatarSo I flipped 6500 ca… on Living steel

I AM LEARNING TWITTER! :D

Tweets by jjloraine

STUFF I LIKE TO READ!

  • Super Shock Gaming Zone
  • Ray Ferrer - Emotion on Canvas
  • Edge of Humanity Magazine
  • a little bit of everything all of the time
  • Crafts Thrill
  • What's Your Tag?
  • And fallen, fallen light renew
  • Reputation Grind
  • Superior Realities
  • The Warchief's Command Board
  • Under Construction
  • Be MOP

Blogroll

  • Admiring Azeroth Great screenshots and pet battle info.
  • Bakuenryu! Awesome series about leading a raid team
  • Be MoP A student’s look at the latest expansion
  • Doomed…ish Write-ups of my D&D fun.
  • Holy Word: Delicious Priesting stuffs
  • Info from Nightwill the Altaholic A great general info blog, with a focus on roleplay, lore and creativity.
  • Lair of the 4-eyed Monster D&D and art blog
  • MMO Melting Pot Summaries of the best MMO blog posts of each day!
  • Notes from a Burning House Personal Reflections and Flights of Fancy
  • Orcish Army Knife Great writing on general WoW, with awesome lore posts.
  • Psychochild A developer’s musings on game development and writing.
  • The Warchief's Command Board Thoughts and Musings from Garrosh Hellscream (HILARIOUS parody blog!)

Meta

  • Create account
  • Log in
  • Entries feed
  • Comments feed
  • WordPress.com

Blog at WordPress.com.

Super Shock Gaming Zone

Super Shock Bundle

Ray Ferrer - Emotion on Canvas

** OFFICIAL Site of Artist Ray Ferrer **

Edge of Humanity Magazine

An Independent Nondiscriminatory Platform With No Religious, Political, Financial, or Social Affiliations - FOUNDED 2014

a little bit of everything all of the time

Thoughts on stuff and things.

Crafts Thrill

What's Your Tag?

Video Games, Comics, and Shenanigans.

And fallen, fallen light renew

An ongoing fiction.

Reputation Grind

It doesn't end at exalted.

Superior Realities

The Warchief's Command Board

Under Construction

Be MOP

  • Subscribe Subscribed
    • a little bit of everything all of the time
    • Already have a WordPress.com account? Log in now.
    • a little bit of everything all of the time
    • Subscribe Subscribed
    • Sign up
    • Log in
    • Report this content
    • View site in Reader
    • Manage subscriptions
    • Collapse this bar
 

Loading Comments...
 

    %d