SakeTami
courseoftemptation
courseoftemptation

patreon


Course of Temptation Dev Diary #93

Hello friends! We are currently on v0.7.1g after some bugfixes following last week's update. Barring anything unexpected, that's probably it until the October update.

But now it is time... to discuss the next major update.

So there's no confusion, especially for new supporters, when I say "major update" I mean a roadmap update which will take some time to complete. We'll see several smaller monthly updates before the update we're discussing today will be delivered.

Last week, I picked five possibilities from the roadmap and laid them out in a poll, and they've now had almost a week to percolate. Adding votes from both platforms together, we have:

Consequences with 92 votes...
Crime and punishment with 163 votes...
Pregnancy with 260 votes...
Year advancement with 265 votes...
And finally... background NPC simulation with 275 votes.

I classify these into basically two categories: crime and punishment and consequences (in fact, these have so much overlap they will likely end up combined into one update someday), and simulation stuff, in that the latter three options all involve major life events that happen over time. With that framing, these results make it pretty clear that most of you would like to see the game's simulation extended, with an emphasis on enhancing the handling of NPCs.

What this means is I'll build a framework for simulating events and changes over time, whether they involve an NPC or PC or both, and thereby lay some groundwork for the top three items. As close as it is, though, some item has to win, and background NPC simulation has the most votes, so that will be the top priority. I'm planning to make at least some progress on the other top three items, though whether they'll actually get done in this update remains to be seen — as always, it's a balance between doing everything I'd like to do and delivering the update in reasonable amount of time.

I've spent this week planning, tinkering, and starting to write some baseline code. One thing I'll need to tackle in this update is also a common request when it comes to enhancing the simulation aspect: NPC-to-NPC relationships. This is a bit complicated, especially for a browser game!

Programmer talk

Our first concern is a very practical one: there's save size to consider. Local storage for a browser game is generally limited to 5-10mb, which isn't very much! With IndexedDB, those limits aren't so much of a worry, but not every device can use IndexedDB, so we have to accommodate that.

If you have any experience with databases, you know what a primary key is: a unique identifier attached to a set of data. Many of the game's data structures have a similar setup, including our NPC info: their primary key is the NPC's name. Now, storing strings like names is expensive. It'd be cheaper to use a unique integer as the identifier, but we didn't do that.

Why not? Well, when we're storing 600-2000 NPCs, whether we use strings or integers doesn't actually make so much of a difference, not enough that I wanted to sacrifice readability. That calculus changes when we're talking about potentially storing how every NPC relates to every other NPC — the savings of integer vs. string is more significant when multiplied by 4 million.

So, if we want to use integers, step one is a lookup table. We want to be able to relate a name string to a unique integer identifier and vice versa. The lookup table itself will add to save size, but we'll make that up in later savings. We'll also have a little lookup table for types of relationships so we can use integers to identify those too.

Further, we'll define relationships as two-way. If NPC A is friends with NPC B, then NPC B is also friends with NPC A. But we don't need to store it this way. We can just store how NPC A relates to NPC B, or how NPC B relates to NPC A, but not both. Then whenever we're looking up how two NPCs relate to each other, we'll check NPC A first, and if they don't record that information, we'll check NPC B for it. This immediately halves our data storage needs.

Using these methods, we can look at our worst case: ~2000 NPCs who each have a defined relationship to every other NPC. This results in a save file around 2,000kb... a 10x increase! This is technically within our limits, and saves would generally be smaller than our worst case, but even so, it'd be much better to cut this down some more.

So, let's employ a couple more tricks:

Relevance: There are a lot of NPCs that the player doesn't care that much about or hasn't even met yet, so we don't need to simulate them all the time — at least not in such a way that they record information that contributes to save size. After all, if you've just met an NPC, there isn't really any perceivable difference whether they've been friends with another NPC since the beginning of the game or whether the simulation made them friends yesterday. Which brings us to...

Procedural generation: We can decide algorithmically whether it makes sense for two NPCs to be friends or rivals, and rather than storing this in the save file, we can just process this algorithm and get the result whenever it's relevant. Then, storing a relationship in the save data is only necessary when it would override what the algorithm would determine.

Using these tricks, save size will be quite a lot smaller than our worst case. It will tend to gradually increase throughout a game, and we may need to do more to address it, but unless the player favorites literally every NPC in the game, we should avoid the worst.

What it will actually look like

A background simulation is neat and all, but it isn't of any use unless some aspects of it also end up in the foreground! So, how will we do this?

My current idea is that simulated events will be baked once per day and then roughly scheduled to happen sometime in the following day. (This is basically how relationship changes work already). Rather than being scheduled for a specific time, we can say they're queued for one of the day's time periods: morning, afternoon, evening, or night.

If the player is in the right place at the right time for a queued simulation event, they can witness something that represents the change taking place. For example, if two people you know are destined to become rivals, maybe you witness the argument in the park that sets this off.

If the player doesn't witness a fitting event in this time slot, or if it's something that wouldn't make much sense to be witnessed in the first place, then we need another way to surface it. The logical choice here would be... Elkbook! This update is a good time for Elkbook to get a bit of a facelift and a lot of extending to give you a good idea of what's happening around campus and around town.

Things I intend to simulate include relationship changes (as we've already discussed), inclination changes (particularly as encouraged by the player), skill changes, adding and removing NPCs (this will help us with year advancement), and various other important life changes that involve timed events or situations that progress (which also helps us with year advancement as well as pregnancy). As with everything in the game, our goal is to use these things to drive the player toward erotic scenes, and to give those scenes more context. And it'll also improve the game as a life sim.

Anyway, that was a long one! Sorry if it was overly rambling. Like I said, I'm in the planning and tinkering stages and still figuring out how all this stuff will actually work, and I've also made a start on the baseline simulation code. Next week, my goal is to make some simulated events actually work along with surfacing them in both witnessed events and Elkbook updates.

But until then... I hope you have a good weekend, and thanks so much for your support! Your help really does mean a lot, and it makes this project possible. Until next time!

Comments

Dang I was really excited for year advancement or pregnancy but at least this will make those other two future expansions more fleshed out and interesting. Good luck this one sounds pretty tricky and tedious but can't wait to see it come to life!

ѕℓєєρу кιиg

Definitely something I'm concerned about, but the worst case scenario outlined here really is the worst case, and I don't intend to have anywhere near that dense a matrix in practice. It helps too that the game isn't adding new NPCs — besides a few being added when year advancement is in, it'll be a pretty static number.

Anarchothaumaturgist

Dwarf fortress starts to slow down pretty bad after a certain number of dwarves. Are you seeing any issues coming up with this kind of O(n!) analysis yet?

Zqui

It could be done, but the limit is less about a single file's size and more about the size of all of them combined, so separate files don't help that much, unfortunately.

Anarchothaumaturgist

Sounds great! I gotta admire you tackling it! As for save game size... I am sure you have considered it, but still feel obligated to mention it (as you remember, I am a bit OCD that way): Have you thought about saving different (but linked) files for each 'save game'? Say one for the MC and one for the NPCs? If it is a code limitation, you could 'cheat' a bit and have NPC data saved at 'significant' events occurring while MC data is saved as it is now or something similar. just a thought

William Urquhart

I'm excited for the NPC sim but man I can't believe how close the poll was. Only beating out preg by 15 votes is pretty insane to me.

jones_Reaper_1


More Creators