A few design lessons I've learned along the way

Thank you so much for this informative and educational response! I truly had no idea what was going on “under the hood”, so to speak, so your explanation cleared that up wonderfully.

I do have to ask, however, why or how literally every other app on my computer manages to handle decimals without incident. Is there something Excel is doing that CS cannot do?

That’s a good question. It’s not necessarily “cannot do” but programming languages generally leave it up to the user to round things off to what they want rather than imposing a one-size-fits-all solution that may not be what you want in a few weird cases? And I’d guess that CS, not being designed for a lot of numeric computing, probably expects people to mostly use integers and Fairmath stats and the like so they didn’t have a need for a solution to this?

I don’t know what Excel does, they’re probably just rounding it off to some small precision that usually works but doesn’t visibly lose accuracy that you care about? Like physical electronic calculators will calculate to more digits than they show on the screen, so it’s still happening, but then when they round it off to display it usually hides the error. If you know what you’re doing it’s pretty easy to find calculations that show it up.

Hmm, yeah, check out this article from Microsoft: sounds like they’re just rounding it off.

Edit: and now I’m probably getting way too far off in the weeds, but the problem with rounding is that computers store numbers basically in scientific notation: a string of digits and then an exponent that says where to place the decimal point. So they can represent very large numbers (hundreds of zeroes at the end) or very small numbers (0.0000…x - hundreds of zeroes at the start) but not both at the same time. And you want to round off at wherever the end of your string of digits lands, not just to some fixed tolerance. So it gets tricky.

6 Likes

enter rabbithole

What you see in the cell of an Excel spreadsheet is a number which is formatted a particular way (as a whole number, or currency, or a date). That hides to some degree the kind of behaviour Josh described.

3 Likes

Lesson #12: Achievements

As we’ve already seen with the Stat Screen (Lesson #9), CS comes with a built-in separate screen that works in parallel to the “main” play screen.

Similarly, the Achievements screen gives the author a chance to add more game elements to the player’s experience.

Unlike the Stat Screen, however, the author has to “enable” Achievements in order to make the button appear at the top of the player’s screen. The way to do that is to include at least one *achievement line of code in your startup.txt file.

Sadly, CS’s Achievement screen is completely non-adaptive, which is more than a little weird when you think about it. If there is just one achievement available, the Achievement screen will still refer to them in the plural, and it will always pluralize the number of hidden achievements, even if there are none.

There is, quite literally, nothing you can do to change this.

:crying_cat_face:

Achievements as Feedback

Unfortunately, the design principles for using the Achievement page are more than a little muddled:

The *achievement command is used to define one or more Achievements able to be awarded to a player for noteworthy feats or accomplishments within the game…

…[or] just about anything in your game entirely deserving of a hearty pat on the back.

My recommendation is to forget about giving your player a “pat on the back” as if you are their coach and focus on basic design principles, i.e. to use the Achievements page as a way to enhance and amplify the game elements of the IF experience.

To wit, Achievements should be awarded that give the player feedback on how well they are (or are not!) controlling (directing) their gameplay.

For example, in a simple game of Rock-Paper-Scissors (R-P-S), what Achievements would be useful?

  • :trophy: Winning one round
  • :trophy: Losing one round
  • :trophy: Winning three rounds in a row

Certainly, awarding an achievement for both winning one round and winning three rounds in a row are a type of “pat on the back” for the player, but why also include an Achievement for losing a round? That’s nothing to celebrate, is it?

Of course, not. The Achievement for losing a round isn’t to chastise or criticize the player but to give him/her critical feedback about their performance, i.e. that they aren’t doing things correctly in order to win the game of R-P-S.

Simply put, Achievements are signposts to the player, saying either “You’re on track” or “You’re off-track” in accomplishing their in-game goals.

Use Cases

Now that we understand the purpose of Achievements, let’s delve a little more deeply into how to apply them.

  • Game performance feedback
  • Story performance feedback
  • Advertising the future
  • Identifying story paths

Using Achievements as game performance feedback is rather intuitive. You simply let the player know when they’re succeeding (moving towards a win/winning) and when they’re not (moving towards a loss/losing), just as in the example above with R-P-S.

It’s the other three categories that merit more analysis.

However, it should not be forgotten that Achievements are all assigned a point value (from 1-100) by the author, so the player achieving the various Achievements as they progress through the story becomes, in effect, a minigame called “Get as high a score as possible.” :joystick:

Story Performance

Most CS (and, indeed, most choice-based IF) game-stories are primarily stories with only a thin veneer of (pure) gaming elements. Therefore, the story is the central focus of the player’s experience.

As such, Achievements can be used to give the player feedback on their progression through a narrative arc (story) and, by doing so, add (at least the perception of) ludic weight to the player’s choices.

Achievements can then be rewarded for:

  • Player inputs (such as name, gender, etc.)
  • Beginning and finishing major story arcs
  • Doing something remarkable in furtherance of the story

For example, in a D&D style game where the player sets up their initial character (including the name, stats, race/class, etc.) via a series of choices, awarding an Achievement once that’s completed is a nice way of telling the player that their inputs were recognized and that the main story is about to begin.

Likewise, if the story-game has three parallel arcs seen from the eyes of a Thief, a Wizard, and a Fighter, then awarding an Achievement at the start of each path (i.e. "Your adventure as a Thief has begun!) is a way to reinforce the player’s decision to follow one of the major stories in your game.

If the Thief’s path then continues with a series of exercises to build up their thieving skills (lockpicking, cracking safes, etc), then awarding an Achievement at the end of that would be a great way to tell the player “You’re making progress in the Thief’s story.”

Again, these Achievements may look like they are referencing game elements, but I am referring specifically to using Achievements as feedback on the player’s progression through your story.

Maybe the Thief always successfully learns how to pick locks in your story, so there’s no real “game” involved to get to that path. The Achievement is used simply to say to the player “You’re making progress” on their path through the Thief’s story.

:crossed_flags: In addition, you can also highlight the player’s reaching of an important story “crossroads” by using Achievements.

If your story-game is about a young royal who has to decide whether to execute an innocent person or else pardon them (and thus set off a civil war where thousands die), you can award an Achievement (regardless of which path the player picked!) that simply says something like “A crucial decision is made.”

This reinforces, to the player, that their choices really matter, which adds ludic weight, a critical element in story-first design. It also lets them know that this decision point was particularly important.

Likewise, if your story falls into regular “beats” akin to chapters, you can also award an Achievement every time the player progresses to the next beat or chapter.

Again, the purpose of these Achievements is to let the player know they are making progress in your story.

Advertising the Future

All Achievements tagged visible in your startup.txt file will be listed as possible Achievements on the Achievement screen.

This gives the player the opportunity to look through them before gameplay begins and see what is (possibly!) coming up in the future.

Used incorrectly, these can be “spoilers” for your narrative arcs, but used correctly, they can help build anticipation for the player (similar to foreshadowing in standard linear narratives).

For instance, if the player sees an Achievement described as “Pull the sword Excalibur from the stone at the lake” then the player will know:

  1. Somewhere in the game-story is a sword named Excalibur, and it’s probably pretty important and/or useful.
  2. The sword Excalibur is located inside a stone.
  3. Therefore, be on the lookout for a sword in a stone somewhere near a lake.

And then, when the player does come across a lake later on, they will be on the lookout for a sword sticking out of a stone.

In other words, you’ve managed to tell the player that the lake is important without ever having to say “keep your eyes peeled for a lake.” Nice!

Likewise, if the 1977 Star Wars movie were written as choice-based IF from Luke Skywalker’s POV, you could include a visible Achievement called “Leave Tattooine”.

This would tell the player that getting off the planet is an important event in the (future) story, so pay attention to opportunities to leave Tatooine!

All without ever giving away the “twist” that the only way to get off Tattooine is aboard the Millenium Falcon with a charming rogue named Han Solo.

Identifying Story Paths

The difference between “signposting the future” and “identifying goals” is that “signposting the future” is foreshadowing what will happen while “identifying goals” is foreshadowing what could happen.

:warning: The player won’t be able to tell the difference between these two. It’s only useful to the author to know, for design purposes.

If the bulk of your story-game is about story, then the main “game” element for the player is reaching a particular story out of all the possible stories available.

For instance, if you have a story-game that includes at least one narrative arc about falling in love with an NPC, you definitely want to include a visible Achievement that identifies “In a romantic relationship.”

Seeing this as a possible Achievement will tell the player “a story about falling in love is out there, and if I make the right choices, I can get to that story.”

For design reasons, many or most of the truly divergent story paths tend to begin closer to the end of gameplay than at the beginning.

Identifying these divergent story paths with a visible Achievement, therefore, tells the player “Here are the possible endings/main stories you can get to in this story-game.”

Imagine you were writing an IF game-story about Laura Ingalls WIlder’s book The Long Winter. You could put in two visible achievements:

  • The family survives the winter
  • The family succumbs to starvation

This tells the player “I better be careful with my choices if I don’t want to read the story about the family starving to death.”

OR it could tell the player “Hmm, I think I’ll make the necessary choices to read the story about the family starving because that sounds like a more interesting story.”

Either way, it’s telling the player that there are named, available story paths out there and that there is some way to get to each one. And, therefore, a game starts being played by the player called “let’s see if I can navigate my way to that story that I want!”

Assuming that the author’s story delivers, playing that game of navigating to a desired story will make the player quite satisfied and engaged. In fact, it is exactly the same experience that the children of Edward Packer enjoyed with their father all those years ago.

Hidden Achievements

ChoiceScript lets you create hidden Achievements that are only visible on the Achievement screen after they’ve been awarded to the player.

Therefore, being awarded these Achievements always come as a complete surprise to the player, so use these sparingly.

The two main uses for hidden Achievements are:

  • Comedic or humorous purposes
  • Fringe/edge cases

Having the option to spring a pop-up box with text (a hidden Achievement) on the player could be used to great effect for humorous or comedic purposes by any author so inclined.

Hidden achievements are also good for those proverbial “pats on the back” when a player arrives at a seldom-visited narrative path or condition.

For instance, in your D&D type game-story, if the player explores every single nook and cranny of the Thief’s story (perhaps tracked by stats), you might want to award them a hidden Achievement for that accomplishment (“maxing out” the stats).

Likewise, in your blatantly illegal Star Wars game-story, if Luke decides to regale everyone with a lengthy discourse on the nutritional properties of blue milk, you could award that an Achievement in recognition of the fact that few players will ever choose to go down that route.

In other words, anything “completist” can get a hidden Achievement. And anything “rarely accomplished” can also get a hidden Achievement.

First, put up the tree, then decorate it

My recommendation is to wait until after you’ve finished with the principle work of authoring your game-story and you can look at it from a holistic perspective before you go back and add in the code for the Achievements.

:christmas_tree:

Ask yourself:

  • Are there any (pure) game elements? If so, what does the “win” condition look like, and what does the “lose” condition look like?
  • What are the main story paths?
  • Which story junctures/decision points are critical/the most important?
  • Are there any text/numerical player inputs? If so, which are most important to the story?
  • Does the player contribute anything else to the story?
  • What is the (main) ending of each story arc?
  • What major/important events happen mid-way during each story arc?
  • What major/important events happen at the beginning of each story arc?
  • What are the edge cases/conditions?

For each one of these, you should consider adding an Achievement :1st_place_medal:

3 Likes

I should add here that there is a small but very vocal minority of CS players that loathes Achievements.

If you really want to accommodate these folks, you’ve got to have a boolean flag set up at the beginning (*create wants_awards false) and then code in an extra line every time you want to award an achievement:

*if wants_awards
   *achieve achievement1

Not sure if it’s worth the effort, though, since you cannot do anything to hide the fact that Achievements exist. All of the above really does is prevent the player from getting pop-up alerts.

Lesson #14: Always Be CSIDE-ing

:surfing_man:

If you’re even so much of thinking about writing a game-story in ChoiceScript format, I highly recommend that you start by downloading CSIDE.

The link above goes to a website called GitHub that no, is not where annoying people hang out :stuck_out_tongue_winking_eye: but a place where programmers store their software so that other people can download it.

If you’re like me and not a coder, the website can be a bit intimidating. But just click on the file that matches your OS, and the rest is easy.

CSIDE comes with a built-in tutorial that will teach you everything you need to know. Honestly, until you get into some more advanced stuff, you will not need another knowledge resource than CSIDE.

The name CSIDE comes from CS for ChoiceScript (the language) and IDE is some kind of coding term that means “special app for creating something with code,” at least as far as I can tell.

Since it sounds like “seaside” when you say the name of the app out loud, their logo is a tsunami about to destroy a tropical island :ocean: :desert_island:

A few benefits of using CSIDE

I’m not going to turn this into a commercial (advert), although I could, but beyond containing a really nifty tutorial, CSIDE will help you:

  • Tell you how many words you’ve written (both code and non-code)
  • Automatically use special colors for the coding parts to help you identify/write them
  • Run tests and identify coding errors
  • Test and play your game (instantly)
  • Export a compiled version of your game

Everything you need to write, test, and debug your game is pretty much right there “in the box” with CSIDE.

Better, it runs great even on old machines like mine.

A few downsides

Really, don’t let the following critical feedback color your opinion of CSIDE - it’s an amazing program, and it’s hard to believe that it’s legally free to download and use.

But if you’re gonna get in the trenches and spend hundreds of hours crafting your game-story masterpieces, there are a few things you should know.

Note: I can only speak to the version running on my computer (1.0.0 for Mac). Other versions may be different.

  • You can only change the settings from the side panel of the CSIDE app (a gear icon), not from any menu at the top of your screen. Make sure you go through these settings carefully when you start, including the autosave settings.
  • You can choose between color schemes (excuse me, colour) schemes and light/dark mode, but you cannot customize which colors the various code types use. The Editor Theme selection has a “Custom” choice you can select, but then you cannot actually customize it :crazy_face:
  • If you have an unclosed, infinite *goto loop somewhere, and you press “play,” CSIDE will go bonkers :boom: The app will freeze up completely, and if you don’t watch out, will start burning up your entire computer’s memory as well. Often, you’ll have to restart your computer.
  • It will not play mp3s even though CS allows you to use mp3s in your game. I’m sure there’s some legal reason for this, but literally every single friggin’ time your game tries to play an mp3, CSIDE will bug you with an error message.
  • The spell check is good but not gold-plated, so don’t rely on it exclusively.
  • Probably not entirely CSIDE’s fault, but the built-in Randomtest will go cuckoo bananas :banana: if you’ve got a lot of *gosub or *gosub_scene commands in your game. Start with a small number of Iterations and then work your way upwards because a long Randomtest can end up freezing the app.
  • Speaking of random, if your code has a lot of *rand commands, the RandomText can also get a bit wonky :dizzy_face:
  • Sometimes, CSIDE will say (during Quicktest) that it cannot find a scene file that you know darn well exists and that there’s nothing wrong with it. The way to fix this is by adding the names of those “unfindable” files in the *scene_list section of your startup.txt file.

Other than that, CSIDE will let you do just about anything using the standard ChoiceScript language.

Unless you’re restricted to writing your game-story on a mobile device (CSIDE is only for desktop computers), CS authors should:

Always
Be
CSIDE-ing :call_me_hand:

2 Likes

Don’t want to be a git :wink:, but Github is where you can store source code yes, but publically available doesn’t mean public domain. Be careful when downloading someone else’s code unless they have given explicit permission. Code is considered intelectual property in most countries.


A little bit of trivia, IDE stands for integrated development environment.

2 Likes

:crying_cat_face:

Sadly, yesterday, I discovered that there is a new (rather major) error with CSIDE.

Yes, it has a one-click “compile your game” function that works flawlessly on your browser, but there’s something inside that file that makes it incompatible with itch-io now, that didn’t exist before (technical explanation at the link :point_down:)

This is now a known problem with no real good solution, despite the fact that the thread is now closed.

:warning: Now, if you want to put a CS game on itch, you have to go through an unbelievably tedious process to compile your game using the original ChoiceScript tool.

The CS compiler will create a game that runs, BUT - and this is a huge BUT - if you have any media (images, sound) in there whatsoever, the steps you have to take to include them are advanced-level coding stuff unless the *image or *sound command points to a file that’s hosted online (i.e. with a fixed http address) as opposed to accessed locally.

Indeed, I went through a ton of old threads (because everyone uses CSIDE now) on how to “format” an image to have it included in your compiled CS game, and I just could not figure it out. Being honest, here.

For those who aren’t coders, a “compiled” version of a CS game is when all your game files are compacted into a single computer file (with an .html extension) that you can store or share.

Clicking on this file will activate your browser, and then the browser will “magically” download whatever it needs to so that all your player experiences is a ready-to-play game.

1 Like

Thanks. But I honestly have no idea what an unintegrated development environment is :stuck_out_tongue_winking_eye:

1 Like

You used to always have a bunch of separate tools: an editor, a debugger, a compiler, a command prompt to run your code, etc., while an IDE tries to roll everything into a single interface.

6 Likes

Excellent bits of wisdom (or as people would call them today, “design patterns”).

Discourse is a bit of a pain to use in long threads, so if possible I would advise to collect them all in a blog or similar!