26
\$\begingroup\$

Not sure whether it fits the scope of this community, or should go to Stackoverflow instead.

Let's suppose that I want my game be easily extendable in its core, i.e. I want that a lot of people, even without decent programming knowledge, would be able to not only tweak existing rules, but even add totally new game mechanics into it. I'm not good programmer myself, but I'm ready to learn, I'm just need some directions and assurance it can be done.

What I've thought about is whether it's possible/feasible to somehow implement game mechanics separately from the main utility code? I mean, for tabletop games we have those rulebooks which don't contain actual algorithms of all actions, but rather describe some protocols and limits, referencing context of each such item heavily. Is it possible to do something similar for PC game, like, describe all the rules in some very high-level, easily readable (and changeable) by a human programming language, which is then "consumed" and parsed by the utility code into a working instance of game mechanics?

That really seems like I need to write my own language and a compiler for it )) Which I won't be able to do, of course. But may be there is an easier approach to the problem?

FYI: my language of choice for the utility code will be Python 3.x

\$\endgroup\$
2
  • \$\begingroup\$ As you are inexperienced and working as a single developer, I suggest that you don't try to implement everything yourself. Using the SDL2 libraries can be very helpful to you in many areas and they have Python bindings so you can work in the language you're comfortable with. To achieve what you are going for, the design of your architecture should be done very, very, carefully and I would anticipate at least one full rewrite even for an experienced team. Also, Python isn't really that much easier to learn than any other language and in my opinion has major gotchas in the intermediate level. \$\endgroup\$
    – ttbek
    Commented Sep 23, 2017 at 16:26
  • \$\begingroup\$ The concept you're looking for is common outside of game dev. There are collection of software tools called business rules engines which am to do exactly this. In game dev, you could also leverage these tools. Apple's GameplayKit for example included GKRuleSystem and GKRule classes for a similar purpose. It would take some effort to extend to allow external editting of this, but could be structured in a way to change behaviour without recompilation of your code. \$\endgroup\$ Commented Sep 24, 2017 at 18:03

8 Answers 8

34
\$\begingroup\$

Generally speaking, the ease with which any system can be extended is dependant upon the degree to which its subsystems are tightly or loosely coupled. Usually, the more loosely coupled the subsystems are, the easier it is to modify them as they are isolated & don't necessarily require a complete understanding of the system as a whole.

Nothing is free though - such system typically require more resources (various combinations of time, money & skill) to build. The degree of extensibility you've described strikes me as being directly at odds with the level of skill you've attributed to yourself. It could be done, but crafting software as you've described it is a very challenging undertaking.

The closest existing things I'm aware of is Vassal (which is far more programmatic than you've described), or making a mod for Tabletop Simulator (which mostly depends human interaction to interpret & enforce any game rules).

\$\endgroup\$
2
  • \$\begingroup\$ Solid advice. I try to keep my code as loosely coupled as possible to ease extensibility, but you will always have cases where it is so much easier to hardcode/couple something. Even as a professional developer not an easy task, and definitely not novice friendly. \$\endgroup\$
    – angarg12
    Commented Sep 22, 2017 at 9:27
  • \$\begingroup\$ TTS now supports Lua and enforcing rules are not completely up to the human interactions now. \$\endgroup\$
    – ave
    Commented Sep 24, 2017 at 20:15
18
\$\begingroup\$

What I've thought about is whether it's possible/feasible to somehow implement game mechanics separately from the main utility code?

It is absolutely possible. One way used often in gaming is Lua scripting.

From the linked article:

Lua was originally designed in 1993 as a language for extending software applications to meet the increasing demand for customization at the time.

Many games use Lua. (I would link but new-user reputation is limiting my link count.)

Lua scripts can be compiled at run-time. This means they can (for example) be text files sitting in your game's "scripts" directory, easily editable by a modder. Your game loads them up and runs them.

I've seen Lua scripts define the properties of in-game units. Here is a random example from TA Spring.

But you want to "describe all the rules". That's possible in theory, as Lua is a full language, but the trouble is you have to be prescient enough to have the core game code know to look for scripts to extend its behaviour.

For instance you might develop a card game that knows to look for cards in a "scripts/cards" directory. That's great for adding new cards, or editing existing ones. But if you later want to expand your game to include miniatures on a grid you're going to have to edit the core code -- no amount of Lua fiddling is going to get you there on its own.

Please note: I bring up Lua because I know it's commonly used both in gaming and in software for customisation. I'm not suggesting it is the only solution, nor the best for the questioner's needs.

\$\endgroup\$
1
  • 7
    \$\begingroup\$ This answer implies that Lua is the only scripting language used that way. There are many other scripting languages which can be embedded in game engines. Some engines also go their own way and implement their own domain-specific scripting language. I would usually not recommend that (because building a language is a ton of work), but it should be mentioned. \$\endgroup\$
    – Philipp
    Commented Sep 22, 2017 at 10:07
3
\$\begingroup\$

There is a continuum of approaches and whether any particular one of them is worth it will depend on exactly what you are trying to do. Specifically, how much control do you want to offer the tweaker?

On the extreme end of control, you can simply let the tweaker modify the code of the entire game. At that point you would essentially be publishing the utility code and at least one example of how to use it. A tweaker could use as much or as little of the code as they want.

An approach that offers a little less control would be to somehow "freeze" your utility code (say by compiling it beforehand) and only let tweakers fill out specific functions (callbacks), restricting what they can do. Depending on what you want to do, this approach can take many forms. A common method would be to put all the display part in the utility/main code and all the mechanics in the tweakable portion. Or, you may want to keep some mechanics in the "frozen" part because players are unlikely to want to change them, or making them changeable is too complicated.

On the low-control end of the continuum is only letting tweakers change values within a fixed range. A data file which let you select the colours of things within the game would be an example. You could, however use this approach and still offer a lot of customization. It would be possible to define a selection of functions and allow tweakers to compose them to create the callbacks from the previous approach, but not allowing them to define new ones. Or maybe you skip the composition part and just offer a finite selection.

The details of all these approaches and which one fits your use case depends on what kind of base game you want to make and how much control you want to give up. Note that commercial games generally use only the second and third methods because the first allows players to make entirely separate games, which introduces complicated licensing issues. Note that as these approaches form a continuum, the second approach may introduce these issues as well.

\$\endgroup\$
3
  • \$\begingroup\$ Making it opensource is my goal, actually. What I see as a problem is how to implement this extensibility in the most easy way, so that other players of the game (which is MP game, btw) could create their own extensions of the basic set of rules, and share them with each other, somehow avoiding conflicts at the same time. So if one user develops some extension overriding certain rules, and another develops different extension, how to ensure that 3rd user who wants to use both of those in his games won't run into compatibility issues? Aside from forcing them to collaborate tightly. \$\endgroup\$
    – tis
    Commented Sep 22, 2017 at 2:45
  • \$\begingroup\$ ..and to implement it in such way which won't require modification of any utility code and thus too much knowledge about programming. \$\endgroup\$
    – tis
    Commented Sep 22, 2017 at 2:46
  • 1
    \$\begingroup\$ I don't think there would be a way to prevent compatibility problems, (even setting the colour of something can cause that!) I think the better thing to do is have a way to detect possible compatibility problems and have a nice way for users to respond. Depending on the design of the utility code interface, and the extensions in question, there may be a way to order callbacks etc. that produces the desired result. Then again, there might not be. Alerting the user that there might be problems and why seems like a better user experience than things breaking with no explanation. \$\endgroup\$
    – Ryan1729
    Commented Sep 22, 2017 at 3:09
2
\$\begingroup\$

It is absolutely possible to separate the rules of the system from the code that applies those rules. I prefer to structure my code that way for complex projects, as it makes it easier to add new rules or change the rules later without introducing bugs into the underlying system. And bugs in a rules engine get found faster than bugs in a system where the rules and other code are mixed together higgledy-piggledy, because the same rules engine gets used over and over by every rule.

Whether it is worth it depends on the complexity of the system. Like I wouldn't bother for Pac-Man, but I couldn't imagine writing Dwarf Fortress any other way.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks, @Robyn. Any reading advice to somebody who doesn't know how to even approach this design properly? Are there some well-established design patterns for such applications? Any books which cover the subject? \$\endgroup\$
    – tis
    Commented Sep 22, 2017 at 2:40
  • \$\begingroup\$ No books, sorry. But the basic idea of a simple rules engine: make a Rule class that has a property for every piece of information you need to describe a rule. If some of these properties hold lambda functions then you can assign complex behaviours to them. Make a class that instantiates a list of Rules, so all your rules are in one place. Make another class that has a method that takes a list of Rules as input and applies them to the system. \$\endgroup\$
    – Robyn
    Commented Sep 22, 2017 at 5:50
2
\$\begingroup\$

It's definitely feasible. If it's worth it depends on your goals.

You don't have to invent your own language or write a compiler to make this work.

If you want your game to be easily extendable, it's probably a good idea to go for it.

It's probably more work for you, at least short term, to create understandable systems and make things easy to modify.

One game that does this is Rimworld (I have no affiliation) and you might be able to see & learn from how they did, basically putting a lot of game data and mechanics in XML files that are in the game folders for anyone to see and modify. The core/engine of the game was made using Unity.

There is also the possibility of extending the game further/deeper by actual coding, I know less about that but you can learn by looking at the mods forum.

The possibility of modding makes the game more interesting to a lot of people and I think it has contributed a lot to its success. It also allows the developers to bring in any mod content they want into the core game and in a way, that speeds up development and improves the game since they get assistance from a lot of people, and they can decide to take in things based on what is popular, what seems to work, etc.

And of course, especially for a small independent studio, they have hundreds of people coming up with ideas and testing them for them, which is a lot of work they couldn't do themselves, nor probably hire people to do.

\$\endgroup\$
2
  • \$\begingroup\$ Though I can see how game data may be defined with xml, I can't imagine how you can use it to define game mechanics/rules. Could you provide some example/article on subject, perhaps? \$\endgroup\$
    – tis
    Commented Sep 23, 2017 at 3:58
  • \$\begingroup\$ @tis Rules are just another kind of data. If my engine has "If A do B" I can load A and B from an XML file, now users can put fairly arbitrary rules, one additional bit that can help is to provide a list with all possible As and Bs you support per se, e.g. "If status statustype then movespeed 100", "If status statustype and time >x then status statustype" So in your design think about what kinds of rules you want to allow on what kinds of objects (status, time, movespeed) and with what kinds of composition to allow (and/or, etc...). If status underwater and time >5 health -10. \$\endgroup\$
    – ttbek
    Commented Sep 23, 2017 at 16:54
1
\$\begingroup\$

You might want to look into Object-Oriented Design. Python has good support for that.

Thick books are written about this which can be scary when you are new, but the main principles are fairly easy.

The main point is just that you identify what kind of objects you are working with. You don't say what kind of game you are thinking about, but things like Player, Monster, Item, Equipment, Weapon, Armour and so on are typical objects.

If you want different game types, you will probably want a Game object that takes care of victory condition and such. Perhaps a Map object too?

Sometimes it is not clear if something deserves to be an object or not, e.g. damage. If you don't make damage an object the code will be simpler, but making it an object makes it easier to customize.

Subclassing: Both Weapons and Armours are Equipment. Equipments are Items. There are probably other types of Items. You will probably find it useful to define a class Combatant that both Players and Monsters are subclasses of.

The idea is that for example Weapons will have many things in common with all other types of Items, they have a weight, size and other properties like that.

So, subclassing gives you a way of saying that "Weapons are like other Items, but in addition you can wield them, they affect the damage you do, etc etc."

Subclassing also lets your mod builders say "My new type of weapon is just like the standard weapons except that ..."

Then you have to decide which object is responsible for what. This is not as easy as it seems and you should do some thinking about it. Making the wrong choices will not affect the basic game much, but will make it harder to customize.

As long as you are just tinkering on your own you can change things around but the moment you release something to the public, making changes becomes much harder! People will make mods that depend on things being just like they are now. Even bugs. People will write mods that depends on bugs staying in the code. If you change things, those mods will break and lynch mobs will appear at your house.

For example:

A Player wielding a Weapon attacks a Monster wearing multiple Armours. This takes place in a particular Game mode and on a certain Map.

Both Combatant may have Skills like Critical Hit and Dodge.

Now, which object is responsible for what?

There is not one right answer to this. A lot depends on what kind of customization you want to allow.

If you never call an object (e.g. the Map), that object cannot change the attack in any way.

After making all these decisions, document them. Write a "Modders manual" that lists exactly what moddable methods each object has, what parameters they take, what they should return, and so on and on and on...

Good luck!

\$\endgroup\$
3
  • \$\begingroup\$ Your input is really appreciated, and you put a lot of efforts in it, so it's definitely worth a +1, but I'm happen to be aware about OOP, in general (though lack experience in it). My current issues is with most general design approach I should take. My game is not something as huge as D&D by scale, yet it's VERY deep in its mechanics nonetheless. That means a lot of complex, intermingled on different levels rules. Which I would like to allow users to extend significantly, not only slightly tweak some values. It may be there is no easier solution, indeed.. \$\endgroup\$
    – tis
    Commented Sep 23, 2017 at 4:01
  • \$\begingroup\$ @tis The key to this is making the correct decision about what are really the objects in your OO model of the game. The "obvious" place to start is with the "nouns" like weapon, armour, etc is not the only way,and it can lead to a tangled mess of uncustomisable code. If a rule says "you an only shoot some monsters with silver bullets in a churchyard at midnight" where do you enforce that rule in the code? In the Gun (or Bullet) class, in the Monster class, in the Fighter class of the gun-user, in the Churchyard class, or in the Time class? The best answer might be "none of the above" ... \$\endgroup\$
    – alephzero
    Commented Sep 23, 2017 at 4:25
  • \$\begingroup\$ ... and rethink the whole design in terms of a Rules class (which is probably really a database) and a Conflict Resolution class. Now, other rules like "if you have no bullets, you can still use your gun as a club" and "if Alice casts a spell that partially (but not completely) protects Bob against bullet wounds, while Charlie is trying to shoot Bob, then ...." have an single, and "obvious," place to be implemented in the code. You may find that your original Gun class now does very little, except produce some audio-visual effects - and not even that, if it is a text-based game! \$\endgroup\$
    – alephzero
    Commented Sep 23, 2017 at 4:29
1
\$\begingroup\$

A simple way to get some basic support for this would be to separate most numerical values into one or more separate text files to allow interested individuals to tweak them into oblivion.

For example, you mentioned tabletop games; if you had a game based on D&D you might have a weapon_damage file containing lines like Battleaxe: 1d12. Your utility code would read that file and whenever damage was dealt by a Battleaxe your code would generate a number from 1-12, 1 time(s) and add them. Tweaking the line to read Battleaxe: 4d6 would instead generate a number from 1-6, 4 time(s) and add them. Similarly, you could have a folder Creatures and inside you have a file for each creature, including lines like AC: 12; then adding new files to that folder would create new creatures. It could even be done for character classes, terrain types, a ton of things.

This style of non-code customization can still be very powerful and cover a lot of pieces of your game. However, this doesn't really allow a user to make changes that you didn't explicitly specify. For example, you might enable Sneak Attack: [damage] to be given to any Creature or Class to add [damage] to any attack that meets the conditions for a Sneak Attack. You could even provide ways to change what the conditions are, such as "whenever you attack from stealth" or "whenever you are flanking" or "whenever you have advantage". However, if a user decides that they want sneak attacks to be "When you make an attack roll, you can also roll stealth against the target's perception. If both rolls succeed, then add the Sneak Attack damage" then the user is out of luck unless you predicted that exact scenario.

If you wanted a user to be able to add completely new behavior to the game without needing coding skills at the same level as the developer, then as people mentioned you're looking at essentially creating either a game engine or a separate programming language. For modifications that don't require coding knowledge, text-based data files and folder structures can still provide a lot of options. If you want users to modify more than that then you'll need to ask them to learn or know a programming language.

\$\endgroup\$
2
  • \$\begingroup\$ Yes, I need to allow them to add new mechanics as well, just tweaking some values won't do. I also thought this may need a separate language, I just thought may be there is already one which I can employ in my Python utility code. \$\endgroup\$
    – tis
    Commented Sep 23, 2017 at 4:13
  • \$\begingroup\$ @tis Have you considered what Wikipedia has on the topic yet? en.wikipedia.org/wiki/Logic_programming \$\endgroup\$
    – ttbek
    Commented Sep 23, 2017 at 16:36
0
\$\begingroup\$

[I'm a decades-long software developer, but with no game development experience, so maybe the games industry takes different approaches, maybe for good reasons...]

Your approach absolutely makes sense to me. The core gives the basic functionalities that mechanics and rules build upon, so it's an API that is to be used by the higher-level components.

And when designing an API, my favorite guideline is to create the language that you want to express your higher level code in (of course, withing the syntax limitations of your programming language).

So, a good approach would be to write some hypothetical rules and mechanics just the way you'd like them to be expressed (withing Python's syntax, of course), thus finding out what you want the core API to provide to the rules and mechanics layers.

And of course, I'd recommend to have a look at the scripting facilities of existing games to get an idea what they do.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .