6

I'm designing a programming language for a game, to be used as the main way of interacting with the game, as opposed to using other methods of control, such as the arrow keys or mouse. My plan is to have the user control game objects through objects in the language.

if unit1.health > 20 {

    unit1.attack(Enemies.enemy1)

}

Where unit1 and enemy1 are the objects. This can be done relatively easily, however, I would also like the language that the user interacts with to be an actual language, and for the game objects like unit1 to behave similarly to objects created by the user.

I don't plan on adding classes or something similar. All attributes of an object are public by default and read-only, and methods are just attributes that are function objects. You also can't add attributes to an object. The only time the user can access the innards of an object is upon creation, as this is necessary to restrict the user from changing game objects.

Is there any way to add a feature to the language that allows the user to do something like inheritance or something that allows easily writing complex code, while still keeping the language "pure" and simple?

Right now, the most you can do is something like:

fake_class = function(x, y) {
    {
        self.x = x
        self.y = y
        z = "hi" // private
        self.change_x_and_print_z = function(new) {
                                        self.x = new
                                        print(z)
                                    }
    }
}

new_obj = fake_class(4, 5)

But I can think of any way to extend the object, as it is read-only and only mutable from within itself.

6
  • This sounds like something unholy to debug Commented Dec 16, 2017 at 3:50
  • @whatsisname, maybe, but it's just a proof of concept mainly, and literally a toy language to control a game. Maybe debugging can be built using the language itself. I have a rudimentary "Type System" so far.
    – Vityou
    Commented Dec 16, 2017 at 5:01
  • Why are you designing a language? If you want to write a game, write the game. Embed Lua, JavaScript, Python, or whatever in your game. Then you don't have to waste time writing a language that isn't as good as those languages, and your players don't have to waste time learning a language that they can't use anywhere else. (If you are designing a language because you want to design a language, that's fine, but then the likelihood of your game ever getting finished is very low.) Commented Dec 16, 2017 at 9:04
  • @Sebastian RedI, you're right, I like building systems for the sake of building them, however, I couldn't find a language that didn't have any undesirable features, many of them allowed users to work around "enforced" features, JS has the delete operator same with python and lua...
    – Vityou
    Commented Dec 16, 2017 at 15:34
  • @Vityou, if you embed another language you can just implement these objects in your host language and easily avoid the ability of the client language to manipulate them outside of your api. However, I'll note that I would really expect a game to have its own language. Commented Dec 16, 2017 at 17:34

2 Answers 2

6

Make it possible to create a new object as a clone of an existing object with new properties.

So for example:

function Base() {
    z = 5
    return {
       x: 2,
       y: 4,
       print_z: function() {
           print(z)
       }
    }
}

function Child() {
     return {
         ...Base(), // start with copy of base
         g: 5,
         h: 3, // add my own stuff
     }
}
6
  • So I would have to give the user a copy function that essentially unpacks the contents of the object? eg {copy(Base())} is equivalent to Base(). Would this behave well with built-in game objects like unit1?
    – Vityou
    Commented Dec 16, 2017 at 2:56
  • @Vityou, that depends on what you mean by "behaves well". Commented Dec 16, 2017 at 3:12
  • I answered my question while I was writing it, but for those who want to know, it was "I mean, since the game objects like unit1 would be injected into the global environment during the game, and since they have methods that do things externally in the actual game, would copying unit1 for example let the user has access to anything they shouldn't?", But I don't see any reason that it would do anything like that.
    – Vityou
    Commented Dec 16, 2017 at 3:41
  • I noticed that this approach would not work well with private attributes, as the user could access them by making a copy of an object, and adding a method that returns the value of a private attribute. Is there any way to deal with this?
    – Vityou
    Commented Dec 17, 2017 at 6:11
  • I was thinking like the javascript model where the "private" attributes are actually variables in a closure. They aren't actually attributes on the object at all, but exist in a shared state only accessible to the functions defined there. When you create a copy of the object, you copy these functions but they still refer to the original closure. Commented Dec 17, 2017 at 6:59
3

There are several alternatives to class-based inheritance that have already been explored

  • Prototype Delegation: objects can have one or more special references to other objects. When an object does not understand a message, the message is forwarded to the objects referenced by those special references. Some of the first languages that explored this idea were Self and Act-1, the first commercial one was NewtonScript, and the most famous one is ECMAScript. Design decisions are: single (ECMAScript) or multiple (Self) delegation, and whether or not those references are "magical" (ECMAScript) or just regular fields that you can assign to at will (Self).

  • Mixin Inheritance: Mixins can be thought of as "classes parameterized over their superclass" or as "composable bags of methods".

  • Trait Composition: Traits are kind-of like Mixins with declared dependencies and conflict resolution (e.g. Method Hiding and Renaming).

The most simple one of these, conceptually, is Prototype Delegation. It is also the one the users will most likely be familiar with, if they have dabbled in web programming.

In Self, prototypes are just regular fields whose name ends with an asterisk *. Messages are re-sent to the fields in alphabetical order, until either someone answers or a doesNotUnderstand: message is generated, which then again follows the same lookup rules. If the doesNotUnderstand: message also is not answered, a NoMethodFoundError exception is raised.

Since prototypes are just regular fields, you can create, delete, and re-assign them at will, just like every other field.

3
  • I would like for the child object to have access to a copy of the parent's private variables, it doesn't seem like this is possible in any of these methods.
    – Vityou
    Commented Dec 16, 2017 at 15:40
  • It is possible if you make it possible. It depends how you implement it. Commented Dec 16, 2017 at 18:21
  • Yes, but that includes more "magic" on the user side than a simple copy function. I don't believe a field behaving as something more than a field is intuitive.
    – Vityou
    Commented Dec 16, 2017 at 18:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.