Oscillation

The universe is filled with things that oscillate.

The earth rotates – we have the shift from day to night and back again.

The moon orbits the earth, causing the rise and fall of tides.

The earth orbits the sun. We experience the recurrence of the seasons.

Light and sound have frequencies.

Electromagnetic waves have frequencies.

The device you’re using now to read this (assuming it’s being viewed electronically) has a tiny crystal inside that generates a train of impulses: on / off / on /off. Those impulses drive the rest of the system.

String theory postulates that the universe itself is composed of tiny strings, vibrating, oscillating.

We breathe in and out.

Our hearts beat.

The fundamental operations of our cells may have a feedback oscillation component to them that drives the chemical reactions.

Even the human brain has a frequency, a frequency that changes depending on what we’re doing, slowing when we’re asleep or meditative, faster when we’re deep in thought or otherwise using our gray matter in an active way.

The last one is of particular interest to me. When you look at neural nets in computing, they’re often, at least initially, set up as a sort of function: data comes in, data goes out. You train the network to respond to the inputs, and then you feed it input and see what is gives you for output. For example, a neural net could be trained for the identification of letters in an optical character recognition (OCR) application, where the “read” letter is output based on images presented as input.

But the human brain is more than that.

Part of what makes the human brain incredible is its massive size, in terms of connections. Depending on where you read, the estimates are 100 trillion up to 1000 trillion connections. What is equally critical for me is the fact the it’s not just a one-way network. The human brain is interconnected. It not only receives stimulation from the outside world; it also stimulates itself, continuously. It feeds back. It influences itself. It oscillates.

You see images play before your eyes. You hear that damn song in your head that won’t go away. (“But it’s my head!”) You relive scenes both pleasurable and horrific. You dwell on things that affect your emotional state, even though, for that moment, the stimulus is your own mind.

What does that have to do with IF? Perhaps nothing. But it is an interesting topic for me, and there is a higher level sort of recurrence that might be applicable, which is the recurrence of thoughts and feelings in our mental spaces. You can see an example of this in an earlier blog about associations.

ResponsIF‘s “fuzzy” design with weighted topics, decaying topics, and responses keyed off of those topics seemed to lend itself to experimentation with oscillation.

The first attempt, which was not topic based, was a miserable failure. I tried to simulate feedback based solely on values approaching each other. Even with layers of variables in between, the values kept achieving a steady state, where nothing changed. Not a very interesting state of affairs.

I achieved better success by having both varying state and target values which flip-flopped based on the direction it was going. Not ideal, and not really feedback as such, but it did oscillate. There are a couple of samples in the ResponsIF repository that illustrate these, one being a traffic light and one being an oscillation sample.

I ended up discovering a different approach to recurrence which may hold promise. I think of it as “ripples in the pond”.

The basic setup is to have a long-term topic associated with a lesser-weighted response. The lesser weighting places the response at a lower priority, which means it won’t trigger as long as higher priority responses can. This behavior for this response is to add in a decaying topic. That topic then triggers a response which may itself add in a decaying topic. The fact the topics decay and that their responses add in new fresh topics causes a ripple effect. Topic A triggers topic B which triggers topic C, on and on, to the level desired. Each triggering topic decays, causing its effect to lessen over time. Once the temporary topics decay sufficiently, the original, lower-priority response triggers, and the process begins all over again.

From a normal mental process point of view, this is equivalent to having long-term topics triggering transient short-term topics, with the long-term responses recurring until satisfying conditions are met. A bit like nagging reminders…

This might have simple uses, but it can also have more advanced uses if you have multiples of these all going off at once. Which responses actually get triggered depends on the state of the system: what the various response needs and weights are. This means that the internal state of an NPC can vary over time, both in terms of what has been experienced by the NPC and what its long-term goals are, as well as any short-term influences. And the NPC can influence itself.

Association

ResponsIF supports associations among topics, which is something I consider important. What does this mean? Let’s give an example from real life.

Say it’s morning, and you go out for a walk with the dog. The sky is gray, but your mind is pondering the day ahead of you. There’s a problem you’ve been assigned to solve, and it’s important that it be done soon. You walk absently, your mind exploring possibilities.

As you approach the corner shop, the sight triggers a memory – you need bread. For a moment, your thoughts of the problem at work have been displaced. You think about when you might be able to get some bread as you continue on, and soon that thought fades. Re-gathering, you return to your original pressing thought.

Waiting to cross the road, your thoughts are displaced again by the need to be aware of the traffic and the proximity to your dog. An old fashioned car cruises by, and you’re reminded of that film that you saw when you were younger, about the car that could fly.You think about the actor who was in it, and of how you used to like to watch his TV show. It was quite an old-fashioned TV show, black and white, but your parents liked to have it on in the evenings in the living room.

That living room was what you entered when you were done playing with your friends outside. You remember the cool evening air when you used to ride your bike and play ball. You remember the time you went off that insanely high jump on your bike, and that time you fell. You also remember that time you feel off your skateboard and fractured a rib.You can almost feel the pain, and how you almost couldn’t breathe.

You register that the traffic has cleared, and you head across, alert to any oncoming cars you may not have seen coming or that may be coming quickly.

Having crossed the road, you follow a path beside the grass. There are flowers growing there, and delicate purple ones remind you of – you almost can’t even bear the name, you miss the person so. Suddenly, you feel the loss all over again. You can’t help but recall images of the last time you were together, of the words spoken, of the tears shed. The heartbreak has faded to a dull ache, but it doesn’t take much to flare it up.

An elderly man approaches you along the path. He smiles and waves as he passes. He told you his name once, but it didn’t stick.

For a moment, you’re in tune with what’s going on around you. You hear birds chatting in the trees. You hear cars drifting by. You smell the remnants of last night’s rain, which you remember made the windows shake and the dog jump. It was impossible sleeping during the downpour, but it was ok, because you like the sound of rain.

The smell of fresh, hot food greets you as you approach a small shop. You remember you need bread. You’re not sure when you’ll be able to get it, because of the time pressure at work…

And you’re back to  your original thoughts.

I’m not sure if that seems familiar or not, but it certainly is for me. I find my head is an ongoing stream of thoughts, steered left and right and up and down by ongoing associations, either to other thoughts or to external stimuli.

Assuming that is how a human mind works, on some level, the obvious question is whether or not you’d actually want that going in your NPC’s “minds”. The interesting thing about what happened above is that there was no external indication of what was happening. There was no speaking or obvious signs of emotion. It was all internal. Does it make sense for NPCs to have an inner life? Traditionally, IF has been about what the character does: what it says, where it moves, whether it attacks you , etc. The invisible inner workings have taken a back seat or not been bothered with at all. After all, does the player care?

I can only say that I’m interested in giving it a try. The reason why is that the inner state influences the outer. Let’s say that someone were to approach you along your walk and attempt to engage you in conversation. The response you give might well be determined to some extent by what’s happening inside. If you’re thinking about what you have to do and how you have no time and how you don’t know what to do and how you really have to work out the problem, your response might be annoyance at any intrusion. If you are forced to respond while you’re contemplating your lost love, the response might be considerably different.

Having this sort of NPC inner turmoil (or at least ongoing inner state fluctuations) could help provide a more varied response during game play, depending on what’s happening or has happened in the past.

One thing you may have noticed in the narrative above was the continual return to thinking about the pressing long term goal. Little distractions came in, some even causing ripples that lasted a while, but eventually, when the water calmed again, the long-term goal came to the fore again. This points to several key things:

  1. Long vs short term topics. Short-term topics have a short lifespan. They are the introduction of topics into the thought stream that cause ripples or even a splash, but they have no sustaining energy. They’re fleeting, disappearing as quickly as they come, replaced by either their own descendants or simply fading away unless sustained. Long-term goals, on the other hand, are constantly there, although perhaps at a lower level.
  2. Higher and lower priorities to topics. Thoughts of work took precedence over thoughts of buying bread, ultimately. But external stimuli were able to temporarily overpower long-term thinking. Responses occurred or not depending on which topics had current weight, and those weights changed over time.
  3. The internal topic patterns oscillated or could oscillate. This is a powerful concept for me, one I’d like to explore further in a separate blog post.

Without delving too deeply into it, there are two primary mechanisms ResponsIF uses to associate topics. First, a response can trigger via multiple topics. This allows topics to be grouped in terms of the effect they have. Second, topics can trigger responses which can then add possibly different (but related) topics either back into the responder or out to other responders via suggestions. And the topics can be weighted appropriately. So, for example, the topic “family” might introduce topics for “mother”, “father”, and “Sarah” with relative strong weights, but it might also introduce the topic “farm” and “Pine Valley” with lesser, but still existent, weights. And if the discussion just prior also had weights for one of those lesser topics, it might be enough to push it up enough in priority to cause a response.

Topics are the glue that link response together. Responses tell you what happens in a riff. Topics tell you what the riff is all about.

Design Goals and Uber Philosophy

I have some fairly specific design goals I intend to explore in my IF “adventures”. Some of them can be seen in my first (and, so far, only) game spondre. That game not only gave me my first experience trying to realize these, it showed me some problems that need to be addressed. Not all of them are easily solvable. But you have to start somewhere!

If you don’t fail at least 90 percent of the time, you’re not aiming high enough. – Alan Kay

First, and not surprisingly, I want the game to be responsive. I don’t mean that just in the sense that you will get a response to your input. That goes without saying. What I mean is that the game should respond dynamically to not only what you are doing but to what you have done in the past. (Wouldn’t it be something if it could respond as well to what you might be about to do in the future?)

Now that’s not unheard of in games, even IF games, but it’s also not unheard of in IF games where, if you provide the same input, even after having advanced the game, you get the same response. To me, that just feels robotic.

Ideally, the game should respond as if it were someone there with you. This isn’t going to be Turing Test stuff, but the responses should make it feel that the game is in some form a conversation with you.

To that extent, I see a certain amount of AI involved in this, not just as far as any in-game characters are concerned but the overall game experience as well. All the text you see should have some sort of intelligence behind (with “intelligence” in quotes, of course) as much as possible and necessary.

I guess what I mean is, I want there to be a unified experience. Just as each of our brain cells is a part of a larger brain, and just as each of us in turn is part of a larger realization which is the collective activity of all of us together, all the elements of a game – rooms (if any), characters, plot, events, etc – are just parts of the combined, collective game. In other words, the game itself could be a considered a collective “non-player character”, working both with and against you to create a resulting story unique to you, using components of itself along the way.

A single “mind” instead of a disparate group of individual ones.

Hopefully, when I read this again in a month or two, it won’t seem like gibberish!

 

50-50

I’ve been learning about and experimenting a bit of late with fuzzy logic. In fact, I decided to implement a variant of it in ResponsIF. For those who don’t know, unlike in “crisp” logic where you have only two values (“true” or “false”), in fuzzy logic you have a continuum of values ranging from 0 (“false”) to 1 (“true”). A value represents a level of certainty or degree of something. For example, if you’re happy, your “happy” value might be 1. If you’re almost perfectly happy, but not quite, your “happy” value might be only 0.85. If you’re only a little bit happy, you might be down to 0.1.

Such variability comes in handy for attributes that don’t have hard edges. A person who is six feet tall would be considered tall, but how about someone only five-nine? And how about down to five-seven or five-five? As you can see, there is no clear line for “tall”, where you can say everyone above this value is tall and those below are not. There is not “you must be this tall” in life. The “tallness” attribute tapers of as height decreases. As it decreases, there is less certainty. Things become iffy. Things become fuzzy.

This blog entry came to be because I happened upon something interesting in relation to that.

In normal logic, you have certain tautologies. One of them is that “A and not A” is always false. This is so because “A” and “not A” can never both be true at the same time, and “and” requires both arguments to be true for it to be true. Similarly, “B or not B” is always true, as either “B” or “not B” will always be true, which makes the “or” true as well.

In fuzzy logic, things aren’t quite so simple.

Fuzzy logic uses “min” for “and” and “max” for “or”. That is, to compute “A and B”, you take the smaller value of “A” and “B”. To compute “A or B”, you take the larger value of “A” and “B”. These fuzzy operations happen to have the same behavior as the standard logic ones when “A” and “B” have extreme values (0 or 1). Check out the numerous truth tables on the web if you’re unsure.

In between the extremes, things aren’t so clear.

I came to think about this because, in ResponsIF, a “need” was initially considered met if the final value evaluated to 0.5 or greater. I began to think about the 0.5 case. Should 0.5 be considered met or not?

First, it occurred to me that “A and not A” when A is 0.5 evaluates to 0.5 So that means that an expression like that would actually satisfy the need at 0.5. That seemed wrong to me. “A and not A” is always false! (Or should be.)

But then I thought of “A or not A” when A is 0.5, and I realized it too is 0.5. Hmm. But “A or not A” should always be a true value. Or should it?

So when A is 0.5, both “A and not A” and “A or not A” have the same middling value.

I had a choice to make: do I consider 0.5 satisfying a need or not? I was getting no help from “and” and “or”. They were both ambiguous at 0.5. And that’s what led to my final decision: 0.5 does not satisfy a need. That’s the 50-50 case, the “it could be or it couldn’t be”. It’s just shy of a preponderance of the evidence. It isn’t anything definite.

I made the change. It might seem a bit strange to someone reading this that I pondered such a small thing at all, or for any length of time, but such tiny decisions are what go into designs like this. You have to work out the minutiae. You have to make the little decisions that sometimes end up to having large ramifications.

Sometimes pondering this level of things brings unexpected thoughts: if 0.5 is on that edge between false and true, if it’s a no-mans land, perhaps it becomes a coin toss. Perhaps when evaluating a need, if it’s 0.5, then it generates a random 50-50 result, sometimes true, sometimes false. That has some interesting ramifications which I might explore someday. In particular, I began thinking perhaps it should always be evaluated that way, as a chance. Not an “above or below this limit” but a random coin toss, where the coin is weighted by the need expression result. For example, if it evaluates to 0.8, you’d have an 80% chance of the need being considered met. Similarly, 0.1 would only give you a 10% chance. The extremes would still work as expected.

I don’t know if that makes sense at all. But it is fun to think about. It did have the result of making me start to consider whether “needs” should stop being a crisp choice at all, whether the “needs” value should just be an additional weight. That goes against its original emphasis, which is that a response allows you to configure it in both crisp and fuzzy ways. But I have to have these design crises on occasion to make sure I’m doing the right thing. Sometimes “the right thing” only becomes clear after doing something else for a while.

Like having 0.5 satisfy a need. It did and now it doesn’t.

Though sometimes I wonder if I made the right choice. It could have gone either way, really…

Oh, I don’t know.