The Dink Network

Dink with Lua scripting

December 16th 2013, 03:32 PM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
Hi, everybody!

Man, I can't believe how active this place still is, for being so old. Well done. I'm also kind of surprised at how active some of the old veteran Dinkers are. Just having looked through some of the latest forum threads, I recognize a lot of usernames from the old days still being present. Hello Kyle, scratcher, magicman and SabreTrout, among others!

For those of you who are now asking yourselves "Who is this guy?" I am Phoenix (real name Alex). I was very active in the Dink community from about 1999 to sometime in the mid to late 2000s, when I more or less lost all interest in anything Dink-related. This place still holds a very special place in my heart, though, and I always find myself coming back. Sooner or later, no matter how long I go, I will probably always be coming back.

So, at this point, you're probably wondering what the title of this post means, and why I'm talking about all this other stuff instead of the topic of the title. Well, I figured that since it has literally been years since I was last here, it was appropriate for me to re-introduce myself. Anyway, let us get to the topic at hand!

First and foremost, in case you don't know; what is Lua? Lua is a scripting language. Not that DinkC isn't, except that Lua is a proper, full-fledged, full-featured scripting language, whereas DinkC is more of a... thrown-together text interpreter doohickey, with a bunch of strange quirks.

Second, why am I talking about Dink and Lua in the same sentence? Well, this is where it gets interesting. You see, I'm currently on vacation, and when I'm on vacation, I tend to get a bit bored. When I get bored, I tend to want to have something interesting to do. In recent years, I've kind of fallen in love with the scripting language Lua. I don't know quite what it is, but I just love that language a lot. One of the greatest things about Lua is that it's more or less intended as a scripting language in other projects. It comes ready to use as a C library, to be integrated into your programming projects at will. Now, having been thinking about Dink recently and having such an affinity for Lua, it was only a matter of time before my mind decided it was time to wed the two ideas. I'm bringing Lua to Dink. Sorta.

I will be adding this feature to my own personal fork of the GNU FreeDink project. This probably means that my code won't ever be part of the official Dink game, but that's all right, I'm not really expecting this to take off or anything. To be honest, I'm doing this more for myself than for any other reason.

Okay, so, what would the consequences of adding Lua to Dink be? There are four major features that personally get me excited, but I'm sure there's more awesomeness that comes along with it. So, here they are:

1) Object orientation

Lua supports object orientation. I will make full use of this. Here's a snippet of how DinkLua code might look (this is Dink's start-1 script converted into Lua):

local crap

function buttonon()
  current_sprite.pframe = 2
  dinkc.playsound(20, 22050, 0, nil, false)
  crap = dinkc.create_sprite(204, 86, 0, 199, 1)
  crap.reverse = false
  crap.noclip = true
  crap.seq = 199
end

function buttonoff()
  current_sprite.pframe = 1
  dinkc.playsound(21, 22050, 0, nil, false)
  crap.reverse = true
  crap.seq = 199
  crap.brain = brain.KILL_SEQ_DONE
end


As you can see, create_sprite returns a sprite object rather than a sprite number, and you can operate on this sprite object in an intuitive way, which is to say, you can set its properties directly, rather than having to call functions with the sprite number as a parameter.

2) Proper variables and variable manipulation

DinkC variables are basically a cheap hack. They can only really store numbers. With Lua, you get variables that can store anything Lua and its Dink integration will support. You can store text, numbers, tables, objects, even function "pointers." I'd elaborate more, but just let that sink in and let your imagination run wild.

local start = "This is"
local middle = " all part of "
local end = "one sentence!"

-- Two dots is the concatenation operator in Lua; it combines two strings into one.
start = start..middle

-- Assume "sprite" here is a sprite object, as mentioned previously.
-- This would have the sprite say "This is all part of one sentence!"
sprite ay(start..end)


3) Real functions, with real parameters and real return values

Yes, indeed. DinkC has a pathetic function support, and in most cases, it's best just left alone. With Lua comes full-fledged function support. Cleaner scripts and helper functions, anyone? Lua functions are also fun in that they allow multiple return values.

4) File includes

Helper functions would be kind of useless if you'd have to put them over and over again in every file. So, an obvious addition is to add support for file includes. Typical usage would go something like this:

local helpers = include("helpers")

function main()
  heart = helpers.create_heart(345, 123) -- x and y coords, e.g.
end


Awesome, right? So, how close am I to completion? Well, before writing this post, I made sure to implement a proof-of-concept version, just to make sure I could accomplish this project. It went superbly, so now I've started the more elaborate and daunting task of adding Lua support proper. I'm currently rewriting the Dink scripting system in such a way that DinkC is just another scripting language to the Dink engine. In fact, if you wanted to, after I'm done, you could compile my version of Dink without DinkC support. Not sure that's ever a good idea, but that's how detached I want DinkC to be. Why? Because for one, it will make the Lua integration cleaner (and to be honest, the DinkC integration will become cleaner too), and second, because it will make adding any scripting language to Dink equally clean (and a lot easier).

I'm mostly writing this post to have some accountability on me, in such a way that I have sort of promised to do this to someone, and can't back out as easily. Feel free to come with reactions, comments, questions, what have you. I will make sure to return to this post frequently to reply to them.
December 16th 2013, 03:39 PM
custom_coco.gif
Cocomonkey
Bard He/Him United States
Please Cindy, say the whole name each time. 
Hi Alex. I was around in the old days too.

Indeed, DinkC is well-known to be a train wreck, and when things work it's practically by accident. I can think of several things I'd have done in my new DMOD if I could store strings in a variable.

The problem, of course, is that hardly anybody's going to mess around with a "fork" of Dink. I think this is a great idea, but I'm also pretty sure people are going to stick to the main version. Still, I know very well what you mean when you say you're doing it for yourself, and I totally respect that.
December 16th 2013, 03:49 PM
dinkdead.gif
Hi Phoenix, long time no see

This sounds amazing, good luck with it.

The only issue I can see with this actually being used is that D-Mods made with Lua would have to be played on your engine, whereas a 'normal' D-Mod can be played on any engine (this also holds true for D-Mods created with Shevek's editor - even though you can use a better scripting language while coding it is still compiled into regular DinkC).

I don't know that DinkC's function support is all that pathetic... Sure there's some weirdness going on when you try and work out whether it's actually running as a separate script number or not but that's usually irrelevant and they seem to work just fine, whether it's local functions or something like external(). I use them extensively.
Apart from that... *drool*
December 16th 2013, 04:09 PM
custom_iplaydink.gif
iplaydink
Peasant He/Him Sweden
Hmm.. 
This sounds very interesting, I too love lua and I think it'd work great as a scripting language for dmods! I'm really sick of dinkC.. >_>
December 16th 2013, 07:25 PM
spike.gif
Ah, I knew you were up to something when I saw your avatar popping up and out down there. I also like your new tag over the super depressing one.

This project sounds very cool. I know a little bit of Lua through dabbling with other things that use it, and with that in mind I find the idea of using it for Dink doubly appealing; Lua is used everywhere, so you can't go wrong by learning it.

After the luck runs out, I wish you perseverance!
December 16th 2013, 09:23 PM
peasantmb.gif
yeoldetoast
Peasant They/Them Australia
LOOK UPON MY DEFORMED FACE! 
Awesome. I can't wait.

> The problem, of course, is that hardly anybody's going to mess around with a "fork" of Dink. I think this is a great idea, but I'm also pretty sure people are going to stick to the main version.

I would contest that. Look at how many people still use Aural+, and how often Dink 1.09 is derided. Even so, we'll be a good audience for messing around with it.
December 16th 2013, 11:11 PM
custom_coco.gif
Cocomonkey
Bard He/Him United States
Please Cindy, say the whole name each time. 
What I really meant was a fork that would break DMOD compatibility.

Never mind me.
December 17th 2013, 02:34 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
> Indeed, DinkC is well-known to be a train wreck, and when things work it's practically by accident. I can think of several things I'd have done in my new DMOD if I could store strings in a variable.

The utility might be a little limited in that Dink doesn't really allow for string inputs, at least not directly. I'm contemplating adding a function for that in the Lua version, or people could go crazy with choice menus and whatnot. I recall there being a DMOD that actually managed to support string input using only DinkC and its variables. Doing something like that in the Lua version should be a lot easier.

> I'm also pretty sure people are going to stick to the main version. Still, I know very well what you mean when you say you're doing it for yourself, and I totally respect that.

Right, as I said, I'm not expecting this to take over or anything. Honestly, I'm hoping mostly to be able to place it as a bragging item in my portfolio when looking for my next job, haha. If anyone else gets even a smidge of enjoyment out of the end-result, that's awesome too.

I will (do my best to) release it in binary form for Windows users, so they won't have to deal with compiling software and such. Assuming I don't do anything too crazy in my code, GNU FreeDink is already cross-platform, so I hope mine will be too.

> The only issue I can see with this actually being used is that D-Mods made with Lua would have to be played on your engine, whereas a 'normal' D-Mod can be played on any engine (this also holds true for D-Mods created with Shevek's editor - even though you can use a better scripting language while coding it is still compiled into regular DinkC).

Well, yes. This won't be backwards compatible by any means. However, as I mentioned, I will provide a binary for the Windows folk, and assuming someone makes a really good DMOD with my Lua version, it shouldn't be all that much work for others to download it for that purpose.

> I don't know that DinkC's function support is all that pathetic...

Yeah, to be honest I've not really looked very much into it from a practical viewpoint... but from what I've read about it, and from how I see it work in the Dink source code... I can't really say it's all that great. Especially not when compared to real programming and scripting languages.

> I also like your new tag over the super depressing one.

Heh, hell knows what that one was about. But my current one fits my username and my return.

> I wish you perseverance!

Thank you sir!
December 17th 2013, 11:21 AM
dragon.gif
Quiztis
Peasant He/Him Sweden bloop
Life? What's that? Can I download it?! 
Hello there old-timer Phoenix. A change from DinkC why not?
December 17th 2013, 11:18 PM
peasantm.gif
shevek
Peasant They/Them Netherlands
Never be afraid to ask, but don't demand an answer 
Very cool. I decided to go for preprocessing sane code into DinkC, because of compatibility. But I fully agree that using a real language would be better. I'm just not sure if people will download a new engine for it.
December 18th 2013, 05:24 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
Yeah, I'm not really expecting this thing to go anywhere. Mostly I'm doing this whole project for my own amusement. I just figured I would share it too, since doing something like this just for yourself isn't all that rewarding.

Being that I haven't been around here for years, it's not odd that I've completely missed your project. It sounds interesting, I'll make sure to have a look at it. The problem, of course, with preprocessing into DinkC is that you're ultimately left with no more features than what can be accomplished with DinkC at the end of the day. Back when I was working on a version 2 of my EasyDinkC editor, I added in lots of features that basically amounted to the same thing; the editor had a clever scripting language that would "compile" into DinkC at the end of the day. I never finished the thing, though, and I don't even know if I've got the source code anymore.

I'm going to try my best to make it easy for people to use my extended engine, to ease some of the pain of using it.
December 18th 2013, 05:44 AM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
Omg I'm gone for two days and the bird rises from the ashes in my abscence! Glad to see you back among us Phoenix! The memoriez!

As for your project, I'm totally on board with this! As many people here probably already know, I don't care much about backwards compatibility. It's nice in a perfect world, but I think it's time to move on from the limitations of the past and evolve past them.

I looked over your feature list three times just to make sure my drooling was justified, and it was! Sure, for very simple scripts it might not make much sense to swap to LUA compared to normal DinkC. But, for new bigger things like a remodeled UI or new battle systems, it's a huge blessing. Yes, there will be a learning curve for those of us not familiar with LUA syntax (like me), but what better motivator to learn than through our favorite little cult game?

A couple of questions... You're rebuilding variables. Does this mean it somehow bypasses other limitations inherent to variables like the concurrent variable limit? I realize it won't touch the global variable limit because that's a save file limitation.

Second, in the example code you're using a non predefined sprite graphic to say a line. Does this mean the sprite loading is also changed? It seems, by your example, that it would be possible to bypass the sequence limit, or forget about it altogether for sprites that are not placed in the editor? What about the hardness for such sprites?

And last but not least, thanks for doing this man! It's not just great to see you back, but for you to be working on something new altogether is exciting!

Btw, Shevek, don't let it steal your thunder either As far as I understand, Phoenix isn't writing a new editor and the whole thing won't have backward compatibility, unlike yours. And we're still in dire need of an upgrade to WDE+, so keep working at that!^^ I must say I appreciate Phoenix' willingness to compile it himself for Windows users though!
December 18th 2013, 07:13 AM
custom_iplaydink.gif
iplaydink
Peasant He/Him Sweden
Hmm.. 
I really don't think people mind keeping ,multiple versions of dink on their computers, many of us already do!
December 18th 2013, 09:35 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
The memoriez! indeed! I have pretty much nothing but great memories from this place. It's what keeps me coming back.

I'm glad to have somebody fully on board! It's great to have someone else than myself psyched for this project. My engine will be backwards compatible in that it will still be able to play all the old dmods, (at least to the extent that FreeDink already is able to) but not the other way around. In any case, yeah, we can't always let ourselves be held back by past limitations. Dink was never intended to run on Linux, and yet, today, we can.

Lua is incredibly simple and elegant. I will be writing some documentation along with my changes, like a small "Introduction to Lua for DinkC users" or whatever, just to get people started, as well as do my best to document all the differences between the two, so that if you know how to do something in DinkC, and accomplishing it is different in Lua, you should be able to go look that difference up somewhere.

I'm not really rebuilding variables, I'm just letting Lua deal with local variables instead of letting Dink deal with them. What that means is that, yes, there is no longer a variable limit on local variables. Have as many as you want in as many concurrent scripts as you want (limited, of course, by the memory limits of your computer). Global variables will be limited the same way they are today, and they will only be able to store integer values, as per today's limitations.

This actually lets me gracefully segue into a topic that I think requires a lot of discussion/thought.

Accessing the Dink globals will probably be done through an object aptly named "global" so that accessing the Dink variable &life from Lua will be done through doing "global.life". However, Lua also supports the idea of global variables, i.e. variables that can be accessed from multiple scripts... but just letting that happen isn't automatically the best idea. I'll explain why.

In my proof-of-concept implementation, each script is entirely separated (sandboxed) from every other script, in such a way that one script's globals cannot be seen from another script. The reason I did it this way is because DinkC users will be used to just creating a file and putting in some functions, and doing so places these functions in the global namespace in Lua, meaning that if they shared their environment, you couldn't have two scripts that both have a "main" function, because there would be a scope naming conflict.

So then, the question is, should I aim for DinkC-likeness, and just have the functions be global and the scripts be completely separated, or should I start a new scripting convention with Lua, that runs all the scripts in the same sandbox environment, rather than in separate sandbox environments, so they can share variables? Doing the latter will require scriptwriters to think to think a little differently about how to implement script functions like main, hit, talk, etc., because as I mentioned, they would interfere with each other if they were all global functions.

But wait, there are many more potential problems! If people aren't careful about using local variables rather than global, you'll quickly end up with a rather polluted (and eventually possibly memory consuming) pool of global variables from scripts that were long since killed off. Also, these variables would not be saved between saving and loading a game, so they cannot be used as reliably as the Dink variables, which do get saved to disk. All in all, I'm not sure it's worth the hassle to support this.

A different option would be to offer a mechanism similar to the global object of accessing Dink variables for Lua variables, and thus letting scripts be DinkC-like, and safely create global variables at will, without risking name conflicts or undesirable memory consumption.

Oh, no, it's not a sprite graphic, it's a sprite object. Probably a bad name choice; in Dink the word "sprite" is often used about the game objects as well, such as in "&current_sprite;" or attaching something to "sprite 1000". Yeah, no, you load sprite graphics as before. I just used it as an example game object, presumably defined previously in the script somewhere.

Heh, well, I assume that if I don't provide Windows binaries for my project, then effectively nobody will be using it. After all, compiling software isn't very commonplace in Windows.
December 18th 2013, 10:39 AM
peasantm.gif
shevek
Peasant They/Them Netherlands
Never be afraid to ask, but don't demand an answer 
I'm glad to have somebody fully on board!

Count me on board as well! I think this is a great project.

But don't worry Kyle, I won't abandon my editor. Instead, when this starts working, I will probably add support for it. I'd just need to write a lua syntax parser (so I can replace sprite names with their editor_num, for example), which should be easy; lua is a very simple language. Actually, I might also cheat and just generate a table at the start of each script, which can then be used by the script. Oh, the joy of having a real language.

Oh, no, it's not a sprite graphic, it's a sprite object.

I think the confusion stems from this website, which inserted html code for a smiley in place of the : followed by s. It should be (space added to avoid the problem):
sprite: say (...)


The : is lua's way of calling a member function, similar to what would be sprite.say in C++ (more precisely: lua does not automatically pass the "this" argument to a member function; object:function (args) is just syntactic sugar for object.function (object, args)).

As for the variables: please encourage good programming. That means as little global variables as possible. So I would definitely go for one sandbox per script. This is also pretty much requried, as you mention, for garbage collection to work.

On the other hand, object globals will be very useful as well. So if you can create an interface for those (for example a table named "volatile" (or perhaps better "v", because using it should be easy), which is shared between all sandboxes) that would be awesome. It can be used for loading functions which you don't want to include explicitly, for tables of strings, that sort of thing. The reason I'm thinking of it is that my editor uses names instead of numbers for sequences (and many other things), and it currently does the translation between them in the preprocessor. However, it would be nice if this could be done without parsing the lua code. Generating a table for them is easy, but it's a large table, and I wouldn't want to define it at the start of every script. It cannot be hardcoded, because it depends on which graphics are loaded through dink.ini.

My engine will be backwards compatible in that it will still be able to play all the old dmods, (at least to the extent that FreeDink already is able to) but not the other way around.

So I have a feature request: please add an interface to create new brain functions. They will need to be registered with a number, or they cannot be saved. My idea is to have an array of brains, which is initially filled with the default brains, but which can be altered by the DMod. So you can say brains[25] = function ... end. This interface needs some documentation, because nobody knows what a brain function should do.

Heh, well, I assume that if I don't provide Windows binaries for my project, then effectively nobody will be using it.

That's what I thought, too, but I have several times tried to compile things on or for Windows and I don't think it ever worked. I'm done with it; it makes me frustrated and I don't want that. If Windows users want good software, let them use a different OS. It's their problem, let them solve it. This is one reason I'm writing my editor in Python; Windows users can run it without me compiling it for them.
December 20th 2013, 10:01 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
I'm currently rewriting the Dink scripting system in such a way that DinkC is just another scripting language to the Dink engine. In fact, if you wanted to, after I'm done, you could compile my version of Dink without DinkC support. Not sure that's ever a good idea, but that's how detached I want DinkC to be.

So, for those of you interested/following along, I have now completed this step. I can now compile Dink without DinkC support (rather crazy, and without the added Lua support, absolutely NOTHING happens when you start Dink), and DinkC is now just another script engine in the Dink engine.

This broke my initial proof-of-concept Lua support, which was to be expected. After all, the way I put the Lua support in was rather fragile and hacky.

Next up is to implement Lua support properly. We're getting somewhere fast.
December 20th 2013, 04:31 PM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
Sorry for not replying to you sooner, shevek. When I first noticed your reply, I didn't have time, and then I just forgot about it after that.

Thanks for being on board! That makes us three explicitly interested parties, so far. I haven't taken the time to look at your editor yet (I've been to entrenched in my Dink/Lua coding), but yeah, adding support for Lua into your editor shouldn't be much of a hassle.

Yeah, I noticed that issue in my example code, I just didn't feel like fixing it. Ultimately, it's the forum's fault for interpreting emoticons within code blocks.

Aye, after giving it some more thought (including your input) I've decided to completely sandbox each script, and add a mechanism like your suggested "volatile" to allow the Lua scripts to communicate. I'm probably going to name it volatile and not v, as I like descriptive names. However, if you'd like to use it as v, it wouldn't take more than a simple "local v = volatile" at the top of your scripts to have a shortcut handy.

As for your brain idea, that would be something I'd add after I've done everything else. At least initially, I simply want this project to be Dink with Lua, without changing too much of how the underlying Dink works.

If I were going to write a new game, I'd probably not go with C, but since Dink is already a C game, converting it into anything else would be quite the undertaking at this point. Not that it's entirely impossible, but... I'm going to stick with C and find some way, some how, to get it to work in Windows.
December 26th 2013, 12:33 PM
slimeb.gif
DaVince
Peasant He/Him Netherlands
Olde Time Dinkere 
Wow... I can't believe how many of you I still remember. Phoenix linked me here (we still keep in touch) and I must say that this project looks promising.

But speaking of forks... Why couldn't this be merged back into FreeDink's main branch once it's all done and completed? Phoenix mentioned this could support more than one language, so why not several at once? That solves that issue, at least.
December 26th 2013, 01:56 PM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
DaVince! Glad to see you back too, even if it's just for a while (hopefully longer ).

I'm glad to see this project advancing. I've learned to be cautious with my enthousiasm because there have been too many cases of such projects dwindling down and eventually getting abandoned. Having said that... I'm pretty excited
December 27th 2013, 10:38 PM
custom_robj.png
Robj
Jester He/Him Australia
You feed the madness, and it feeds on you. 
This is an awesome project you've got here Phoenix, I am behind you all the way.
December 28th 2013, 07:04 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
The merge back into the official GNU FreeDink is up the Beuc, the maintainer of that version. If he's willing to do it, I'm not saying no, but it's not up to me.

The project is still going strong (slowed down during Christmas, for obvious reasons) but I've currently implemented most of DinkC in Lua, save for a few details and very weird features, like the choice menu, which I am working on now.

After that, I'm going to re-implement the original Dink game in Lua, and make sure I can play the whole thing through using Lua only, which should ensure at least a minimum of feature-compatibility and feature-completeness. After that, I'm going to do my best to build and release a Windows executable for those interested in trying out my engine. I'll obviously let you all know when that time comes.
December 30th 2013, 03:49 PM
farmer.gif
Beuc
Peasant He/Him France
 
Hi,

Adding Lua support sounds like a good idea.
(@DaVince ... but supporting several new languages sounds like a maintenance nightmare!)

When Phoenix told me about his experiment, I said it could be a nice addition to FreeDink, but it requires a lot of automated tests on the code.
Currently any tiny change in the DinkC engine may cause a D-Mod to mysteriously fail, so we need to detect these regressions more efficiently. All the more if the DinkC engine is modified/isolated when adding Lua support.

Also it would be nice to have versioning statement in the D-Mods, so that FreeDink would automatically know what version of the Dink engine or script engine the D-Mod was made for (as opposed to: having the user guess whether the D-Mod should be played with 1.07 or 1.08 or ...).

Btw, I don't like conditionally compiling with/without DinkC/Lua/etc. It's already a hassle to make sure people get the right Dink engine, so let avoid *variants* of the engine (imagine: - "I've got FreeDink already, shouldn't it work??" - "Oh, but your version of FreeDink is compiled with feature X enabled and feature Y disabled, while my D-Mod works with the opposite config!" - "Arrrrghhhh!!").
I made a conscious effort to make every FreeDink feature available 100% of the time, or never. This is particularly vital for GNU/Linux where every distribution tend to compile things their own way.

I'm currently dealing with several changes in my personal life, so I don't have much time on my hands right now, but I'll try and keep an eye on the thread
December 31st 2013, 03:31 AM
pq_knight.gif
ExDeathEvn
Peasant He/Him New Zealand rumble
"Skinny Legend" 
I am most intrigued by this idea, particularly after my Minecraft endeavours regarding mods like Computercraft which also use Lua Script, so I dabbled in it a little bit recently myself and plan to keep looking at it.

Looking forward to seeing your progress!
December 31st 2013, 05:48 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
Right, so I have not yet added these automated tests. While I agree with you in principle about the importance of them, I was more eager to have something working than I was with making sure everything worked right in a backwards-compatible manner. Obviously, this will most likely slow down adoption of my feature into the official FreeDink (if ever), but it doesn't mean it's entirely undoable. I am unfortunately not familiar enough with all the oddities of DinkC to feel entirely qualified to write these tests, as I don't know what strange edge cases need to be tested.

That being said, I tried making as minimal changes to the DinkC code as I could. In particular, the DinkC parsing code is entirely untouched, as is most of DinkC binding code. However, I have done some refactoring with the more complicated binding code, like playmidi, which basically amounts to avoiding repetition of the same code in the two language's bindings. The largest changes were made to the code that deals with loading, running, resuming and killing scripts, since how that is done differs in the different scripting engines. Again, however, I tried making the changes as minimal as possible.

I completely agree with the versioning support. It should definitely be possible for a dmod to know whether it can run on the current engine or not. However, since the current one doesn't really have any such mechanism, apart from get_version(), which will only work in DinkC (so a Lua dmod wouldn't even run at all on that engine, obviously) I'm not sure how useful it will be in protecting "new" type dmods from "old" type engines. In fact, I don't think this versioning should be a script at all, because if a newer version has a different scripting engine than previous versions, then their scripts won't even be possible to run. Perhaps a better choice is to use a declarative file (maybe even dmod.diz?) for this purpose.

The Lua scripting has been coded for 1.08 mode only. If you run it with the 1.07 compatibility mode, the Lua engine turns itself off. I did that mostly so I don't have to deal with stuff that is only in place to make existing dmods work in the first place.

Yeah, I get what you're saying about the conditional compilation. Mostly I wanted it to make sure that even when I completely disabled DinkC, Lua would still work, and the other way around, i.e. the two engines aren't interfering/interacting with each other. I also wanted it to be able to run a dmod that has mixed scripts, but only load one particular type of script... I do this when I'm re-writing Dink so that it doesn't load the existing scripts, letting me know which scripts I have to convert next.

I'm thinking instead of making them compile-time conditional, I'll make the engines run-time conditional. So you can run Dink with something like "--disable-dinkc" and "--disable-lua" to get the same effect, but not miss out on the feature itself in the application.

I'll keep updating the thread when new things are happening. Currently, as I said, I'm just re-implementing Dink in Lua for testing purposes (and to serve as a reference source for people who want to get into Dink Lua coding to look through).
December 31st 2013, 11:32 AM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
I think it's a good idea if you (for now) stick to your original scope. Growing it into something more than the original idea will jeapordize the project before it has had a chance to prove its merit. Let's get something working into people's hands and see what the requests are then
December 31st 2013, 01:04 PM
farmer.gif
beuc
Peasant He/Him France
 
Implementing regression tests early in the development gains time - so this will actually make adoption faster, not slower
Plus we don't want to create a new DinkC that so easily breaks

I would suggest avoiding doing clean-ups and new features on the same code branch. Good practice is to make independent branch for each major change, so they can be reviewed and integrated independently - especially if I implement in the near future a few changes I have on my mind that may conflict with yours.
December 31st 2013, 01:41 PM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
Implementing regression tests early in the development gains time - so this will actually make adoption faster, not slower

Well I have absolutely no insight in how these tests function, so I'll take your word for it

Plus we don't want to create a new DinkC that so easily breaks

True!^^
January 27th 2014, 03:21 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
I apologize for the lack of updates. My vacation has finished, and the time I have to work on this project has greatly diminished. That being said, I'm not done, so don't lose hope, if you were waiting for me to finish.

As a treat for the impatient, why don't I demonstrate how I've dealt with choice menus? The choice menu is the strangest construct in DinkC, it doesn't follow the rules of any other programing language I've ever seen. Because of its odd structure, I cannot directly replicate it in Lua. Just a reminder of how choice menus work in DinkC first:

choice_start(); 
set_y 240 
set_title_color 15 
title_start(); 
This is the title
title_end(); 
"Choice 1" 
(&cow > 1) (&sheep < 5) "Choice 2" 
"Choice 3" 
choice_end();

if (&result == 1)
{
  // Do "Choice 1" stuff
}
// etc.


If you're a fan of that structure, the way you can imitate that the most in Lua goes like this:

local choice_menu = dink.create_choice_menu({
"Choice 1",
{global.cow > 1 and global.sheep < 5, "Choice 2"},
"Choice 3"
}, "This is the title", 240, 15)
choice_menu: show()

if global.result == 1 then
  -- Do "Choice 1" stuff
elseif global.result == 2 then
  -- etc.
end


Not quite as elegant as the DinkC solution, but again, that cannot be quite replicated in a proper programming language. However, as Lua support object orientation, I still think we emerge victorious in a comparison. This is how the choice menu is meant to be used in Lua:

local choice_menu = dink.create_choice_menu()

local choice1 = choice_menu:add_choice("Choice 1")
local choice2 = choice_menu:add_choice("Choice 2", global.cow > 1 and global.sheep < 5)
local choice3 = choice_menu:add_choice("Choice 3")

local choice_result = choice_menu: show()

if choice_result == choice1 then
  -- Do "Choice 1" stuff
elseif choice_result == choice2 then
  -- etc.
end


Why do I think this is better?

First of all, you get choice result objects from the add_choice method, which you can use in your if statements later. If you name these well, you don't have to keep scrolling back up and count where in your choice menu that choice is, so you can compare against the right result number. Another obvious benefit is that if you were to shuffle your choice order, you wouldn't have to change a thing anywhere else. In DinkC, if you move "Choice 2" to the top, then it would suddenly be &result == 1, and you'd have to change your if statements around. In Lua, "Choice 2" would still result in choice_result == choice2, and so no change is necessary.

Second (and this also works with the DinkC-like shorthand shown first), you can prepare your choice menu in one location, and use it in another. You can re-use the same choice menu objects over and over again, once created. Here's an example from my "escape.lua" file (The Lua counterpart of DinkC's "escape.c"):

function main()
  dink.playsound(18, 22050, 0, nil, false)
  player:freeze()
  
  -- Prepare escape menu
  local escape_menu = dink.create_choice_menu()
  local escape_load = escape_menu:add_choice("Load a previously saved game")
  local escape_restart = escape_menu:add_choice("Restart")
  local escape_quit = escape_menu:add_choice("Quit to system")
  local escape_help = escape_menu:add_choice("Help")
  local escape_continue = escape_menu:add_choice("Continue")
  local escape_gamepad = escape_menu:add_choice("View/change gamepad buttons")
  local escape_save = escape_menu:add_choice("Save game")
  --escape_save.condition = false -- Disable save-anywhere choice
  
  -- Prepare quit menu
  local quit_menu = dink.create_choice_menu()
  local quit_yes = quit_menu:add_choice("Yes, I really want to quit the game")
  local quit_no = quit_menu:add_choice("I was just kidding, back to the action, please")

  -- <Prepare all the other escape menus>
  -- ...

  while true do
    local escape_result = escape_menu: show()
    
    if escape_result == escape_continue then
      player:unfreeze()
      dink.kill_this_task()
      return
    elseif escape_result == escape_quit then
      local quit_result = quit_menu: show()
      
      if quit_result == quit_no then
        dink.wait(300)
        player: say("Phew, that was a close one!")
      elseif quit_result == quit_yes then
        dink.kill_game()
      end
      
      player:unfreeze()
      dink.kill_this_task()
    end
  end
end


I've obviously left out a lot of the "escape.lua" functionality here, but you get the gist: You can prepare the menus one place, and use them in another, which can result in a nice noise reduction in the part of your code that acts upon the choices. And if you think about it, by separating choice menu creation from choice menu usage, you could even move the choice menu creation out of your code files entirely and into a file dedicated to choice menu creation if you wanted to.

If you have any feedback, feel free to drop me a reply. Again, I am still working on this, the pace has just slowed down quite a bit due to my vacation having ended.
January 27th 2014, 06:59 AM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
I greatly prefer the second method, which I will henceforth name the best choice choice menu or bccm).

I'm guessing you can input any condition in the add:choice method as a second parameter? And combinations of AND, OR, NOT?

Also, I had one extra question/suggestion that I was thinking about this morning. We know we're able to utilize strings in the LUA code. This is great for many reasons (choice menu's being one of them), but I was thinking about using strings to let the player enter his name. Some d-mods in the past have allowed letter input through various means (with LUA it would be quite easy), but I realize that the variables still only exist in the LUA code, not the DinkC code and definitely not, most importantly, in the save file.

So, you could enter a name but as far as I understand it won't be saved. So my question/suggestion is, would it be possible to (on game save) also save the variables usd in LUA to a seperate encrypted file (possibly same name as the save but with a different extention)? Preferably it would load these variables again the next time the game starts and if that's not possible, at least allows us to read from them manually.

Too bad your time has become limited again, but I think we all understand how that goes Hopefully it won't cause you to give up on the project, it's a really great thing to look forward to!

January 27th 2014, 07:58 AM
peasantmb.gif
yEoldetoast
Peasant They/Them Australia
LOOK UPON MY DEFORMED FACE! 
Novashell had choice menus implemented but they were mostly undocumented except in the examples. It may be a good candidate to study as it used Lua and had a lot in common with Dink.
January 27th 2014, 09:55 AM
peasantm.gif
shevek
Peasant They/Them Netherlands
Never be afraid to ask, but don't demand an answer 
Good to hear there's still progress.

I greatly prefer the second method

+1

I'm guessing you can input any condition in the add:choice method as a second parameter? And combinations of AND, OR, NOT?

Yes, BUT... it's a bit more confusing than it seems.

What you see there is a Lua function call. The expression with the and and or parts is evaluated by Lua and therefore can be as complex as Lua allows. It is evaluated before the function is run, and the function only sees you pass in true or false.

Now here's the confusing part: if you move that statement away, the conditionals will be evaluated when it is defined, not when it is shown. So if you define your choice menu in main(), it will only show those choices if the condition was true at that point, not if it has become true since then.

In fact, I don't really see a reason for supporting that argument. Having conditionals is useful in DinkC, because it is so limited. But in Lua, you can just use if cow > 1 then choice2 = choice_menu:add_choice("Choice 2") end, which is more clear, because it doesn't suggest that the the condition is evaluated later. What you may want to support, however, is giving it a special color.

would it be possible to (on game save) also save the variables usd in LUA

Sounds like a nice feature, but I wouldn't do it yet; first make the thing work.

There is a workaround though. You can request the character codes of a string from lua. You can store these in things that are in the save file, such as a series of editor_frames in a dedicated screen.

encrypted file

Why? If you're trying to prevent cheating, give it up. Players will cheat anyway. Besides, the engine must be able to decrypt the file, which means that the player, who has the engine, has everything they need to decrypt it as well. It's a lost battle. IMO if texts are saved, it should be done in a file that is as readable as possible. That makes debugging vastly easier.
January 27th 2014, 10:17 AM
wizardb.gif
Kyle
Peasant He/Him Belgium
 
the conditionals will be evaluated when it is defined, not when it is shown.

Oh That's unfortunate and I had no idea it worked like that either. Thanks for the information But of course the workaround you posted will work just fine too.

You can request the character codes of a string from lua. You can store these in things that are in the save file, such as a series of editor_frames in a dedicated screen.

That'll work fine too^^ Of course, it would be nice to be liberated from these things for a change

Why? If you're trying to prevent cheating, give it up. Players will cheat anyway.

You vastly overestimate the coding skills of this community. Decrypting even a simple text file is beyond 99% of our members' skills. Can the skilled people release a simple tool to do it for the others? Yes. Will they? I hope not, but in theory an encryption tool can work with a unique key chosen by the developer right?

I'd like to add onto this some more... A way to stop cheating is of great interest to me. I have always dreamed of an expandable d-mod, preferably with addons to it made by community members, that has a persistent hero character (Dink or whoever) able to be leveled, customized and equiped far beyond the current capabilities. In theory, it would be possible to upload your save/character to a custom made site, which then lists your progress and character details and places you on a leaderboard. This is the thing I'd like to one day achieve for this community. But with open cheating? It can't be done and I wouldn't even put in the effort.
January 27th 2014, 12:15 PM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
That is correct, Kyle, choice menu conditionals can be any combination of valid boolean expressions, including and, or and not. And shevek is also correct in that conditionals are evaluated upon definition, and not when the choice menu is shown. However, there's another feature of the Lua choice menu conditionals that I forgot to mention: They can be functions which return true or false. What does that mean? If you wanted at-time-of-choice-menu evaluation instead, you could replace my example with this:

local choice_menu = dink.create_choice_menu()

local choice1 = choice_menu:add_choice("Choice 1")
local choice2 = choice_menu:add_choice("Choice 2", function() return global.cow > 1 and global.sheep < 5 end)
local choice3 = choice_menu:add_choice("Choice 3")

local choice_result = choice_menu: show()

if choice_result == choice1 then
  -- Do "Choice 1" stuff
elseif choice_result == choice2 then
  -- etc.
end


Now, you have a functionality that more closely mimics DinkC's behavior. But wait. That there is a full fledged function. You could do almost ANYTHING in there to decide whether a choice menu is shown or not. Shevek is also correct that many of the limitations of DinkC are gone, making some parts of this unnecessary, but I'm going to leave it in for compatibility's sake. I am planning to mention in the documentation that doing conditionals the way you're used to in DinkC will in fact evaluate them then and there, and show the example of the function for getting just-in-time evaluation.

Any features that are additional to existing DinkC features will have to wait until after my initial release. Saving Lua variables is on the list of post-release plans.
January 27th 2014, 02:25 PM
peasantm.gif
shevek
Peasant They/Them Netherlands
Never be afraid to ask, but don't demand an answer 
You vastly overestimate the coding skills of this community. Decrypting even a simple text file is beyond 99% of our members' skills. Can the skilled people release a simple tool to do it for the others? Yes. Will they? I hope not,

I would probably write such a tool myself, because I very much dislike it if I don't have control over what my computer is doing. I might not release it publicly, but I would certainly give it to any programmer who asks for it.

If you consider your time wasted when people cheat, then don't start; either there are so little users that your time is wasted (and if you're unlucky there are still cheaters), or there are cheaters.

in theory an encryption tool can work with a unique key chosen by the developer right?

Um, strictly speaking, yes, but it doesn't help you. The program needs the key to decrypt the file, otherwise it is useless (a save file doesn't help you if you're unable to load it). But the program is under full control of the user. So the user can simply tell the program to write the unencrypted data, or even the encryption key, to a file.

Closed source people seem to think that by not releasing the source, they protect themselves against that, but that is a very weak protection. Especially teenagers (who you probably want to protect against most) are very good at figuring out how to use disassemblers and debuggers to get the information they need. The Dink community may not have enough members to contain one of those, so here it might actually work. But the reason it works, and you're not wasting your time, is that you're wasting your time, because there aren't many users.

There are a few things that can be done to create a fair tournament, but none of them may sound good to you.

Firstly, you can avoid the problem. What is the problem? That cheaters have control over their hardware, and use that control to make the program do what they want. If you make sure they don't control their hardware, they can't cheat (if there are no bugs). This means distributing computers to all players, which cannot be opened (because there's a person watching them, or because the computers will self-destruct when they try to open them). The guard scenario may work well in a classroom setting, for example. It does not work at all for something you want people to download from the internet. This is the only scenario where encryption actually works as protection of data (that can be downloaded over the internet by the trusted machine).

Secondly, you may make cheating too complex. If people need to upload a video of their playthrough which is checked by a human to see if it was done fairly, it would be very hard to write cheating code that isn't detected. This doesn't prevent all types of cheating; they can still find out the answers to puzzles without solving them. It also takes a huge amount of manpower when the community is getting larger.

Thirdly, what I think is the only realistic option (unless you're in a classroom setting), is to prevent the "benefits" of cheating. The cheaters want to have their names at the top of the high score list for everyone else to see. So instead of having a global high score list, you have a score for each person, and they can compile their own list of their score and those of their friends. If they think someone is cheating, they ask them and if they don't like the answer, they'll remove them from their list of friends. I'm sure people will still cheat, but nobody will care.

Actually, that third version is probably the only fun one for large groups anyway, because otherwise virtually everyone will be unable to reach the top 10 list; there's always someone with a higher score. If you add "friends of friends" to the list, you can still get a reasonably large list of competitors, without it being so large that competing becomes unrealistic.
January 31st 2014, 08:08 AM
dinkdead.gif
"don't lose hope, if you were waiting for me to finish"

*cough*

"Not quite as elegant as the DinkC solution"

Never seen anyone say that before

Seriously though, this is looking good. Lua shouldn't be too hard to pick up...
January 31st 2014, 08:54 AM
custom_iplaydink.gif
iplaydink
Peasant He/Him Sweden
Hmm.. 
Wow! I want this so bad O_O
April 15th 2014, 04:03 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
All right, ladies and gents. The project is not dead. To make a long story short, I'm sick a lot, and recently I was in the hospital for half a month, after having spent most of two months before that sick at home. Suffice to say, sickness does not a great programmer make. Today, however, I'm feeling pretty good, and I thought I'd try something new: Streaming my programming. I know I've enjoyed watching such sessions by others, but I can't really speak for other people, so if I get no viewers, I won't really be offended. Plus, how often do people lurk here? Not that often.

Anyway, if you're interested, I'll be streaming my Dink-Lua programming on Twitch for the next two hours or so. I hope you enjoy.

PS. I'll be streaming with music... my test in music is a bit... eclectic, so uh... feel free to mute it if you don't like it.
April 15th 2014, 06:16 AM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
Apart from a short visit from ExDeathEvn, I didn't have any visitors. I don't suppose I could expect it when it was unannounced and on a weekday (at least in the European time zones) during work hours. If there's any interest, I would consider doing a planned programming stream at a more reasonable day and time (during a weekend, at a time that works for both Europeans and Americans, for instance.)

In any case, the main point of my posting here is that I'm still working on this, and that I'm not too far away from a release, at least one that can be run/tested on Linux computers. I will not bother with trying to compile this thing for Windows until the end, because I foresee it being a major hassle. So... I hope there are some Linux dinkers out there who'll be able to help me test.
April 15th 2014, 07:33 AM
pq_knight.gif
ExDeathEvn
Peasant He/Him New Zealand rumble
"Skinny Legend" 
Enjoyed what I briefly stopped by and saw (some scripting, a glitchy bonca and some roaming around). Not sure what that whole "I'm a god!" thing and the halo was about but I had to disconnect while you were still fighting pillbugs on the farm.
Looks very interesting!
April 15th 2014, 03:39 PM
wizardb.gif
Phoenix
Peasant He/Him Norway
Back from the ashes 
I use a god-mode script to avoid having to play the game legitimately, for testing purposes. It's my Lua re-write of mimifish's God Mode script.
April 15th 2014, 03:54 PM
spike.gif
Apart from a short visit from ExDeathEvn, I didn't have any visitors. I don't suppose I could expect it when it was unannounced and on a weekday (at least in the European time zones) during work hours. If there's any interest, I would consider doing a planned programming stream at a more reasonable day and time (during a weekend, at a time that works for both Europeans and Americans, for instance.)

Yeah, I just saw this now, having slept through the entire day. I would at least try to stop by, if I knew about it beforehand.