CHAPTER 13

image

Engineering Domain-Specific Languages for Games

Robert Walter

Programming languages are like musicians. The broader the audience they are addressing, the more popular they can become, even if they are not the best at what they do. While it takes a lot more than a mainstream orientation to stay on top of the charts, it is always a plus to address the wants of the many.

But there is a place for the specialized, too. Just as alternative artists pervade the history of music, domain-specific languages (DSLs) have enjoyed a long tradition in software engineering (a good overview is given in Deursen et al., 20001). While early versions of this kind of programming language like FORTRAN, Lisp, and COBOL evolved over the years to fulfill more generic purposes (thus staying famous), others like SQL, regular expressions, and make became evergreens within their technical domains. Despite their success, however, the concept of engineering and the potential of using DSLs have been relegated to the “academics and theory” shelf for a long time (a good reference on DSL development patterns is given in Mernik et al., 20052). Only recently, a growing interest in software design philosophies like user-centered and domain-driven design, as well as the coming of age of model-driven development methodologies and language workbenches, has led to a new popularity for these elegant tools.

Now, without stressing the music analogy any further, let’s take a look at two questions.

  1. Why should game developers care about DSLs?
  2. How can game developers make use of DSLs?

Naturally, I need to cover some basics first, but I cannot dive too deep into the details of language-oriented programming (LOP) in this chapter. Therefore, those who are new to the field of programming languages and how they work might consider reading the cited literature first.

What Are DSLs?

Object-oriented programming expert Martin Fowler only recently defined the term “domain-specific language” in a very handy way (Fowler, 20103), so let’s use his definition in order to discuss the characteristics of DSLs:

A DSL is a computer programming language of limited expressiveness focused on a particular domain.

The purpose of a DSL is to let users write computer instructions in a “natural” way. I knowingly choose the generic term “user” in this context, since DSLs are first and foremost languages designed for domains, not specific user groups. Although domain experts should be involved in the creation of a DSL to make use of their domain knowledge, they do not have to be users of the language. In game development, however, there is a huge potential in empowering designers using DSLs, as you will see later.

Unlike general-purpose languages (GPLs) like C++ and Java, DSLs provide only a limited vocabulary and almost no control structures. Instead, they offer powerful, domain-specific semantics. In short, a DSL features exactly the elements necessary to describe its application field formally (read “completely”) and precisely, which makes it easier to learn, even if less expressive, than a GPL. DSLs abstract by making the relevant details of a domain explicit, while omitting the distracting ones. This approach allows developers to address problems right where they occur: in the problem space, instead of manually mapping them to a generic solution space.

Like GPLs, DSLs feature a formal syntax. Thus, a domain-specific program (DSP, a program written in a DSL) can be processed automatically with an interpreter or a generator, for example.

What Does a DSL Look Like?

Bearing the game development process in mind, you can think of a sample language that is tailored to the “interactive dialog” domain. Listing 13-1 shows a language definition using four regular expression rules.

Listing 13-1. Simple Language Definition for Branching Dialog

dialog ::= dialogLine dialogLine+ ;
dialogLine := character action ':' STRING ('or' dialogLine)?;
character := ID ;
action := 'asks' | 'says' | 'answers' ;

The first rule defines a dialog as a dialogLine followed by at least one or an arbitrary number of additional dialogLine elements (specified through the + symbol). A dialogLine features a character that has to be an identifier (ID), followed by an action that is either the keyword asks, says, or answers. A colon and a STRING (the actual content of the dialog line) follow. The rule for the dialogLine uses optional recursion (the ? symbol indicates optionality) to allow nesting dialog lines. A program written in the language above might look like the one in Listing 13-2. Although the language design in this example is certainly far from perfect, it should give a basic idea of what DSLs can look like.

Listing 13-2. Simple DSP Example for Branching Dialog

Robert asks: “So, what do you think of this so far?”
Reader answers: “It looks just great!”
    or
Reader answers: “Not so sure if that might work, but I'll give it a try.”

Using proper generators, dialog written in the language of Listing 13-1 can be transformed into different formats. For example, you could create several scripts sorted by characters for the audio recordings, the necessary XML format for the story engine, and a graphical representation such as a dialog tree displaying the dialog’s structure. The dialog script becomes the central entity for dialog writing (it is code, after all!). Whenever dialog needs to be changed, the writer changes the DSP and distributes the new version by recompiling the program. This type of centralization represents but one way that DSLs can significantly help to preserve consistency throughout the development process, utilizing the “DRY” principle (“Don’t Repeat Yourself,” Hunts and Thomas, 19994).

Now, for everyone who might feel the need for a third, more “renegade” reader answer in Listing 13-2, like, “Don’t bother me with DSLs. Everyone knows that they are impractical due to the fact that one always needs to build a complete infrastructure for them, like a parser, an editor, and an analyzer, which still would not be comparable to a common IDE,” please make do with the second reader answer in Listing 13-2 for now. I’ll come back to this issue in a second.

A Categorization of DSLs

There exist different “kinds” of DSLs. A DSL can either be internal or external (Fowler, 20105). This differentiation is useful since internal and external DSLs are not only different in the way they are created and used, they are also usually applied in different contexts, as you will explore in a second. A less rigorous way to categorize DSLs is to consider their technical orientation. Eventually, both ways of categorization should help you to get a better “grip” on the term “DSL.”

Internal DSLs

An internal DSL is embedded in a GPL using a limited set of the features of the GPL. Internal DSLs are bound to the grammar of their host language and thus do not need a distinct toolset to be processed. This, of course, constrains the flexibility of syntax design. A good example of an internal DSL is incorporated within the .NET Framework component LINQ. It provides a natural language-like API that utilizes the access to data collections.

A common way of defining an internal DSL is through chained methods. Listing 13-3 illustrates the Method Chaining pattern (compare Fowler, 2010; there are more patterns described to define internal DSLs—take a look at Fowler’s book) available in LINQ. The given statement returns a list of selected inventory items in descending order according to their value. Note that this is plain C# code.

Listing 13-3. Example of the Method Chaining Pattern Used in LINQ

return inventoryItems
        .Where(item => item.IsSelected)
        .OrderByDescending(item => item.Value);

Internal DSLs exploit the advantages of language-like programming interfaces, making code more comprehensible and consequently easier to maintain. In game development, I consider internal DSLs a useful tool to simplify development processes, since many domain experts (visual artists, sound engineers, etc.) do have a technical background and thus, even if they are not intending to use internal DSLs to develop game logic by themselves, are able to understand corresponding programs. This capability introduces interesting possibilities in terms of communication, cooperation, and agile development techniques like pair programming.

External DSLs

Juxtaposed with internal DSLs, external DSLs are self-contained languages featuring their own grammar and a standalone infrastructure. Hence, an external DSL can be tailored exactly to the requirements of the domain, using semantically meaningful keywords and grammar rules. Similar to GPLs, a program written in an external DSL is processed in the form of an abstract syntax tree (AST). As a consequence, one needs to define proper processing tools in order to really benefit from an external DSL. The creation of external DSLs is increasingly supported by tools commonly called language workbenches, like Xtext, MetaEdit+, MPS, and Microsoft’s Software Factories, which, among other things, feature rich support for the creation of IDE tooling. For example, based on a single syntax definition file, Xtext creates the corresponding abstract syntax definition file, a fully featured parser, and a serializer, as well as a rich plug-in editor with syntax highlighting, code completion and validation, and quick fixes by default (see Figure 13-1).

9781430267003_Fig13-01.jpg

Figure 13-1. Dialog language definition in Xtext (top) and complying sample program in generated default editor (bottom)

Technical Orientation

In addition to their environment, DSLs differ in their technical orientation. This is a qualitative distinction compared to the one above, but it proves useful to understand the potential in the application of DSLs. The internal DSL integrated in LINQ, for example, is a highly technically oriented, internal DSL. It utilizes the ability to query structured data, which can be used for arbitrary application domains. SQL is an example of a technically oriented, external DSL. Altogether, we can categorize DSLs that abstract a technical problem space as highly technically oriented (as has been done similarly by Kleppe, 20086).

In contrast, there are languages that describe non-technical domains. For example, Inform, currently in its seventh installment, features a declarative DSL with a very natural language-like syntax to create interactive fiction applications, as shown in Listing 13-4. Inform 7 abstracts a non-technical domain to allow users to create their own interactive fiction without handling technical issues.

Listing 13-4. Rule Description in Inform 7

Instead of throwing something at a closed openable door, say “Or you could just use the handle like anyone else, of course.”

Figure 13-2 provides an overview of possible DSL forms of interest in this chapter. While a DSL is either internal or external, the dimension of technical orientation is certainly somewhat blurry, allowing DSLs to address different fields of application. As it is especially hard to think of a popular internal DSL with a low technical orientation, Figure 13-2 shows an example of a made-up language, which could be embedded in C++ to equip characters and set some properties.

9781430267003_Fig13-02.jpg

Figure 13-2. A DSL landscape

Note that DSLs do not have to be textual, but can be graphical, contain tables, or mix different kinds of representations. Although it is a major decision whether to use a textual or a visual language, this differentiation is of no further concern for the workflow presented here. The decision should always be made individually in a very early phase of language engineering and should depend on which representation best fits the domain at hand.

Why Should You Even Care?

As mentioned before, domain-specific languages raise the level of abstraction, which allows you to address problems right where they occur. But what does this mean for game development? Game development combines the artistic challenges of multimedia production with the engineering challenges of IT. Experts from many different disciplines (game design, art, programming, acting, music, and so on) join forces to create and deliver a product. Thereby, the transition from game design to a playable game is arguably the most crucial step to take within a production process.

Game design documents (GDDs) are the common tool used to bridge the gap between design and implementation. However, just as in classic software engineering, document-based development approaches of this kind present several problems. They rely heavily on game designers’ ability to communicate their ideas in a comprehensible way, and to understand problems occurring during implementation that call for design changes. These changes must be thoroughly integrated into the GDD. At the same time, development teams must be able to interpret the design document correctly and translate it into code, never missing revisions or ad hoc changes.

It is hard to guarantee consistency throughout a project, especially with larger teams. On a project management level, agile development approaches like Scrum (Schwaber, 1995, Keith, 2010) have been introduced successfully in the last years to address these issues and to compensate for the missing scalability. Utilizing frequent communication (“daily scrums”) and short iteration cycles (“sprints”), an empowerment of the development teams as well as a process supervising role (“scrum master”) have brought significant benefits to different AAA productions, like Double Fine’s Brütal Legend,7  Valve’s Left 4 Dead 2,8  and Turn 10’s Forza Motorsport 3.9  Still, there is a gaping lack of consistency on the tool level that strengthens the transition from design to implementation, and that is where DSLs fit in.

In the realm of academia, there are different approaches that try to devise generic, formal languages that allow the description of game design per se. Because they need to be able to cover the design of Skyrim as well as Angry Birds, however, their concrete syntax often lacks accessibility and expressiveness, making them inapplicable in practice.

It seems to be a more flexible and hence a more pragmatic approach to allow and utilize both the creation and the application of specific modeling languages that meet the demands of a given game project directly. This way, toolsmiths and developers can facilitate long-established and a “for them approved” terminology as well as an appropriate level of technical orientation and abstraction in the language design. DSLs enable exactly this, and generally, can be an integral tool to support the following:

  • The implementation of games in a faster, more precise, and more natural way.
  • The communication of game design by creating and using semantically meaningful and at the same time formal models.
  • In the case of external DSLs, the integration of high-level content into a game by automated interpretation or (text) generation.

Hence, the main potential of DSLs in game development is to empower non-programmers like game designers and writers. Still, DSLs can be a useful tool for programmers too, not least by fostering interdisciplinary collaboration among the different domain expert groups, but also by writing code on a higher level of abstraction. This approach leads to faster iteration times, a higher consistency throughout the development process, and eventually to higher product quality.

In the following section, you will look at a language engineering workflow that demonstrates how DSLs can be defined and how this process can accompany and enhance game design.

How to Use DSLs

The categorization of DSLs has shown that their application can be manifold. That is also true in the context of game development. However, instead of a tedious discussion about which application fields might be more or less appropriate for them, you will work through a language engineering workflow. The workflow is intended to let you, as a toolsmith, create languages for your game projects, since you know best which tools fit into your development process. The workflow is therefore knowingly independent from the type of DSL you want to create and the tools you want to use to create your language infrastructure. For illustration purposes, you will consider the creation of a weapon definition language to highlight the steps of the workflow and underline how the language creation process itself can be used in the context of designing aspects of a game. Naturally the example is simplified due to the limited space a book chapter provides.

Language Engineering Workflow

The creation of a domain-specific language is an iterative process, just as the creation of a good game should be. The main assumptions of the language engineering workflow presented here are that there should always be two different kinds of development roles and that the language design should be undertaken from the bottom up.

Figure 13-3 shows the two developer roles in language engineering. First, let’s define a domain expert as a person with extensive domain knowledge and expertise. The domain expert is in charge of identifying and defining the entities and semantics of the domain. Domain experts are not in charge of developing the language’s actual syntax or any tools for language processing. This responsibility falls to the language engineer, who is a person with extensive knowledge in language design and tool creation for various environments and purposes.

9781430267003_Fig13-03.jpg

Figure 13-3. Roles and their tasks in language engineering

Depending on the scope of the domain, it is reasonable that more than one domain expert and language engineer participate in the language engineering process. Furthermore, the described tasks of a domain expert can be subdivided into front-end and back-end tasks. This means that there might be a front-end domain expert, for example, a game writer who leads the identification of the requirements for a branching dialog language. One back-end domain expert, a programmer of the story engine, covers the design of the intended outcome and further processing, while another back-end domain expert, a localization manager, determines which information is necessary for voice recording scripts. The language engineers take this information and synthesize it into a language definition and corresponding toolset. The basic workflow with the respective role responsibilities is shown in Figure 13-4.

9781430267003_Fig13-04.jpg

Figure 13-4. Bottom-up workflow with role responsibilities

DSL Requirements

Led by the domain expert(s), the DSL requirements are determined by domain characteristics, which means that proper abstractions of the domain need to be found. The domain characteristics should therefore at least comprise the central domain entities and terms with clearly confined semantics for the given domain. Language engineers should interpret their role in a predictive, hence moderating, way during this phase in order to create both a sound domain outline and a solid foundation for the ultimate language design. As the bidirectional relationship between the DSL requirements and the reference artifacts points out, I propose an iterative process between these two tiers. The DSL requirements are meant to eventually capture the domain so that both domain experts and language engineers are aware of the vocabulary, semantics, purpose, scope, and target group of the domain.

What is called “general criteria” can be derived from language engineering principles as listed in Table 13-1, taken from the book Software Language Engineering by Kleppe, 2009.

Table 13-1. Principles of Language Engineering

Principle

Description

Simplicity

An easy-to-learn language is easy to use.

Consistency

Choose a suitable design and hold [on] to it.

Flexibility

Give the user flexibility in how to formulate a DSP.

Homogeneity

Show related concepts in the same way and keep them together; show unrelated concepts differently and separately.

Color

Use color sparsely.

Testing

Test the language design on language users.

For this example, you’ll look at a fictional language creation process at Fictional Game Studio (FGS), following the toolsmith and language engineer Tobey, working with a game designer called David to create a DSL for defining weapons and their behavior. Tobey is new to the team and does not yet know how the internal processes at FGS work. In a first iteration, David describes the requirements for the language as follows.

David: In our upcoming game, the player will use different kinds of weapons, each with its own abilities and behavior. The goal is to have a simple language that allows us designers to describe the weapons and how to use them. Based on these descriptions, we want to generate different things like a media list for the art department, statistics about the weapons, and the necessary code files so that our game engine can work with the weapons.

Tobey: By “kinds of weapons,” do you mean that there will be different weapon classes you want to describe with the language, like Sword and Axe, or do you mean to describe specific weapons like a sword called Slicer, for example?

David: Both! There will be what we call weapon types, like Sword, Dagger, or Axe, which determine distinct abilities for a weapon, like range or how the weapon is handled. Then there will be concrete swords, like a Slicer or an axe called Splitter, which are the actual weapons used by the player.

Tobey: So there is already a fixed set of weapon types?

David: We know that we want to include swords, daggers, and axes, but the language should allow us to define new weapon types during development.

Tobey: This means we need a weapon type description language as well as a weapon description language. How is a weapon type defined?

David: Every weapon type determines if it is a one-handed or a two-handed weapon. What’s more, a weapon type is either of short, medium, or long range, and either of slow, medium, or fast velocity.

Tobey: And what abilities do weapons have?

David: Every weapon has a unique name and a unique look. Naturally, a weapon has an attack attribute that determines how much damage the weapon can do. There is also a durability attribute, which determines the weapon’s status.

Tobey: What does that mean exactly?

David: Over time, weapons get worse, and durability decreases. When durability becomes zero, the weapon breaks and becomes worthless when used.

Tobey: So weapons get worse over time regardless of whether they are being used?

David: That’s actually a good question! The durability was meant to decrease by stroke and a certain probability. However, our game tells a story throughout several decades, so let me discuss this with my team before making a decision.

While the domain expert, David, describes the intention for the language, Tobey needs to ask the right questions to find and define the requirements of the domain at hand. As you can see with the durability property for weapons, the process of defining the language requirements might be used as a tool to reconsider game design itself, although this is not its primary focus, of course. Tobey and David are going to refine this first requirement talk after taking a look at the second layer of the language engineering workflow, namely the reference artifacts.

Reference Model

There are two kinds of ephemeral artifacts that have to be created in the second layer of the language engineering workflow. The intention is to find exemplary instances of the front end (reference models) and the back end (reference output) of the toolset. The reference artifacts should iteratively be developed to enrich and specify the DSL requirements more precisely. In the end, they should include instances for all domain elements in order to cover the domain exemplarily as well as consider language engineering principles (see Table 13-1).

A reference model is a sample program written in the planned language. The central issue is to think of a representation that covers as many of the DSL requirements as possible. Thereby, the reference model serves as a communication platform between domain experts and language engineers in order to combine and manifest their expertise in the language design. In other words, the reference model is the vehicle to map the DSL requirements (layer 1 of the workflow) to the concrete syntax of the language (which will be defined in layer 3). Again, the language engineer should moderate the creation of the reference model, always keeping the tooling of the language in mind. This is where the game designer (as a domain expert) might benefit even more from the language creation process. The task of finding a textual or graphical formal representation that separates a game concept or design from its technical realization in a multi-expert group implicitly leads to a reconsideration of existing design ideas and can validate and render them more precisely and even enhance them. Let’s see how Tobey and David are proceeding.

Using pen and paper, David and Tobey start to create reference models for their weapon description language based upon the first DSL requirements.

David: I think I understand what reference models are meant for, but how are we going to approach this?

Tobey: Let’s start with the weapon type language. How would you like to define weapon types if we were to be completely free? Go ahead, how would you define the weapon type Halberd, for example?

David: Well, maybe just like this:

Halberd is a new weapon type.

Tobey: Very good. Now, is it a one-handed or two-handed weapon type? How fast is it? What is its range?

David: This would be a slow, two-handed weapon type of long range.

Halberd is a new, slow, long-range, two-handed weapon type.

Tobey: I like your language design, since it’s extremely readable and explicit. It already contains all the information necessary to define a Halberd. However, it is somewhat verbose, so I would suggest simplifying it a little. Since this is a definition language, I would argue in favor of making this fact explicit in the language, introducing a keyword Define.

Define Halberd as a new, slow, long-range, two-handed weapon type.

Tobey: Since it’s a definition, we can leave out the term “new.” What’s more, we are going to define weapon types here, so maybe we can also leave out the term “weapon,” if you like, to make it handier:

Define Halberd as a slow, long-range, two-handed type.

After some more corrections and discussion, minding some of the language engineering principles of Table 13-1, they create the following reference model. As you can see, the term type is defined to be optional, minding the Flexibility principle.

Define type Halberd: slow, long-range, two-handed.
Define Axe: medium, mid-range, one-handed.
Define type Dagger: fast, short-range, one-handed.

For defining weapons, they run through a similar process, finally coming up with the reference model shown in Listing 13-5.

Listing 13-5. A Reference Model for Defining Weapons

Define Splitter as Axe:
              attack = 16
              durability = 23
             < by stroke: 0.1, 30%
             < by day: 0.2, 50%
Define weapon Needle as Dagger:
              attack = 7
              durability = 20
              < by day: 0.2, 10%
              < by stroke: 0.1, 80%
Define Toothpick as Halberd:
              attack = 38
              durability = 44
              < by day: 0.3, 20%
              < by stroke: 0.2, 30%

Weapons are defined by a name and refer to an available weapon type. Similar to the term type in the first reference model, weapon is declared optional here. After a colon, the weapon properties need to be defined. The attack property is determined by a positive number, while durability is defined by a maximum value as well as two additional value pairs. Each durability decrease is introduced by a lower than symbol. The first pair indicates how much the durability decreases per stroke with a distinct probability, the second pair respectively how much the durability decreases per in-game day, also by a distinct probability. It is up to the designer to decide which decrement behavior is defined first (again, minding the Flexibility principle!).

Reference Output

In general, DSPs can be processed in two different ways. It is possible either to execute a DSP directly with a dedicated interpreter or to process it with a generator, for example, to generate code or configuration files. In the case of generation, the reference output has to represent the desired generated artifacts corresponding to the reference models. The relation between the reference models and the reference output is vital to identifying the processing rules later on. In case of interpretation, the reference output has to mirror the desired results and actions the reference model is intended to evoke. This could be a storyboard displaying how the interpretation of a dialog defined in a DSP should be displayed later on screen. The reference output has to be defined for every target platform and every reference model. That way, the language engineers can derive the processing rules necessary to fill the gap between both abstraction layers. Actually, the gap correlates to the applied degree of abstraction in the DSL. In other words, the processing rules have to add the target platform-relevant details that are omitted by the degree of abstraction of the corresponding DSL. Let’s look at the example at FGS again to illustrate this.

For weapon type and weapon description languages at FGS, there are different outputs desired:

  • A media list for the art department
  • Statistics about the defined weapon types and weapons for the designers
  • Configuration files that utilize the weapon types and weapons for the game engine.

You are not going to look at how the different outputs for the DSPs are created from a technical side, but you will examine how the requirements for the processing rules can be identified and refined working with the corresponding domain experts.

Media List

In cooperation with Arthur from the art department, Tobey and David figure out that the media list will be a simplified version of a “weapon program,” a simple to-do list, so to speak. Every weapon type needs a 2D icon for the in-game menu, every weapon a 3D model. The idea is that whenever a designer comes up with a new weapon type or weapon, the art department gets an updated to-do list to create a first draft of the necessary asset. In the case of the weapon type language, the art department specifies that they need to know the name of the type (e.g., Dagger) and whether it is a one-handed or two-handed weapon type. In case of the weapon description language, they also need the name-attribute (e.g., Needle) and the corresponding type of that weapon. In order to allow an iterative development process, additions to the weapon program must not override already checked items on the artists’ to-do list. The corresponding reference output created by your stakeholders looks like Table 13-2 (the third column is meant to be edited by the artists manually).

Table 13-2. Reference Output for Art Department

Weapon Type

One- or Two-handed?

2D Icon Done

Halberd

Two-handed

Yes

Axe

One-handed

No

Dagger

One-handed

No

. . .

. . .

. . .

Weapon

Type

3D Model Done

Splitter

Axe

Yes

Needle

Dagger

Yes

Toothpick

Halberd

No

Statistics

The statistics for the weapon types and weapons are something that game designers should benefit from. They should help decide which weapons are going to make it into the final game and what kinds of weapons with which properties are missing to finally balance the game’s “weapons inventory.” Hence, this view should enable the designers to display and compare the already defined weapon types and weapons in terms of their abilities. The information for this view can be directly derived from created weapon programs by parsing the abstract syntax tree. Hence, Tobey and David decide to create an interpreter that displays the statistics for the weapon types using three pie charts. Thereby, the weapon types are counted and compared in terms of their handling (one-handed vs. two-handed), their range (short-, mid-, and long-range) and their velocity (slow, medium, and fast). Moreover, the statistics for weapons should allow designers to ask for the expectable durability of weapons given by their durability properties. Figure 13-5 shows a draft for the statistics view.

9781430267003_Fig13-05.jpg

Figure 13-5. Reference output for statistics view

While the upper half of the statistics view is not editable, designers are meant to insert a weapon’s name, the number of hits, and the number of days in order to see the weapon’s worst case and expected behavior. Naturally, you could include a lot more statistical features based on the data of a weapons program.

Configuration File(s)

For the implementation to generate, David and Tobey talk to Paul, the senior programmer of the team. Paul shows Tobey how FGS’ in-house game engine manages in-game items in general and how they intend to integrate the modeled weapons into this system. The abstract concept of weapon types is realized in the engine by an abstract class called WeaponType. The code generator is now in place to generate a subclass for every designed weapon type that sets its properties and prepares the necessary method stubs (see Figure 13-6). Moreover, every designed weapon is mapped to an object instance of the corresponding weapon type. Therefore, the generator needs to create a simple XML file that serves as configuration file for the game engine, as shown in Listing 13-6.

Listing 13-6. Excerpt of Reference Output XML Configuration File

<Weapons>
     <Weapon id="Splitter">
          <Type>Axe</Type>
          <Attack>16</Attack>
          <MaxDurability>23</MaxDurability>
          <DurabilityBehavior>
               <Day value="0.1" probability ="30" />
               <Stroke value="0.2" probability ="50" />
          </DurabilityBehavior>
     </Weapon>
     ...
</Weapons>

Note that the class diagram in Figure 13-6 is not the created reference output but gives an overview of the classes that need to be generated for the corresponding reference model. The reference model would be an actual implementation of at least one of the classes in the target language, such as C++.

9781430267003_Fig13-06.jpg

Figure 13-6. Class diagram illustrating the classes that need to be generated

Language Definition

The language definition and the processing rules are directly derived from the reference artifacts. The language engineers have to identify syntax rules and static semantics based on the reference models for the language. The creation of the generators and/or interpreters should not be performed at the very end, but iteratively with the language definition, since some requirements of the processing might influence the language implementation. Furthermore, depending on the technology used to create the language toolset, small adaptations—in comparison to the reference model—are inevitable in language design. However, the language engineers should always confer with the domain experts in order to find an adequate solution in case of changes. In order to make external DSLs really applicable, IDE support is necessary. Language workbenches support the creation of smart editors, which, for example, feature syntax highlighting, text completion, and syntax analysis by default.

Just like in GPLs, the abstract syntax is the structural description of a DSL. In its representation as an abstract syntax tree (AST), a DSP can be processed by a parser. The user, however, writes DSPs using a concrete syntax, featuring keywords in a distinct notation. A concrete syntax thereby always conforms to an abstract syntax. Hence, it is possible to create several concrete syntax definitions for the same abstract syntax, for example, a visual and a textual representation for different use cases.

Given the reference artifacts from the last section, Tobey and David are now able to derive the grammar for their languages as well as create the processing rules and tools for the interpreters and generators they need. To illustrate how the grammar can be derived from the reference models, you use the Xtext grammar language to create the weapon type definition language. Considering the reference model again, you can derive that weapon types are defined by a sequence of single weapon type definitions:

Define type Halberd: slow, long-range, two-handed.
Define Axe: medium, mid-range, one-handed.
Define type Dagger: fast, short-range, one-handed.

The reference model in this example holds three of these weapon type definitions, but in practice there might be an arbitrary number of definitions per file. You can derive a rule that your Model consists of an arbitrary number of TypeDefinitions:

Model: typeDefinitions+=TypeDefinition* ;

In Xtext, this line means that you have a root element called Model that holds a list of elements of type TypeDefinition. Now, how is TypeDefinition defined? Every single definition starts with the keyword Define, optionally followed by the keyword type. After that, an identifier has to follow. After a colon, the three properties for a weapon type have to be declared. In Xtext, this can look like Figure 13-7.

9781430267003_Fig13-07.jpg

Figure 13-7. Language definition (concrete syntax) for weapon types in Xtext (top), showing the automatically generated abstract syntax as ecore model (bottom)

Similarly, you can derive the grammar rules for the weapon definition language. For the different outputs suggested in the example above, the description of the corresponding implementation would go beyond the scope of this chapter and might well cost a lot of resources.

Conclusion

Domain-specific languages are a powerful tool to abstract the core of a problem from technical or unrelated constraints. For game development, they offer different possibilities to be usefully applied. They can bridge the gap between game design and its implementation by empowering game designers and writers to formally describe parts of a game, meaning to program it. The creation process alone can help to validate, refine, and enhance existing game designs, making the process itself a tool to find precise game design descriptions. Using generators or interpreters, the formal structure of DSLs enables all kinds of possibilities for processing domain-specific programs. Generators might be used to transform a DSP automatically into another, usually more specific format, like C++ code or XML files to free programmers from tedious and error-prone tasks. DSPs might as well be interpreted directly to simulate and evaluate modeled behavior, like playing through an interactive dialog, or to derive additional information from a DSP in real-time, like the in-game item statistics shown in this example. Last, but not least, internal DSLs can be used to make programming interfaces more comprehensible to non-programmers, opening up new possibilities for pair programming, something that, unfortunately, could not be handled in more detail in this chapter.

The language creation process itself can be used to communicate and reconsider a game’s design iteratively, as has been shown by the example in this chapter. Game designers can incorporate design rules into the DSL, making the design independent from concrete implementations—an especially important consideration for multiplatform games and/or game series. Once defined, game designs (using a formal language) can be distributed to different platforms with proper generators. Design changes need only be implemented once and can be distributed automatically to all platforms. At the same time, programmers can integrate their domain knowledge into (code) generators so that boilerplate programming tasks are performed automatically with a constant level of quality.

Yet DSLs are no silver bullet for game development. It must still be proven whether the proposed application fields work in practice. A major downside of external DSLs is that one needs to create a corresponding toolset in order to make use of a language. Hence, it is always necessary to consider whether the investment of creating such a tool actually pays off in the intermediate and long term. However, given the state of the art of modern language workbenches that support the implementation of DSLs nowadays, and the fact that there is quite regularly the need to create specific tools in the context of new game projects, it seems only reasonable to consider creating and using DSLs more frequently in the future.

________________

1van Deursen, Arie, Paul Klint, and Joost Visser. “Domain-specific languages: an annotated bibliography.” SIGPLAN Not. 35 (2000): 26–36.

2Mernik, Marjan, Jan Heering, and Anthony M. Sloane. “When and how to develop domain-specific languages.” ACM Comut. Surv. Ser. 4. 37 (2005): 316–344.

3Fowler, Martin. Domain-Specific Languages. Amsterdam: Addison-Wesley Longman, 2010.

4Hunts, Andrew, and David Thomas. The Pragmatic Programmer. Amsterdam: Addison-Wesley Longman, 1999.

5Fowler, Martin. Domain-Specific Languages. Amsterdam: Addison-Wesley Longman, 2010.

6Kleppe, Anneke. Software Language Engineering: Creating Domain-Specific Languages Using Metamodels. Amsterdam: Addison-Wesley Longman, 2008.

7Gamasutra. “Postmortem: Behind The Scenes Of Brutal Legend.” www.gamasutra.com/view/news/25799/Postmortem_Behind_The_Scenes_Of_Brutal_Legend.php#.UJAn-Gcdx_A.

8Nutt, Christian. “Q&A: Valve’s Swift On Left 4 Dead 2’s Production, AI Boost.” Gamasutra. www.gamasutra.com/view/news/25701/QA_Valves_Swift_On_Left_4_Dead_2s_Production_AI_Boost.php#.UJAod2cdx_A.

9Graft, Kris. “Racing Evolution: Forza 3 And The Changing Driving Sim.” Gamasutra. www.gamasutra.com/view/feature/4144/racing_evolution_forza_3%25%20_and_the_.php.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset