Thursday 31 October 2013

We interrupt our regular coverage for a terrifying announcement

Rogue Jack-O-Lanterns have been spotted on testIsland...


 ... and an eerie skull-like architecture is reported to have appeared in the Dreamscape - or should I say the NIGHTMARESCAPE?! [Probably not - Ed.]


Happy Halloween from the Asciilands Dev Team!

Saturday 26 October 2013

Behaviour!

This post is dedicated to behaviours. Object behaviours. Behaviours of objects within Asciilands. All objects in Asciilands have behaviours and there are many types of behaviours which do many different things. They control how objects behave when they interact with each other or when left alone or in response to some other situation.

Complex simplicity vs simple complexity

I'd like to start with a link to an article written about a game that I love and kept in mind whilst writing the behaviour code.
The game is Spelunky and the article is this.



If you couldn't be bothered reading, it basically details the way various non-player characters in the game happen to trigger a complex series of behaviours leading to a hilarious, unexpected and rich experience for the player.

This is what I love about Spelunky; the complex things that can happen from seeming simple, single-purpose enemies and in-game actors. I think the thing that makes it so satisfying is that when you play, you feel like a participant in the game world instead of the sole driving force behind the game's events. This is the feeling I wanted to emulate but it seemed utterly insurmountable. What kind of insane attention to detail was required to create all these complicated events possible? How could I hope to emulate that? As the game content grew, how much back-tracking would I have to do to make sure everything can interact in interesting ways with other objects?

The amount of work seemed mind-boggling. The amount of new interaction code would grow geometrically with the creation of new content.

Or so it would seem.

When I first started working in behaviours, I quickly discovered this strange truth: the most simple behaviours instigate the most complex interactions.

Notice this: the separation of the idea of "behaviours" and "interactions". Let's look at that article again with that in mind: The tribesman DID have simple behaviours; throw boomerang, seek boomerang, pick up boomerang, find player. The shop-keeper only has to ensure "his" objects don't leave the boundaries of his shop before turning on the rage behaviour and the player only has to trigger one of those.

It then becomes apparent that simple behaviours are a requirement of complex interactions.
Consider this: The tribesman has a simple behaviour that makes his seek and pick up a boomerang. If his behaviour was a little more complex, if he had to pick up his boomerang, suddenly this scenario can't happen. Similarly, if the shop-keeper waited for the player to remove his items from his shop, it couldn't have happened. Simple behaviours are easier to trigger allowing "accidents" to happen. Importantly, they can happen without the player's intention or instigation.

Once I figured that out, the future seemed much brighter. Rather than coding complex behaviours, I only had to focus on two things:

  • Keep the behaviours simple
  • Don't give the player special status when it comes to behaviour execution
I haven't mentioned that second point so I'll give a quick Asciilands example and then get into the methods used to create the behaviours.
When play testing, I created a bunch of NPCs to walk around and a bunch of items to collect. Since I wanted to follow the second rule, the NPCs could pick up the items just the same as the character. They have an inventory using all the same code as the player. In fact, they share most of their code except that the player is controlled by a human and the NPCs speak to you when you bump into them.

Anyway, I was getting tired of them picking up the items that I wanted to test so I wrote another behaviour and attached it to the NPC that causes them to surrender a random item in their inventory when you bump into them.

Thanks, Flinos!

That out to make testing the items easier...however, strangely it only seemed to be working some of the time. I put a bit of debug tracing code in the giving-item behaviour and found that this was because I was following the second rule without knowing and the items were being passed from NPC to NPC as they fumbled about with their random-number based wandering.

I left the trace code in so I could find the items I was after but this accident made me very happy! The obvious next step is to add a behaviour called say, "psycho" which causes an NPC to attack others if they happen to come into contact with a weapon. This would mean that once in a blue moon, an item would get handed around and find its way into the inventory of the wrong guy and a new kind of enemy would emerge creating a new experience for the player. Who knows, as behaviours evolve and guard NPCs emerge who react to nearby attacks start being implemented, fights could begin and end without the player even knowing.

The possibilities are endless but not because the behaviours are complex but because the interactions between simple behavious become complex if the scope for their triggering is left broad enough!

The best method to create madness

Writing object code: easy. Writing behaviour code: easy. Attaching behaviour code to object code: hmm.
The most difficult thing about making the object code work with the behaviour code was that I never thought it was difficult. This caused me to write it:
  • Strangely
  • Poorly 
  • In ways difficult / annoying / tedious to implement repeatedly
  • All of the above
In this section, I'll run through the methods used (including the one I wrote that other post about explaining collisions) and explain what did and didn't work.

Attempt 1: Traits!

For those who know PHP: I wrote each of the behaviours inside a trait.
For those who know code but not PHP: traits are sort of like interfaces but you actually implement what's inside them. It's to prevent needing to rewrite common code for different objects.
For those who don't know code or PHP: this was silly.

I like diagrams so I'm going to explain this using diagrams.
Here we have an object and a behaviour:


Since the object is a trait, when we combine them, they become attached rather like this:


How nice. Programatically they're now one entity and can be coded as such. The behaviour code and the object code are all coming from the same object. Wait, this is too abstract. This object is a person and he is...walking.


So what's good about this arrangement? Well the person's code can say "I am a person and a person can walk so I'm going to walk" and the person will walk. Simple. The walking code says "I'm going to move my person to the next square because that's what walking is!". Brilliant, look at those little guys walking around down there! Hey! Let's make them talk! Ding!


We now have walking, talking people. They know how to walk and they know how to talk because they were literally made to do it. How does this interaction look inside the object? Sort of like this:


So the Person tells its walking and talking behaviours what to do and how to do them and they do them (rather like your brain telling your legs to walk and your moth to speak).
The way the behaviours get attached rather than actually being part of the object is important for creating different objects with common behaviours.
We might have an NPC who can talk but not move. We might have an animal who can walk but not talk. We might give an attack behaviour to the animal instead. We might replace the walking behaviour with a chase behaviour etc.
It's modular and it works nicely to maximise difference in objects just be creating combinations of behaviours.

What's the problem with this then? Notice how the person prompts the behaviour to start and the behaviour then carries out its purpose with person? Well what if we did make that non-moving person. We'd have a situation that looks like this:


Not cool. The person still wants to move because that's part of what makes the person code part of the person code. Sure, the obvious way around this is to simply perform a check to see if the person has this ability or to turn it off and on but then we're losing that simplicity AND we're losing the portability. We have to code all those checks into every object that may or may not have whatever behaviour.

To further complicate the problem, suppose we wanted the NPC to stand still while we talk to them. Now the behaviours have to be aware of each other and make similar check both against the object they're attached to AND the other behaviours attached to that object. What should be done about that? Some kind of behaviour register array? A bunch of booleans? Eh, messy. No thankyou.

So what did we learn about traits and trait-based behaviour code?

The good:
  • Modular
  • Linked directly to the host object
The bad:
  • Not very good at being aware of each other
  • Linked directly to the object
  • Can't add or remove behaviours on the fly, can only activate or deactivate.
  • Messy
The ugly:
  • The only way to sort out the problems of linking behaviours to other behaviours that may or may not exist is to have all the combinations accounted for and checks made to see what we have to work with. This defeats the purpose of the entire system.
Ok, let's try something else.

Attempt 2: Objects!

What if behaviours were now objects in their own right? We'd have this:


Ok, now let's get our talking, walking person back in this new form...

Right. What are the main advantages of this? Firstly, since the behaviours are independent to the object itself, they can have self-awareness. This wasn't possible with traits since walking doesn't have a "self" independent of the person.
This probably makes more sense to those of you who are developers but it's very important.
What's in these behaviour objects? This is what the behaviours "know":


Now let's see what happens when the behaviours are made to activate!:


Again, I'm not sure how easy this is to make sense of for people with no development experience but this is one of the more technical posts.
The key difference here is that the object doesn't tell the behaviours what to do like it does with the traits. All it does is till the behaviours what's going on and the behaviours activate when the call is relevant to them.

This prevents that problem that we ran into when our person wanted to walk without the walking behaviour. With this new system, the person just says "I'm idle, what should I do?" and if he has walking behaviour, the walking behaviour will kick in and say "walk!", otherwise nothing will happen. That's better! It also means that we can add and remove behaviours without having to write extra code in the person to handle all the new things it can do. As long as the person knows when to make announcements and the behaviours know which announcements to listen for, everything will go smoothly.

Out non-walking man might suddenly need a "flee" behaviour because we attacked him or something. With this new model, instead of needing the flee behaviour all along and having to turn it on when we attack him, we GIVE him the flee behaviour and it activates by itself. The person doesn't need to know why or how because the behaviour is in control and doesn't need his help.

Hold on though, what happens if we have a walking person who then gets a flee behaviour? Won't they walk half-randomly and half quickly-away as the behaviours compete?

Well they would, yes...but there's a simple solution for that: every behaviour knows its "type" and each object can only have one of each type behavior. Since walking and fleeing are both movement types, the fleeing will REPLACE the walking.

I'll explain diagrammatically:
If we have a person who can walk and we want to add the ability to talk, no problem. We can just add that behaviour since they don't conflict:


The complication is introduced when we want to add another kind of movement since they are not compatible. They will conflict. It's important to note that having multiple behaviours respond to the same event is not a problem, it's necessary. The problem is only if the behaviours are clearly in conflict (like two kinds of movement or different speech behaviours or multiple attack types).
Anyway, we can't be wandering and fleeing:


A check is made and if it is found that that behaviour type "slot" has been filled, a replace needs to happen.


We now have our talking fleeing object!
Those with a keen eye may have noticed another problem that existed with trait behaviours that has not yet been resolved: behaviours not being able to talk to each other.
The behaviour type slot is also the solution to that problem and solves it in a way that helps uphold an extension of that old second rule: don't give anything more special status than it needs in order to function correctly.
A behaviour doesn't need to talk to another behaviour, it only needs to talk to another behaviour type.
For example, when talking to an NPC, they stop moving. This can be achieved by having the talking behaviour tell the movement behaviour (walking or fleeing depending on what is in the moment slot at the time) to pause for a short time.

This killed two birds with one stone and I hadn't even seen the second bird coming!

Ok, so what did we learn about object behaviours?:

The good:
  • More modular
  • Cleaner to work with
  • More independent
The bad:
  • So far they're working fine but I thought that about traits, too, for a while
The ugly:
  • Once the event triggers and listeners are understood, it isn't too ugly but it can seem rather tangled when it isn't fully understood
Object based behaviours it is! They have yet to let me down and they're very versatile for use with all sorts of objects and items with all different kind of event triggers and behaviour types.

Thanks for reading!

EDIT: One more thing! The editor from the last post has been the main focus of my recent efforts and it's more or less finished now. Below is a screen-shot of about half and hour's work. Oh, the efficiency!


I'm curious to know whether or not the 3D form of the castle is apparent or if it kinda take a while to "get your eye in" to be able to see what's being attempted using the tiles.

Let me know!

Thursday 17 October 2013

Editor!

Today I am pleased to announce an early alpha of the Asciilands editor! It allows much easier creation and editing of the maps and shows how it will look in real time.
Creation of good dev-tools was always part of the plan with Asciilands and so far, this feels like the most triumphant example.

Enough talk, you probably want to see it. Maybe. Here it is!


You can't christen a map editor with anything other than some horrible in-game text so that's exactly what I did.

The interface is fairly self-explanatory; choose from the world tiles on the left and the scenery objects on the right and add them to where the cross-hair is.

Editing text files like we've always done is fine but there are distinct advantages to this kind of interface:

  • It's much faster to make a change.
  • It can be transitioned to instantly from test play.
    • This means, for example, that play testers could not only tell us about map annoyances or oddities but they can immediately cross over and change it to what they might have expected.
  • It's prettier and nicer and doesn't suffer from the distortion that non-square characters impose on text-based maps.
  • My eyes will hurt way less when I'm trying to do the dual-tone walls of cave interiors, trying to distinguish between lower-case and capital Ws in huge blocks.
Other development developments are as follows:
  • New behavior system complete and original behaviors transitioned to new system
    • I will be doing a blog comparing and discussing the two systems soon.
  • Added a few extra features and areas to testIsland to test new improvements (e.g. BluffCave now has a second, deeper, and much larger area to test the various way to enhance in-game visibility).

Development continues!
As ever, anyone interested in testing Asciilands (or the new editor) remotely in invited to let me know!

Behaviour system blog will be coming soon.