Sponsored By

GDC 2002: Social Activities: Implementing Wittgenstein

In Black & White, a number of different "group minds" were implemented(reactions, towns, dances). These activities had a lot in common, but were implemented completely separately. What was in common between them was not captured explicitly. This meant that adding a new type of activity was quite difficult and time-consuming: all the bookkeeping had to be re-implemented each time. This feature proposes a new system that captures what is common between different activities and makes it as easy as possible to add a new type. Furthermore, and more excitingly, this new system allows the mod community to add new activities after the game has been released. This is a good idea because the perceived "depth" of an AI agent is largely a function of the number of different sorts of activities he can engage in. By making it optimally easy to add new activities, we increase the total number of activities we can implement. In Black & White, the number of activities implemented was rather small. With this new system, we hope to have hundreds of different activities.

Richard Evans, Blogger

April 24, 2002

22 Min Read

This article starts with a theoretical case for what we call activity-orientated structure, arguing that activities are an important part of human life, and one that will become increasingly important in future simulations including human-like agents in believable contexts. Second, since there are so many different activities, it is important they can be added easily to the system and realized in the game world as actual (albeit non-physical) objects, rather than (say) abstractions in the minds of agents.

Implementational issues are also explored, focusing on the way activities should be added to the system. We argue that activities should be defined in a high-level language, which is compiled into C++. An example piece of activity-content, defined in this high-level language, is presented.

The Case for Activity-Orientated Structure

Why Social Activities are Important in the Simulation of Agents
Since this article is concerned almost exclusively with the notion of 'activities', it seems prudent to begin by trying to explain why we believe this concept merits such attention. In particular, we shall seek to establish successively that:

  • Social activities are part of human life, and thus are usefully 'included' (in some sense) in simulations of human-like agents.

  • Social activities are an important part of human life; thus their inclusion in simulations is correspondingly important to the believability of the simulation

  • Social activities are the most important part of human life, that which distinguishes us from mere brutes. Thus, without addressing the activity concept in our simulations, we will be limited to simulating brutes.

Social activities are part of human life - agents who do not understand them can appear dumb. This minimal claim is most easily illustrated by considering a series of examples where an agent's lack of 'understanding' of activities and their relations can be cited as a failing of that agent.

  • A chess computer. Although it is very good at chess, a chess computer is blind to the world around. It will never get bored of playing chess, and want to play something else. It does not understand, in other words, that playing chess is merely one activity amongst many, which satisfies some desires but not others. The chess computer doesn't understand the place of chess within the social flux - it doesn't understand that chess is a game played for recreation or competition.

  • A problem with Black & White. In this game, a creature may be making friends with another, when he decides to interrupt this to go toilet. What is stupid about this behaviour is that the agent had no understanding of the consequences (for the activity of making friends) of stopping in mid-conversation to relieve himself. The same problem can arise in The Sims (a very entertaining piece of software): Peter's character was chatting up a lady, but then got tired, and in the middle of his chat he went off to have a bath. (The fact that this happens in both programs shows it is a moderately deep problem, and not a consequence of one particular implementation).

  • Agents' understanding of Ownership. Nowadays, many games include agents owning objects. But this "ownership" is implemented in the simplest possible way. The following comments apply to SHRDLU, but apply directly to modern computer games. "SHRDLU cannot be said to understand the meaning of "own" in any but a sophistic sense. SHRDLU's test of whether something is owned is simply whether it is tagged "owned". There is no intensional test of ownership, hence SHRDLU knows what it owns, but doesn't understand what it is to own something. SHRDLU would understand what it meant to own a box if it could, say, test its ownership by recalling how it had gained possession of the box, or by checking its possession of a receipt in payment for it; could respond differently to requests to move a box it owned from requests to move one it didn't own; and, in general, could perform those tests and actions that are generally associated with the determination and exercise of ownership in our law and culture" [Herbert A Simon, "Artificial Intelligence Systems that Understand" (IJCAI-77, Proceedings) p.1064 [quoted in Dreyfus p.13] Agents (in current computer games) do not understand ownership because they do not understand the social activity in which ownership is embedded: ownership is a concept which belongs to the social activity of Enforcing Ownership, an activity which involves agents monitoring who owns what, and punishing others who mess with other people's things.

Social Activities add colour to our lives, lives which are otherwise coarse and materialist. From a certain perspective, our lives can seem empty. If all that there is in the world is other objects and agents, what is there for us to do except manipulate those objects and agents? All that we can want is to acquire as many objects as possible, and have as much influence over other people as possible.

This coarse and materialistic view of human nature is based on the assumption that all that exists is other objects and agents. Getting away from this dark picture involves admitting the existence of a variety of social activities. These activities elevate us because they give us new things to want. The lives of the Black and White creatures and the Sims characters are unquestionably materialistic because their desires are materialistic.


Maximally strong claim: participation in sophisticated social activities is the critical property which distinguishes people from animals. Heidegger distinguished between merely existing, as an animal exists, and full-fledged human existence. (Heidegger called this "Dasein" or "being-there", and characterised it as participation in the social flux of the world). This insight has filtered through into popular culture: a well-known mobile phone company has mooted that "life is made of one to ones". Even Swedish popsters Abba echo the sentiment - "Without a song or a dance what are we?" - in other words, it is our participation in forms of life that makes us uniquely human.

The sophisticated skills we prize about ourselves, our ability to reflect, communicate, care about others, are dependent on our ability to participate in various social activities. Social activities, rather than just being one of the many things the mind thinks about, are actually the things which make sophisticated thought possible. It is because we can participate in sophisticated social activities that we can have the sophisticated thoughts that we prize. Philosophers have given many examples of aspects of sophisticated personhood which are conditional on participating in social activities.

  • Understanding of language. Wittgenstein's language-games are examples in which someone knows what something means because he understands the activity he is in. Investigations $2: "The language is meant to serve for communication between a builder A and an assistant B. A is building with building-stones: there are blocks, pillars, slabs and beams. B has to pass the stones, and that in the order in which A needs them. For this purpose they use a language consisting of the words "block", "pillar", "slab", "beam". A calls them out; -B brings the stone which he has learnt to bring at such-and-such a call. If someone understands what "pillar" means, he does so in virtue of understanding its role in the activity in which it is embedded.

  • Compassion towards others. Wittgenstein asks "Why can a dog feel fear but not remorse? Would it be right to say "Because he can't talk"?" [Zettel $518] The reason a dog can't feel remorse is that he cannot participate in the moral community in such a way as to recognise or manifest remorse. It is because he cannot participate in this activity that he cannot enter into these feelings.

  • Feelings
    "The concept of pain is characterised by its particular function in our life. Pain has this position in our life, has these connections". [Zettel $532]
    "The concept of pain is bound up not just with characteristic pain-behaviour in circumstances of injury or illness, but also with pity and commiseration, fear and anxiety, cruelty and mercy." [B&H Vol3 p.68]

  • Structure and Organisation of Knowledge. "Heidegger pointed out that the outer horizon or background of cultural practices was the condition of the possibility of determining relevant facts and features and thus prerequisite for structuring the inner horizon" [Dreyfus 36] In other words, we must not represent facts in one big pool, but must organise them structured by which social activities they are relevant to. This is the way for agents to get efficient access to the things which are relevant in a particular situation. "The basic insight dominates these discussions that the situation is organized from the start in terms of human needs and propensities which give the facts meaning" [Dreyfus p.262]

Activities Are Varied and Must be Easily Addable
Here are a few paradigmatic examples of activities.

  • Games (with winners, and without winners)

  • Friendships

  • Romantic attachments

  • Conversations

  • Marriages

  • Households

  • Social groups (e.g. the "in crowd", "the nerds")

  • Meals

  • Parties

  • A night out; say to the cinema

  • The moral community

  • An insult

  • Saying goodbye

Notice some of these activities, like a meal, are short-lived, but others are extremely long-term: a family lasts as long as there is anyone in it. Some activities can only exist within the context of a parent activity - a Goodbye activity, for example, cannot exist on its own. These activities which must have parents are called sub-activities.

These activities group people together, and these groupings can overlap:


image002.gif

Activity groupings can overlap..


In this dramatically charged example of activity-overlap, Arthur and Belinda are married. Arthur and Charlie are friends, but Belinda and Charlie are flirting.

Since there are so many different sorts of activity, we shouldn't think in terms of "adding activities to our simulation" being a one-off operation. Rather, once our simulation has become activity-enabled, activities have become a kind of content. When building a simulation of a society of agents, there are many different levels at which we should easily be able to add new content - there is no magic formula or technique to generate plausible agents, there is just lots of different behaviour to simulate. Each bit of behaviour needs to be easily-addable; behaviour needs to be addable at lots of different levels (e.g. objects, animations, actions, and goals). If our simulations are to address activities, as we have argued they must, then activities become one of these levels. The sophistication of a simulation is a function of the level at which we can easily add content.

Should Activities Exist Inside or Outside the Minds of the Agents?
We have presented arguments aiming to illustrate that 'activities', in a broad sense, are something which must be present in realistic simulations of people. Further, we have argued that new activities should be easily addable. We have been deliberately vague, thus far, in precisely how this importance is to be addressed, and in what sense they should be 'included'. It is our claim that the best way to include them is for there to be actual 'activity-things', non-physical entities with their own state and internal logic to them, existing in the game world. Based on their state, they influence the behaviour of the agents within them, and based on what happens, they change their state. Vitally importantly, an 'activity-thing' does not command its participants to obey - it just requests that they perform an action, and tells them the consequences of ignoring this request. The agents themselves decide which requests to listen-to, based on their evaluation of the consequences of performing the various options.

There is one superficially impressive argument against this model, viz the fact that, in the real world, it seems that activities do not exist, at least in this sense. If they exist at all, they exist in our minds alone. "Ought we not, therefore, simply build the agent minds in an appropriate way, and hope that they 'discover' or 'learn' activities?"

The activities-really-exist approach has significant advantages over the all-in-agents'-minds one. Firstly, it is vastly simpler. Second, it is much less wasteful of memory - the state of activities would, in a simulation based on the second approach, have to be stored multiple times, once for each agent. Third, it is much clearer how newly created types of activity (the creation of which, we have argued, must be as simple as possible) will fit into the activities-really-exist approach - they just create new kinds of activity objects in the world. Under both approaches, the agents minds ultimately make the choices over which actions they want to take - activities are only a guide.
Having dismissed the in-agents-minds approach to activities, no other natural contenders, apart from the one we have suggested, present themselves. It has the virtue of straightforwardness, and of being (to some extent) tried-and tested: in Black and White,. towns, reactions and dances were all implemented as 'group minds'.

Now that we have explained why we think there should be 'activity-things' in the game-world, let us drop the shudder quotes and silly name, and call them simply group activities, or (where no confusion with the naive meaning of the word arises) simply activities.

Objection: "Are You Not Really a Behaviorist in Disguise?"
There is a worry that by focussing on the social activity, and allowing activities to influence how agents behave, we are taking something away from the individual agents - where is agent autonomy in this world of overlapping activities which jointly determine behaviour? Are we not really behaviourists in disguise, who are taking the cleverness out of the agent, and putting it into the social activities instead?

Remember that an agent does not blindly follow the commands of an activity. Instead, an activity requests that an agent does something (and communicates to him the consequences of failing to follow this request). An agent who is in many overlapping activities at once will have a number of requests pending at any time, and must choose between them. He decides which to follow by looking at the consequences of accepting or rejecting each request, and chooses the option which best satisfies his current goals.

"OK", says the objector, "your agents have some autonomy because they can choose between the various requests they receive. But they are not properly autonomous because the range of choices is dictated from outside (by the activities), they do not themselves decide what the range of choices is".

This objection misses the point made earlier, by Wittgenstein and others, that participation in an activity enables us to make choices we couldn't otherwise make. Unless we are participating in the game of chess, we cannot choose between castling kingside and queenside. This choice is only available to us once we have entered into the chess-playing activity. Social-activities, in other words, are not constrictive but enabling. As another example, a couple cannot get married except in a societal and cultural context. Without culture, while they can visit a civic building, swap rings, say appropriate words, sign in a book and take lots of photos, they have not got married despite the fact that (in the particular culture and society that the authors come from) these are the physical actions that a couple do perform if they get married. Participation opens up new possibilities.

The Implementation of Activity-Orientated structure

Requirements for an Implementation of Activities
Our activity implementation must satisfy these requirements

  • It must be easy to add new activities

  • Processing activities must be fast

  • Activities must be easily debuggable

  • The consequential structure of activities must be able to be queried by agents, so that they can determine whether or not it is in their interest to accede to requests.

Already these requirements seem almost incompatible: if activities must be efficient and debuggable, they should be written in C++ so we can use the existing optimisation and debugging tools, but if they are written in C++ it won't be very easy for content authors to add a new activity, because it will require a programmer, and it will be very difficult for the structure of the activity to be exposed to the agents: it might necessitate duplication of information, once to do things, and once to tell the agents what will be done. If, on the other hand, an activity is defined in a text file in a nice easy-to-use language, then content authors will be able to add new activities easily, and the agents will be able to use the information, but we lose the optimisation and debugging tools which C++ gives us. What to do?

The solution we have adopted is to define a new activity in a text-file, in a special-purpose easy-to-use language, but when this activity is parsed, c++ files are generated. This way we get the best of both worlds!


Implementation: Overview
A new activity is defined in a text file. When the activity is parsed, a new c++ activity is defined in cpp and header files. This activity inherits from the base Activity class:


image2.jpg

When the activity is parsed, a new c++ activity is defined in cpp and header files..

The alternative to this might be some C preprocessor based technology (Game Programming Gems Vol 1, Section 3.1 - A Finite State Machine Class). This would have the advantages of being simpler (one would not need to write a parser) and one would gain the benefit that the code the debugger debugs would be precisely the same as that the user wrote, rather than merely generated from it. However, this would unacceptably straightjacket us - the preprocessor is a very weak tool. Moreover, writing a parser is not very hard using lex and yacc (note also that the hard part of writing a compiler from scratch, the semantics, can be partly avoided as we build our language on C++ and can leave some of the semantics to the C++ compiler). Moreover, on certain systems, via use of techniques like #line preprocessor directives, the debugger can be made to take the user directly to the appropriate line of the activity file, if the system breaks in an activity.

Activities in More Detail
Now we have decided that a dedicated 'front' to C++ as a form for an activity system, we must ask what form we would like that front to take. The first approximation to an answer would, for most game programmers, be a state machine. State machines have a proven history, and are very useful. However, it turns out to be useful to extend this slightly, to make the states hierarchical, and give states local variables. These are automatically constructed on entry and destroyed on exit. This is very similar to programming using the local stack machines in (Game Programming Gems 2, Section 3.2, Micro-Threads for Game Object AI) Thus an activity defines a state hierarchy:

     activity Name(Parameter1, … ParameterN) {
          State1:
                 State 1.1:
                        …
                        State 1.1.1
                                …
                        State 1.1.2
                                …
                 State 1.2
                        State 1.2.1
          …
     }

Each particular state can have its own parameters, its own preconditions, its own message handling, its own local variables with initialisations, its own actions, and its own sub-states.

Needs
Needs conditions specify what needs to be true for the activity to remain in this state, and what state to switch into if circumstances change. If we are in a particular state, all needs conditions in all parents states are checked before checking our own particular state's. If we have the state tree:

     S1:
          needs 1
          S2:
          {
               needs 2
               ..
          }
     S3:
     …

and we are in state S2, then needs1 will be checked, followed by needs2.

Requests
The only way an activity can affect the game-world is by issuing a request to an agent. Request statements ask agents if they wouldn't mind performing actions, and waits to find out if they actually bother to perform these activities.

A requests statement will appear in a state of the form:

     // needs conditions
     requests
          agent1.action1 !Þ Rejection(1)
          ®
          Finished
     {
          // actions to perform while waiting
     }

The first time this state is entered, the requests are passed to the agents concerned. From then on, we wait to see if any agent rejects the request; if so the rejection message is passed. If all agents finish their requested activities, state moves to Finished.

Messages
Messages are a way for activities to communicate without having to knowing each other's implementation details. Activities respond to messages using message-handlers. A message can have various parameters which are passed to the handler. If a message is passed to an activity, the handler function is called immediately. The handler may or may not change the state of the activity. Messages can be defined at any level of the state hierarchy -- handlers lower down the chain take priority over more general handlers.

Example Activity

   ScissorsPaperStone(Agent p1, Agent p2, int max_score)
   needs p1, p2
   constructor
   {
          int score1=0;
          int score2=0;
          int NumGoes=0;
          AGENT_LIST Players;
          enum actions
          {
                 scissors,
                 paper,
                 stone
          };
          Players.push_back(p1);
          Players.push_back(p2);
          -> Play
   }
   state Play
   {
          needs score1<max_score && score2<max_score !-> Finished
          requests
                 Players do CHOOSE(scissors, paper, stone) !-> GiveUp
                 ->
                 Evaluate
   }
   state Evaluate
   {
          if (p1.GetChoice() > p2.GetChoice())
          {
                 score1++;
          }
          else
          {
                 score2++;
          }
          -> Play
   }
   state Finished
   {
          if (score1 > score2)
          {
                 => UpdateScoreFromResult(p1) // send message to parent
                 -> WinnerCelebrates(p1, p2)
          }
          else
          {
                 => UpdateScoreFromResult(p2) // send message to parent
                 -> WinnerCelebrates(p2, p1)
          }
   }
   state WinnerCelebrates(Agent winner, Agent loser)
   {
          requests
                 winner do CELEBRATE() !-> GiveUp
                 ->
                 LoserCries(loser)
   }
   state LoserCries(Agent loser)
   {
          needs loser
          requests loser do CRY() -> GiveUp
   }
   state GiveUp
   {
          -> Delete
   }


Conclusion

In this article, we have tried to motivate the introduction of social activities as the next obvious level at which to add content, and we have outlined a working system which makes it very easy to add a new activity (without having to worry about all the book-keeping needed to integrate our new activity with all the others). In our prototype, we already have a large number of activities running simultaneously: various games (both turn-taking games and games with simultaneous-turns), conversations, meal-times, courtship activities, with a moral community activity running in the background.

This work has been inspired by philosophers (Wittgenstein and Dreyfus) who are apparently critical of the very possibility of AI. It is pleasantly ironic that their work, which they might see as precluding the possibility of AI, will result in the next generation of social agents.

References

DeLoura (ed), Game Programming Gems, Volumes 1 and 2
Dreyfus, "What Computers Still Can't Do"
Hacker, "Wittgenstein: Meaning and Mind"
Heidegger, "Being and Time"
Wittgenstein, "Blue & Brown Books"
Wittgenstein, "Philosophical Investigations"
Wittgenstein, "Zettel"

Read more about:

Features

About the Author(s)

Richard Evans

Blogger

Richard Evans is head of artificial intelligence at Lionhead Studios. Before coming to work at Lionhead, he studied philosophy at Cambridge and later Artificial Intelligence at Edinburgh. He was responsible for much of the AI in Black & White, the creatures' AI, and the various "group minds" (reactions, dances) of the villagers.

Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like