Game Design Retrospective: LinkedOut
I have a graveyard full of unfinished gamedev projects, and I thought it would be fun to talk about some of these efforts. Here's a job search simulator!

This is a new series I hope to do that focuses on some of the game projects that I work on in fits and bursts. Currently, I'm in a dormant period, and not working on any games. Many of my projects tend to stall out past a certain point, but I'm revisiting them in the hopes that I can showcase things I did, and maybe find inspiration to pick them up again.
Setting the Stage
Rewind back to April of 2019. I had just left a job at Sentry due to disagreements and difficulties in working with management, and was dealing with a long and arduous process of applying for a new tech job. The hiring process in the SF startup scene is tough: there's a lot of hoops to jump through, and I found myself dealing with a lot of teams that didn't care much about my accomplishments or personality.
As the rejections started piling up, I found myself becoming bitter. Most companies in the space have a multi-phase hiring process that includes crafting a resume, writing a cover letter, doing various take-home tests, and enduring multiple phone calls before eventually doing an on-site interview with members of every team. It's exhausting: at any part of the process, you can face instant rejection. For every 100 jobs you apply to, you might hear back from 5 of them.
Introducing LinkedOut
The name is something of a dead giveaway: LinkedOut is a parody of LinkedIn, built as a retro-style fakeOS. The goal is simple: fill out a character sheet depicting your background, and try to successfully get a job before your savings run out.
There are a couple of elements here that make LinkedOut fairly unique among my projects. Let's dig in.
FakeOS
I've been obsessed with the concept of fakeOS'es since the advent of Flash-based Windows parodies on Newgrounds. To me, the idea of building something with just-enough functionality has always felt fun and novel, and struck me as an interesting way to tell a story.
LinkedOut's fakeOS is extremely bare-bones, and borrows visual cues from Unix's Common Desktop Environment, GEM, and aspects of Mac OSX. It's ugly and low-resolution, and reminiscent of DOS frontends from the early 90's.
Launcher
The launcher is incredibly basic. All it actually does is open separate manually-made GUIs made in the game editor.

Window Management
One really interesting thing that I managed to hack together was a basic windowing system. You can drag windows around, and clicking on a given window will make it cover other windows. There's a basic check to see if a GUI is already open, which will simply bring the corresponding window to the top of the stack.
It's a little bit of a hack, in that I'm using a "draggable GUI" module to accomplish this. I haven't made time for a proper refactor, because the script's API is a bit tricky to master. For now, windows are hooked automatically, which requires hotfixes to behave the way I want. In the future, I hope to ditch the automatic method and instead use the API more extensively.
Notifications
A lot of my projects make use of some kind of notification system. These largely exist to give context clues to the player, particularly in communicating events and states.
In LinkedOut, notifications use a very simple method, with a generic API that various events can hook into.
popUp(Info, "Welcome!", "Welcome to fakeOS!");
This basically slides a small window onto the screen, with a corresponding graphic and messages. In the future, I might distinguish between Windows-style error messages, and small bubble notifications in the corner of the screen.
RPG Elements
Despite giving the visual and functional appearance of a boring piece of business software, LinkedOut is actually an RPG with game mechanics and what I call a "stats-rolling system". The main inspiration here is to generate events and outcomes that are affected by a wide range of potential inputs.
Character Sheet
The character sheet determines player stats in the form of a resume profile. Based on what options are chosen, these stats generate an overall resume, with various weights affecting how the process works.
My idea here is that I wanted to highlight all the different ways recruiters can be negatively biased, mainly factoring education, race, gender, and prior work history. All of these values get saved as variables with related values, which individual job interviews can look at and make judgements about.
Fun note here: As it stands today, Adventure Game Studio has no inherent notion of drop-down dialogs or text-entry buttons. These are basically hacked together by drawing buttons or listboxes directly on top of specific areas when a particular button is clicked. Given that each button can be given a dedicated custom function, you can basically re-use the same ListBox element to populate pre-determined values into a list, then set a variable when one is clicked.
User Profiles
After all your stats are generated, the fakeOS opens up. Any time you try to quit the game or log out, a save file gets created, and that gets represented on the login page as your user profile.
Building the save system this way gives the impression of user progression, while also immersing basic game functions into the simulation itself. You can always start a new profile as someone else, with different stats, but the game will always treat individual accounts as different people.
There's currently a bug with the restore function that I still need to fix, to ensure that the current time gets accounted for when saving or loading. It's honestly probably not that complicated to fix.
Budget / Time Queue
LinkedOut features a time cycle that factors in a rough calendar. In-game time factors in a variety of expenses: monthly subscriptions, daily purchases, bills, emergencies, and occasionally lucky breaks.
The goal here is to provide a stronger incentive for the player to get a job. If you run out of money and can't find work in time, it's game over. Additionally, the further you get on the calendar, the more desperate you become, and the job listings dwindle in overall quality more and more.
Job Dispatch System
One of the key design decisions I made when building this is that you shouldn't see all possible job offers at once. Instead, new offers get added over time from different companies, and they all target different capabilities and requirements.
You can absolutely apply for jobs that you're either overqualified or underqualified for, but the gist is that you'll always have options.
A big idea here is that as time goes on, and you face more rejections, the quality of the job leads become less and less desirable. I really like the idea that a couple months could progress in-game, and the player is effectively left to pick between fast food positions and call center jobs.
Interviews
The interview system as it stands today is pretty weak, and needs a heavy refactor. The main challenge from a design perspective is that every interview needs to be somewhat unique, and account for the player's stats and profile.
Because of the way the dialogue system works in Adventure Game Studio, the interview system relies heavily on nested conditional statements to determine what the interviewer says. I'm not really happy with this approach, because it effectively means that every line of dialogue needs to consider 8 or 9 different stats to set the situation. These also determine what available answers the player can provide.
Here's an example of a basic education check:
// Dialog script file
@S // Dialog startup entry point
cJon.Say("Welcome to Axiom, %s %s! I'm Jon, I'll be your interviewer today.", playerpn, playerln);
cJon.Say("Let's see here...");
Wait(40);
if (edu_max <= 3) {
cJon.Say("Oh dear, it seems that you've never completed college.");
cJon.Say("I'm not sure how you've managed to squeeze through the interview filter.");
cJon.Say("I'm afraid that we're going to have to reject you outright.");
StopDialog();
exitInterview();
}
else if (edu_max > 3) {
cJon.Say("I see that you have %s listed on your Resume...", playeredu);
}
return
And here's what it looks like to try doing checks on a variety of dialogue options:
// Dialog script file
@S // Dialog startup entry point
cJon: Welcome! I see you're here for your first interview. How exciting.
cJon: I have your resume in front of me, why don't you tell me a little about yourself?
cJon: First off, why do you want this job?
return
@1 // "I like money!"
cJon: I see...
cJon: What appeals to you about the position?
option-off 1
option-off 2
option-off 3
option-on 4
option-on 5
option-on 6
return
@2 // "I like a good challenge!"
cJon: Well, this is just for a data entry position, so there shouldn't be much of a challenge in the short term...
cJon: What appeals to you about the position?
option-off 1
option-off 2
option-off 3
option-on 4
option-on 5
option-on 6
return
@3 // "I want to grow my career!"
cJon: Well, this is an entry-level position, but there's opportunities to grow with the company, if you end up being a good fit.
cJon: What appeals to you about the position?
option-off 1
option-off 2
option-off 3
option-on 4
option-on 5
option-on 6
return
@4 // "This job makes good money."
cJon: Well, it's an entry-level position...
cJon: Honestly, I wouldn't focus on the money too much.
return
@5 // "I greatly admire the company's mission statement."
cJon: "Serving the World, One Plate at a Time."
cJon: Yes, it is an impressive statement.
cJon: We work hard here to uphold our company values.
return
@6 // "I think my skills can help grow the company."
cJon: You think so? What skills do you bring to the table?
return
There's too much complexity in this method, and it doesn't scale well to potentially thousands of option permutations.
Why did development stall?
I still think LinkedOut has some really awesome ideas, but there's a tremendous amount of complexity that makes it hard to develop further. Here are a couple of pain points.
Many Variables, Few Interfaces
When I say "interfaces", I don't mean GUIs for the game. Instead, I specifically mean the mechanisms in which the game handles and parses data.
One aspect of this relates to how Adventure Game Studio handles characters and dialogue trees. Do I want to make a unique dialogue tree for every interview, and a unique character for every interviewer?
Any developer would rightly point out that this approach isn't sustainable, especially when there are potentially dozens of interviews with a wide array of potential outcomes. Sure, you could nest a lot of conditional statements into the game logic, but that can be terribly inefficient when you're juggling so many variables and objects.
Static Assets Are a Time Sink
When I started development, I immediately ran into a problem: I wanted to have a variety of different characters that you can talk to, who all look and act differently. Building on the previous problem, I found myself struggling to design different sprites and expressions for a growing cast of characters. If you can have 100 different interviews, this is a problem.
Dynamic Graphics Are Hard
My tool of choice, Adventure Game Studio, is notoriously limited in what it offers to developers. These limitations are often a boon, though, as they force me to be creative in working around the engine capabilities, and what's offered out of the box by default. I've been able to develop quest systems, character reputation mechanics, a unique dialog system, and even a transit map with a bus.
One way to work around graphical limitations is to have the game engine draw certain things for you programmatically. This can be useful if you're designing a UI for scrolling chat bubbles, or an armor equipment system where various parts of a character sprite change. This is all thanks to the DynamicSprite and DrawingSurface systems in AGS.
Unfortunately, these particular APIs are remarkably obtuse, and difficult to master.
How to Move Forward?
The main thing to understand is that the relative complexity of how this code works today is what bogs down development the most. I have some ideas on how to do this, but it's tricky.
Increase Statistical Randomness
One thing that I think could greatly help replayability is to add a "randomness" weight that can affect any potential interaction. Job Interviews boil down to so many little factors, some of which are virtually invisible and have more to do with bias, posture, body presentation, and a whole world of external factors like how someone woke up in the morning.
I think one aspect that could greatly improve this loop is to effectively copy the "Chance" card from Monopoly. At regular intervals, introduce some kind of positive or negative boon that can alter various stats. Maybe you didn't sleep well, and your ability to communicate is diminished. Maybe you've had 10 bad interviews, and have a lot of anxiety. Maybe you caught up with a friend, and your spirits are heightened. There's a lot of different little bits to introduce that could temporarily alter the loop.
Re-Use Assets for Faces
Given the inherent DOS-inspired style for the game's design, it may be a good idea to take a page out of an old DOS game designer playbook: instead of trying to draw one person at a time, create an assembly line of sorts to construct people out of a bunch of compatible assets.
By making faces and features all compatible with one another, you could just have the game randomly mix and match parts for every interview, and have that collection of parts pretend to be a character.
Aggregate Scores vs Attributes
Right now, the player profile resorts to a series of variable strings to denote stats. I don't actually think this is bad, but trying to build logic on variables alone is a headache.
One way around this may be to relate profile fields to numerical values that add up to a given score. If someone is pursuing software engineering, lacks an education, but has a body of work, that should score differently than someone who has no education or experience at all. Instead of deriving values straight from the character sheet, an aggregate score
Bias Thresholds
No job interview is without bias. Whether it's related to background, education, race, gender, or economic bracket, every job interview incorporates these in different ways, based on both the interviewer and the workplace.
One way that I might make things easier for myself is to set "Bias Thresholds", which would basically be weights assigned to the interviewer based on profile fields. These would act separately than aggregate scores, in the sense that they would more represent whatever attributes the interviewer is implicitly looking for, and could be easily tied into job listings.
Consider a Rewrite
Look, I love Adventure Game Studio. It's been my tool of choice for damn near 20 years now. But, there are serious limitations within the engine, and that makes approaching some of my ideas much harder than if I used a more modern engine. It may simply be the wrong tool for the job.
One passing thought I've had is to consider writing an entirely new prototype in Godot. It would take some time to learn, and I would have to translate a lot of my existing ideas to Godot's node-based system, but it might offer much greater flexibility towards what I'm trying to do.
In Conclusion
This has largely just been a writing prompt to showcase some aspects of my game design process and various experiments. I have a lot of goofy ideas, and gamedev has been a big hobby of mine for a long time. In accordance with a new year, I want to spend more time focusing on this hobby again. I would love to take another stab at LinkedOut, because I genuinely think it's a funny idea and worth building.