Make Lua evaluate 0 to false and non 0 numbers to true

Anyone here who has an idea about how to fake expressions to be interpreted as true/false if they’re 0 or 1 as in lots of typical other languages?

Im porting a reasonably big JavaScript game - the actual code is only about 25k lines but in addition it has about 130k lines of story scripts also evaluating expressions/handling conditions the same way. So far I just tried to modify all the script expressions into Lua code and called that code on demand, but I just noticed there are a lots of conditions just using the shortcut version, i.e. a kind of

if myStoryVariable then

instead of

if myStoryVariable == 0 then

or

if myStoryVariable ~= 0 then

So, right now, my code is valid but just wrong, as in Lua 0 and 1 (or any other number) is true.

Anyone with an idea how to solve this in a nice way?

I actually do have code from the scripting system of the original game to evaluate the expressions but it’s ugly code and lot’s of other stuff mixed in, like management of variables or calling all kinds of external functions for special variable name etc. and I’ve successfully transformed all this into plain Lua code already. So I could just port all that expressions handling code but I’d so much prefer to use Lua for this.

Of course I could simply read through those 130k lines of story script and fix it where required - but I know after just a few thousand lines it’s starting to become a decent source for additional bugs :slight_smile:

Are you thinking of something like this or am I misunderstanding the issue?

 

local function check(i) if i == 0 then i = false else i = true end return i end local x = 1 if check(x) then print("Yay!") end
function isValueTrue(val)     return (val \> 0) end

Hehehe, I feared that I wasn’t able to explain the problem in a reasonable way :slight_smile:

It’s not that easy to explain/understand, I guess … here’s a sample how a condition line in the scripting can look

WPhiolen = 2 und Kronqueste and 1W20 <= Klugheit - Sinnenschärfe / 2 und 2W20 <= 2 * Intuition + Sinnenschärfe / 2

The initial W is the start of a condition in the script

The 1W20 means, it’s the result of one rolled die with 20 sides and the 2W20 is the sum of two of those

Klugheit, Intuition etc. are hero attributes while

Kronquests is a quest variable form the current story

When I load the scripts I modify all those lines into Lua code, replacing vars, attribs etc., modifying = into == etc. etc. resulting in valid Lua code - which, for the given line will be

return hero:getInventory():getItemCount(“Phiolen”) == 2 and storyVariables[“Kronqueste”] and Dice(1, 20) <= hero[“Klugheit”]-hero["Sinnesschärfe]/2 and Dice(2,20) <= 2*hero[“Intuition”] + hero[“Sinnesschärfe”] / 2

which is a string I can just use with loadstring and then execute.

But there you have it at the storyVariables[“Kronqueste”] part - this is an integer in a table of storyVariables and if 0 it means it should evaluate to false and if it’s any other number, it should evaluate into true.

Of course I can just add == 0 and be done - but I have thousands (maybe more than ten thousand) of those lines and while I was able to transform everything else into valid Lua code using pattern matching, replacement etc. it seems I’m stuck with that last problem.

Also there are countless lines where the script actually does compare the story variable to an integer and both, to zero as well as to non zero values.

I’m not 100% sure about this, but you may be able to override the equals operator (and others):

http://lua-users.org/wiki/MetamethodsTutorial

http://lua.2524044.n2.nabble.com/override-assignment-operator-td7195255.html (not the solution, but may help)

http://lua-users.org/wiki/MetatableEvents

It seems for tables and globals this is feasible, but locals are a bit harder.

Hopefully someone with a little more Lua black magic skill will read this and answer.

I gave this a real go, but couldn’t work it out.  Sorry.

My best suggestion.  Work up a better converter and convert the code with a script.

I’d look for a javascript to lua converter on gitHub:

You may need to run it with a standalone version of Lua to do the conversion work since Corona Lua may not support all the features needed by the converter scripts.

I’m going to assume that your parsing is rock-solid and you operate at the clause level, where in an expression like

if A and B or C and not D or (E and (F or G)) then

the capital letters stand for said clauses. Is this accurate? (I don’t know off-hand if Lua and JS honor the same precedences?)

If you have nested parentheses like so then some of this gets hairier, of course, since you might want a 0 to bubble up. But if not, three clause forms come to mind:

VALUE  Just a name, like Kronqueste, or a constant like 4 or our nemesis 0.

LHS comp RHS An expression with a comparison operator (==, ~=, <, <=, >, >=, or JS equivalents depending on when analyzed) between a left- and right-hand side.

EXPRESSION  Some assortment of values and arithmetic operators that might culminate in 0, e.g. Kronqueste * 3 + 7.

The VALUE case you can detect by trimming off spaces at each end, string.match ()'ing the result against patterns like “[_%w]+” or “%d+”, and seeing whether you got the whole match. In the constant case, just replace the result by true or false. Otherwise, either do as roaminggamer suggests and say throw a proxy over storyVariables ( rawget might come in handy as well, if you do so), or append the comparison against 0.

Failing that, do a search for any of the comparison operators and if so leave the comp case intact.

Otherwise, you have the EXPRESSION case and can just parenthesize that and compare against 0.

All untested, of course.  :smiley:

Thanks for your reply and trying, I also thought about using a proxy object and metatable but the problem then is situations with actual integer comparisons … 

Seems like I might just bite the bullet and port the expression parser of the original game, damn. I got everything else sorted out so far while porting all the JavaScript code to a much nicer Lua version :slight_smile:

@StarCrunch - well I did not do a lot of parsing, what I did was modify the scripting into valid Lua code like replace != with ~=, replaced all kinds of “variables” actually requiring function calls to the hero or other gameworld related data, the variables with the lookup into the storyVariables table and some tweaks here and there which worked quite well - until I noticed some strange behaviour given by 0 interpreted as true :slight_smile:

I do have the code to manually handle the original expressions with all details and special cases so I can just port this to Lua and be done.

It’s just that, I’ve come so far and I’d have loved to get it fully working as (in a simple way) transformed Lua code :slight_smile:

if you’re doing the string conversions (ie the parsing of one script language to another) then why not just “wrap” the output script using conversion functions of your own making?

input:  Kronqueste

old output:  storyVariables[“Kronqueste”]

new output:  tobool(storyVariables[“Kronqueste”])

local function tobool(v) if (type(v) == "number") then return (v~=0) end return (not not v) end

The problem is, the scripts use those variables very arbitrarily (they were originally done by various book authors, over a timeframe of almost 15 years and already ported form another platform and language once during this time, so it’s just lot’s of legacy data not always in an ideal format), i.e. it’s very possible that the same variable will sometimes be used as a boolean but in another expression as an integer in a calculation and in another one as a boolen but by comparing to 0.

I just started to port the original expression handling code - it’s not that bad, it’s just not as beautiful as pure Lua would be :slight_smile:

then as per others’ prior replies, and if it were me, i’d require that all conditional expressions be explicit, ie add the “~=0”, then if used as numeric expression will still work.  (otherwise no bullet-proof way to trap all possible uses, as you’ve seen and know)

Are you thinking of something like this or am I misunderstanding the issue?

 

local function check(i) if i == 0 then i = false else i = true end return i end local x = 1 if check(x) then print("Yay!") end
function isValueTrue(val) &nbsp; &nbsp; return (val \> 0) end

Hehehe, I feared that I wasn’t able to explain the problem in a reasonable way :slight_smile:

It’s not that easy to explain/understand, I guess … here’s a sample how a condition line in the scripting can look

WPhiolen = 2 und Kronqueste and 1W20 <= Klugheit - Sinnenschärfe / 2 und 2W20 <= 2 * Intuition + Sinnenschärfe / 2

The initial W is the start of a condition in the script

The 1W20 means, it’s the result of one rolled die with 20 sides and the 2W20 is the sum of two of those

Klugheit, Intuition etc. are hero attributes while

Kronquests is a quest variable form the current story

When I load the scripts I modify all those lines into Lua code, replacing vars, attribs etc., modifying = into == etc. etc. resulting in valid Lua code - which, for the given line will be

return hero:getInventory():getItemCount(“Phiolen”) == 2 and storyVariables[“Kronqueste”] and Dice(1, 20) <= hero[“Klugheit”]-hero["Sinnesschärfe]/2 and Dice(2,20) <= 2*hero[“Intuition”] + hero[“Sinnesschärfe”] / 2

which is a string I can just use with loadstring and then execute.

But there you have it at the storyVariables[“Kronqueste”] part - this is an integer in a table of storyVariables and if 0 it means it should evaluate to false and if it’s any other number, it should evaluate into true.

Of course I can just add == 0 and be done - but I have thousands (maybe more than ten thousand) of those lines and while I was able to transform everything else into valid Lua code using pattern matching, replacement etc. it seems I’m stuck with that last problem.

Also there are countless lines where the script actually does compare the story variable to an integer and both, to zero as well as to non zero values.

I’m not 100% sure about this, but you may be able to override the equals operator (and others):

http://lua-users.org/wiki/MetamethodsTutorial

http://lua.2524044.n2.nabble.com/override-assignment-operator-td7195255.html (not the solution, but may help)

http://lua-users.org/wiki/MetatableEvents

It seems for tables and globals this is feasible, but locals are a bit harder.

Hopefully someone with a little more Lua black magic skill will read this and answer.

I gave this a real go, but couldn’t work it out.  Sorry.

My best suggestion.  Work up a better converter and convert the code with a script.

I’d look for a javascript to lua converter on gitHub:

You may need to run it with a standalone version of Lua to do the conversion work since Corona Lua may not support all the features needed by the converter scripts.

I’m going to assume that your parsing is rock-solid and you operate at the clause level, where in an expression like

if A and B or C and not D or (E and (F or G)) then

the capital letters stand for said clauses. Is this accurate? (I don’t know off-hand if Lua and JS honor the same precedences?)

If you have nested parentheses like so then some of this gets hairier, of course, since you might want a 0 to bubble up. But if not, three clause forms come to mind:

VALUE  Just a name, like Kronqueste, or a constant like 4 or our nemesis 0.

LHS comp RHS An expression with a comparison operator (==, ~=, <, <=, >, >=, or JS equivalents depending on when analyzed) between a left- and right-hand side.

EXPRESSION  Some assortment of values and arithmetic operators that might culminate in 0, e.g. Kronqueste * 3 + 7.

The VALUE case you can detect by trimming off spaces at each end, string.match ()'ing the result against patterns like “[_%w]+” or “%d+”, and seeing whether you got the whole match. In the constant case, just replace the result by true or false. Otherwise, either do as roaminggamer suggests and say throw a proxy over storyVariables ( rawget might come in handy as well, if you do so), or append the comparison against 0.

Failing that, do a search for any of the comparison operators and if so leave the comp case intact.

Otherwise, you have the EXPRESSION case and can just parenthesize that and compare against 0.

All untested, of course.  :smiley:

Thanks for your reply and trying, I also thought about using a proxy object and metatable but the problem then is situations with actual integer comparisons … 

Seems like I might just bite the bullet and port the expression parser of the original game, damn. I got everything else sorted out so far while porting all the JavaScript code to a much nicer Lua version :slight_smile:

@StarCrunch - well I did not do a lot of parsing, what I did was modify the scripting into valid Lua code like replace != with ~=, replaced all kinds of “variables” actually requiring function calls to the hero or other gameworld related data, the variables with the lookup into the storyVariables table and some tweaks here and there which worked quite well - until I noticed some strange behaviour given by 0 interpreted as true :slight_smile:

I do have the code to manually handle the original expressions with all details and special cases so I can just port this to Lua and be done.

It’s just that, I’ve come so far and I’d have loved to get it fully working as (in a simple way) transformed Lua code :slight_smile: