Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Make Lua evaluate 0 to false and non 0 numbers to true
Started by Michael Flad Dec 08 2018 07:09 AM

- - - - -
11 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 196 posts
  • Corona SDK

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 :)
 


[TOPIC: post.html]
#2

XeduR @Spyric

[GLOBAL: userInfoPane.html]
XeduR @Spyric
  • Contributor

  • 368 posts
  • Corona SDK

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


[TOPIC: post.html]
#3

schizoid2k

[GLOBAL: userInfoPane.html]
schizoid2k
  • Contributor

  • 548 posts
  • Corona SDK

function isValueTrue(val)
    return (val > 0)
end


[TOPIC: post.html]
#4

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 196 posts
  • Corona SDK

Hehehe, I feared that I wasn't able to explain the problem in a reasonable way :)
 
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.


[TOPIC: post.html]
#5

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,380 posts
  • Corona SDK

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.



[TOPIC: post.html]
#6

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,380 posts
  • Corona SDK

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.


Edited by roaminggamer, 08 December 2018 - 10:16 AM.

  • Michael Flad likes this

[TOPIC: post.html]
#7

StarCrunch

[GLOBAL: userInfoPane.html]
StarCrunch
  • Contributor

  • 769 posts
  • Corona SDK

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.  :D


  • Michael Flad likes this

[TOPIC: post.html]
#8

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 196 posts
  • Corona SDK

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 :)



[TOPIC: post.html]
#9

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 196 posts
  • Corona SDK

@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 :)

 

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 :)


  • StarCrunch likes this

[TOPIC: post.html]
#10

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,259 posts
  • Enterprise

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


  • Michael Flad likes this

[TOPIC: post.html]
#11

Michael Flad

[GLOBAL: userInfoPane.html]
Michael Flad
  • Contributor

  • 196 posts
  • Corona SDK

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 :)



[TOPIC: post.html]
#12

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,259 posts
  • Enterprise

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)




[topic_controls]
[/topic_controls]