It is currently April 19th, 2024, 11:58 am

RainGame - A functional game engine without scrip... WITH a custom scripting language!

Skins that control functions in Windows or Rainmeter
User avatar
balala
Rainmeter Sage
Posts: 16144
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: RainGame - A functional game engine without scripts or plugins | Now with Scrolling!

Post by balala »

Yamajac wrote: November 16th, 2019, 10:36 pm No, they can't actually. WebParser *can* have regex but the regex functions differently behind the scenes, making it significantly less useful. String measures are the only place in Rainmeter that regular expressions actually work unrestricted.


For instance, in a web parser measure if you put (test) then ONLY the first test will be replaced, because it isn't global. In a string measure, ALL instances of test will be replaced, because it is global. It's impossible to parse an entire website in two measures with webparser measures, but it's possible if you replace one of the web parser measures with a string measure.
Let's clarify for first what are we talking about. Both jsmorley and me were talking about regular expression substitution (done with a RegExSubstitute and a Substitute options added to the measure). This is working on any kind of measure. This technique can be used for instance to add leading zeros in front of a number when you want to show that number through a String meter.
For instance let's take the following Time measure:

Code: Select all

[MeasureSecond]
Measure=Time
Format=%#S
This measure returns the number of seconds with no leading zero. If now you add a RegExpSubstitute=1 and a Substitute="^(.)$":"00\1","^(..)$":"0\1" options to the above [MeasureSecond] measure, you'll get the result with three digits: if the number of seconds has one single digit there will be added two zeros in front of it, while it has two digits, one single zero will be added. Both cases you get the result with three digits (even if this doesn't make too much sense). No String measure involved, however the regular expression substitution still works. Same way works with WebParser measures, or even with Calc ones.
Believe us, this works not just with String measure.
User avatar
Yamajac
Posts: 134
Joined: June 30th, 2014, 8:44 am

Re: RainGame - A functional game engine without scripts or plugins | Now with Scrolling!

Post by Yamajac »

balala wrote: November 17th, 2019, 7:21 am Let's clarify for first what are we talking about. Both jsmorley and me were talking about regular expression substitution (done with a RegExSubstitute and a Substitute options added to the measure). This is working on any kind of measure. This technique can be used for instance to add leading zeros in front of a number when you want to show that number through a String meter.
For instance let's take the following Time measure:

Code: Select all

[MeasureSecond]
Measure=Time
Format=%#S
This measure returns the number of seconds with no leading zero. If now you add a RegExpSubstitute=1 and a Substitute="^(.)$":"00\1","^(..)$":"0\1" options to the above [MeasureSecond] measure, you'll get the result with three digits: if the number of seconds has one single digit there will be added two zeros in front of it, while it has two digits, one single zero will be added. Both cases you get the result with three digits (even if this doesn't make too much sense). No String measure involved, however the regular expression substitution still works. Same way works with WebParser measures, or even with Calc ones.
Believe us, this works not just with String measure.
If you want to add leading zeroes, I have a better example of a regex here.

I know you can use regex substitute on any measure. I didn't know you could make a measure that only returns numbers have a string value with a substitute, but that still doesn't make a calc measure as powerful as a string measure. Calc measures can not be arrays - at least not in the same cpu time as a string measure. You could in theory replace the whole calc measure with a string as the first substitute and then work exactly the same way, but there's no direct benefit, it just costs an extra substitution. (Though having the separated number/object output could potentially be useful in some cases but this is a bit of a tangent)


Take the following code as an example;

We first create an array/object type thing in a reasonably human readable format, then we convert that human readable object into a string with the escaped variable names using the [EntityLoader] measure regex, and then finally resolve all the variables in the [Entities] measure to turn it into a regex readable string: X9Y9NSlime1|X8Y6NSlime2|X12Y4NSlime3|X1Y4NBox1|X5Y6NBox2|

We can then check if an entity is at position X/Y by passing the X and Y coordinates to the ToBeCheckedX and ToBeCheckedY variables and updating the [CheckEntityCollisions] measure. Then if that entity exists, we can access its variables through nested variables like [#[&CheckEntityCollisions]X] effectively turning Rainmeter ini files into something almost resembling OOP.

Code: Select all

[variables]
; Entity stuff
Entities = Slime1|Slime2|Slime3|Box1|Box2

; Entities need to be manually placed in the world for now. 
; Give them an X, a Y, Entity type and an Image
; 0 = Pushed on collision
; 1 = battle (not currently implemented)
Slime1X     = 9
Slime1Y     = 9
Slime1Type  = 1
Slime1Image = Slime

Slime2X     = 8
Slime2Y     = 6
Slime2Type  = 1
Slime2Image = Slime

Slime3X     = 12
Slime3Y     = 4
Slime3Type  = 1
Slime3Image = Slime

Box1X     = 1
Box1Y     = 4
Box1Type  = 0
Box1Image = Box

Box2X     = 5
Box2Y     = 6
Box2Type  = 0
Box2Image = Box



[EntityLoader]
Measure  = String
String   = #Entities#
Group    = EntityUpdate
DynamicVariables = 1
RegExpSubstitute = 1
Substitute       = "(.*?)(\||$)" : "X[#\1X]Y[#\1Y]N\1|"
[Entities]
Measure = String
String  = [&EntityLoader]
Group   = EntityUpdate
DynamicVariables = 1

[CheckEntityCollisions]
Measure  = String
String   = [Entities]
Group    = NoUpdate
Disabled = 1
DynamicVariables = 1
RegExpSubstitute = 1
Substitute       = ".*?X#ToBeCheckedX#Y#ToBeCheckedY#N(.*?)\|.*" : "\1"
IfMatchMode      = 1
IfMatch          = "\|"
IfMatchAction    = [!UpdateMeasureGroup CollisionCheckers]
IfNotMatchAction = [!UpdateMeasure HandleEntityCollisions]

So. Can you use a regex on any measure? Yes, of course you can. Does it let you do things like this? No.

Was I wrong in saying string measures are the only measures that can do this? Yes. Webparser can do the same thing but requires one extra measure and significantly more cpu time + logic, and time measures can do the same thing in probably very slightly more cpu time, but the same logic. (And any measure EXCEPT a top level parent web parser can do the same thing by wasting the first substitute to pass the string to the measure, technically.)

Being able to output both a number and a string in one measure as jsmorley pointed out is extremely cool, though. I have no idea how it'll be useful, but I'm sure I'll use it someday.

But believe me, arbitrary strings + regex substitute is what makes regex powerful in rainmeter. Regex with predetermined outputs like time, cpu, loop, etc is NOT the same thing, and is significantly less versatile although still quite powerful. Just not to nearly the same degree as with a measure supporting arbitrary strings because those measures just enter an entirely different league of utility, opening up so many more options.
User avatar
balala
Rainmeter Sage
Posts: 16144
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: RainGame - A functional game engine without scripts or plugins | Now with Scrolling!

Post by balala »

Yamajac wrote: November 17th, 2019, 8:25 am If you want to add leading zeroes, I have a better example of a regex here.
As usually there are more possibilities. But your solution requires adding new measure to the code, which not always is a good idea. The best approach is to reduce as much as possible the number of measures and meters. So for a simple case when leading zeros are needed, the simple way using a regular expression substitution is a much simpler way. I don't contest your approach is good as well, it definitely is, but avoiding a suplimentar measure can be a good idea.
Yamajac wrote: November 17th, 2019, 8:25 am I know you can use regex substitute on any measure. I didn't know you could make a measure that only returns numbers have a string value with a substitute,
No, in fact every measure has a numeric and a string value. Many times these are the same. For instance the string value of a Calc measure is the same as its numeric value, just written as a string. That1s why you can apply freely the regular expression substitution to any measure, no matter what type it is.
Yamajac wrote: November 17th, 2019, 8:25 am So. Can you use a regex on any measure? Yes, of course you can. Does it let you do things like this? No.

Was I wrong in saying string measures are the only measures that can do this? Yes. Webparser can do the same thing but requires one extra measure and significantly more cpu time + logic, and time measures can do the same thing in probably very slightly more cpu time, but the same logic. (And any measure EXCEPT a top level parent web parser can do the same thing by wasting the first substitute to pass the string to the measure, technically.)

Being able to output both a number and a string in one measure as jsmorley pointed out is extremely cool, though. I have no idea how it'll be useful, but I'm sure I'll use it someday.

But believe me, arbitrary strings + regex substitute is what makes regex powerful in rainmeter. Regex with predetermined outputs like time, cpu, loop, etc is NOT the same thing, and is significantly less versatile although still quite powerful. Just not to nearly the same degree as with a measure supporting arbitrary strings because those measures just enter an entirely different league of utility, opening up so many more options.
Yes, I suppose you are right here.

Finally one more thing I have to say: please don't say regexp. RegExp is an option of a parent WebParser measure. The regexp you are talking about is the regular expression substitution, which is something different. Please don't mix these two things.
User avatar
Yamajac
Posts: 134
Joined: June 30th, 2014, 8:44 am

Re: RainGame - A functional game engine without scripts or plugins | Now with Scrolling!

Post by Yamajac »

balala wrote: November 17th, 2019, 4:20 pm As usually there are more possibilities. But your solution requires adding new measure to the code, which not always is a good idea. The best approach is to reduce as much as possible the number of measures and meters. So for a simple case when leading zeros are needed, the simple way using a regular expression substitution is a much simpler way. I don't contest your approach is good as well, it definitely is, but avoiding a suplimentar measure can be a good idea.
No it doesn't, regexpsubstitute can be used on any measure.

Code: Select all

[time]
[MeasureTime]
Measure=Time
Format=%#I:%M
;#;     ^ kinda stinks for my notepad++ syntax highlighter
MinValue = 8
MaxValue = 7
RegExpSubstitute = 1
; The first substitute grabs the entire string and adds zeroes to the front
; The second substitute grabs the leading zeroes and duplicates them several times
; to ensure we have enough leading zeroes for all use cases
; Then finally the third substitute removes all but the last X digits
; Where X is the MinValue on this measure
Substitute = "(^[0-9]*)" : "0000000\1", "^(0*)(0.*)" : "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\2", "0*([0-9]{[MeasureTime:MinValue]}.*)" : "\1", "(\.[0-9]*)" : "\1000000000", "(.*\.)(.+)(00*)(0[^0-9]*)" : "\1\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\4", "(^.*\.)([0-9]{[MeasureTime:MaxValue]}[^0]*)0*" : "\1\2"
balala wrote: November 17th, 2019, 4:20 pm No, in fact every measure has a numeric and a string value. Many times these are the same. For instance the string value of a Calc measure is the same as its numeric value, just written as a string. That1s why you can apply freely the regular expression substitution to any measure, no matter what type it is.
Yes, but what JSMorley kindly pointed out is that they CAN be made differently through a substitute, like this. Which is extremely cool, I still haven't figured out a practical use case for it but it would probably be useful for code golf at least.
balala wrote: November 17th, 2019, 4:20 pm Finally one more thing I have to say: please don't say regexp. RegExp is an option of a parent WebParser measure. The regexp you are talking about is the regular expression substitution, which is something different. Please don't mix these two things.
Regexp is the key on webparser measures. Regexp is also just the normal way to refer to regular expressions in the rest of the world. Sorry if it gets confusing, but I'm not the one who made conflicting section key names.
User avatar
Yamajac
Posts: 134
Joined: June 30th, 2014, 8:44 am

Re: RainGame - A functional game engine without scrip... WITH a custom scripting language!

Post by Yamajac »