#ifdef NORMAL, HARD

Brainstorm ideas of possible additions to the game. Read this before posting!

Moderator: Forum Moderators

Forum rules
Before posting a new idea, you must read the following:
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

#ifdef NORMAL, HARD

Post by Helmet »

It would nice if you could use a comma in this manner to consider NORMAL and HARD difficulties: #ifdef NORMAL, HARD

Presently, to consider NORMAL and HARD difficulties, one has to do this:

Code: Select all

#ifdef EASY
#else
	[event]
    		name=exit hex
    		# code
    		# code
	[/event]
#endif
At a glance, it appears that the event only works on EASY, but that's not the case. Sometimes it gets confusing.

Thanks.
User avatar
Lord-Knightmare
Forum Regular
Posts: 1250
Joined: May 24th, 2010, 5:26 pm
Location: Somewhere in the depths of Irdya, gathering my army to eventually destroy the known world.
Contact:

Re: #ifdef NORMAL, HARD

Post by Lord-Knightmare »

Well, we have this which serves your purpose:

Code: Select all

#ifndef EASY
[event]
    name="start"
[/event]
#endif
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

That occasionally creates a mess.

#ifdef can wreck my tidy code as I try to isolate areas from other areas based on difficulty.

Say, I have 500 lines of code. I want to add 4 lines in the middle that are only applicable to NORMAL and HARD. So now I have to wrap the first 250 lines of code in #ifdef EASY and the last 250 lines of code in #ifdef EASY. Ugh. And then later I add another 4 lines that are NORMAL and HARD, and 4 that are EASY and NORMAL. Double ugh.

I think it would be more elegant, intuitive and tidier to keep one's focus on the code being written as it's written, instead of scrolling up and down, trying to encapsulate previous code as exceptions.
User avatar
Lord-Knightmare
Forum Regular
Posts: 1250
Joined: May 24th, 2010, 5:26 pm
Location: Somewhere in the depths of Irdya, gathering my army to eventually destroy the known world.
Contact:

Re: #ifdef NORMAL, HARD

Post by Lord-Knightmare »

Say, I have 500 lines of code. I want to add 4 lines in the middle that are only applicable to NORMAL and HARD. So now I have to wrap the first 250 lines of code in #ifdef EASY and the last 250 lines of code in #ifdef EASY. Ugh. And then later I add another 4 lines that are NORMAL and HARD, and 4 that are EASY and NORMAL. Double ugh.
I deal with like 2000 lines of WML code in my scenarios so this is rather trivial to me. I don't think wrapping the first 250 lines of code in #ifdef and #endif is necessary. You can pretty much just use #ifndef HARD for code for Easy and Normal and #ifndef EASY for NORMAL and HARD.
You can avoid the scrolling thing and have a much better experience using a specialised text editor like VSCode with the WML extension installed and enabled.
screenshot
Screenshot 2020-11-30 233034.png
User avatar
Ravana
Forum Moderator
Posts: 2476
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: #ifdef NORMAL, HARD

Post by Ravana »

#ifdef NORMAL
#define NORMAL_OR_HARD
#enddef
#endif
#ifdef HARD
#define NORMAL_OR_HARD
#enddef
#endif

And then can use #ifdef NORMAL_OR_HARD
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

Ravana wrote: November 30th, 2020, 5:37 pm And then can use #ifdef NORMAL_OR_HARD
Wow, thanks. It works; I can use #ifdef NORMAL_OR_HARD now. Awesome.

But...now #ifdef NORMAL also includes HARD, even though I don't want it to.

Can you take that awesome code to the next level, so EASY does EASY, NORMAL does NORMAL, HARD does HARD, and NORMAL_OR_HARD does NORMAL and HARD, and EASY_OR_NORMAL does EASY and NORMAL? And make it a macro so I don't have to paste it into every scenario? Or explain how to add it to _main.cfg? Your code boggles my mind; I have no idea how it works. But I like it. :D
User avatar
WhiteWolf
Forum Moderator
Posts: 735
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: #ifdef NORMAL, HARD

Post by WhiteWolf »

Helmet wrote: November 30th, 2020, 7:00 pm But...now #ifdef NORMAL also includes HARD, even though I don't want it to.
I really fail to see why it would work why that. Did you actually test this or is it just speculation?
Can you take that awesome code to the next level, so EASY does EASY, NORMAL does NORMAL, HARD does HARD, and NORMAL_OR_HARD does NORMAL and HARD, and EASY_OR_NORMAL does EASY and NORMAL?
Because this should already work exactly like you described here.
And make it a macro so I don't have to paste it into every scenario? Or explain how to add it to _main.cfg?
Just include this above your scenario inclusions in the _main.cfg. It goes right where all your other macro definitions go that you use in your scenarios. Or alternatively just include it to your very first scenario. Not in the others.
[Sidenote: Definitely do not include this in every scenario - that means in each consecutive scenario you are redefining a symbol without first undefining it (#undef), and wesnoth will dump warnings about this to its log (that's not a nice thing to do :) ) Yes, if you load up a saved game from scenario 3 after making this addition to scenario 1 will not apply the change to scenario 3, but including it to every scenario is not the way to work this around. ]
Your code boggles my mind; I have no idea how it works. But I like it. :D
A bit of useful reading: https://wiki.wesnoth.org/Preprocessorref
Ifdef checks if a preprocessor symbol has been defined or not. Ravana's code defines a new symbol in the game, if we're playing on NORMAL, or on HARD. Therefore after that point you can check for this symbol. If it has been defined, then we know we're either on normal on hard, because we only defined it for those cases.
Author of the Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Standalone works: The Ravagers - now for 1.14, with new bugs!
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

WhiteWolf wrote: November 30th, 2020, 7:34 pm I really fail to see why it would work why that. Did you actually test this or is it just speculation?
I tested it. After I read your post, I tested it again -- just in case. In the code, a guy named Jonivan should only appear on NORMAL. But he also appears on HARD.

Code: Select all

#ifdef NORMAL
#define NORMAL_OR_HARD
#enddef
#endif
#ifdef HARD
#define NORMAL_OR_HARD
#enddef
#endif

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    

#ifdef NORMAL

# # ifdef EASY # 						Bowman only exists on NORMAL, HARD
# # else
[event] #							Bowman regains normal movement
    name=exit hex
    [filter]
        id=Jonivan
        x,y=22,4
    [/filter]
    [event]
        name=turn end
        [modify_unit]
            [filter]
                id=Jonivan
            [/filter]
            max_moves=5
        [/modify_unit]
    [/event]
[/event]
#endif
WhiteWolf wrote: November 30th, 2020, 7:34 pm Just include this above your scenario inclusions in the _main.cfg. It goes right where all your other macro definitions go that you use in your scenarios. Or alternatively just include it to your very first scenario. Not in the others.
Ah, thanks for the info.
WhiteWolf wrote: November 30th, 2020, 7:34 pm A bit of useful reading: https://wiki.wesnoth.org/Preprocessorref
Ifdef checks if a preprocessor symbol has been defined or not. Ravana's code defines a new symbol in the game, if we're playing on NORMAL, or on HARD. Therefore after that point you can check for this symbol. If it has been defined, then we know we're either on normal on hard, because we only defined it for those cases.
Thanks. I guess I just don't see why WML needs to involve preprocessors or symbols. Why didn't the developers make the code like this?

Code: Select all

[difficulty]
	choice=EASY
[/difficulty]
Or...

Code: Select all

[difficulty_limit]
	only=normal
	only=hard
[difficulty_limit]
I'm going to read about preprocessors now. The problem, I think, may be that I don't know what they are.
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

Oops. It's looking like it's my fault the Ravana's code didn't work as expected. I had another #ifdef EASY and #else (which allowed NORMAL and HARD to happen, not EASY) that I forgot about.

See? Those things cause me a headache.

EDIT: It's working now.

Thank you Ravana and WhiteWolf. I like using difficulty levels to add more units, and so forth. That code will help me make fewer mistakes.

I put the code in [campaign] in _main.cfg. It didn't stop working, so evidently I guessed right.
User avatar
Ravana
Forum Moderator
Posts: 2476
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: #ifdef NORMAL, HARD

Post by Ravana »

Thanks. I guess I just don't see why WML needs to involve preprocessors or symbols. Why didn't the developers make the code like this?
Preprocessor works even with invalid WML, it is general purpose text inclusion, it does not know anything about WML.

Preprocessor is comfort feature mostly. All WML can be in _main.cfg removing need for inclusions, and difficulty handling can be done with in game choices and variables. I guess historical reasons why it is how it is.
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

Ravana wrote: November 30th, 2020, 10:24 pm Preprocessor works even with invalid WML, it is general purpose text inclusion, it does not know anything about WML.

Preprocessor is comfort feature mostly. All WML can be in _main.cfg removing need for inclusions, and difficulty handling can be done with in game choices and variables. I guess historical reasons why it is how it is.
Oh, that was helpful. Thanks. I was wondering if it was something like that.

I modified your code to include EASY_OR_NORMAL. Man, I like this nifty code. It works so well. It makes sense.

I still think my original suggestion should be considered, though, as it agrees with the K.I.S.S principle espoused by the creator of BfW. Writing EASY to engage the NORMAL and HARD difficulty modes, for example, requires convoluted thinking.

I think some developers are so smart, they don't know or remember what convoluted thinking feels like. WML is easy to them. But for somebody struggling with WML, even a simple problem can be a huge stumbling block. The more logical WML is, imo, the easier it will be to learn and use. And remember.
User avatar
WhiteWolf
Forum Moderator
Posts: 735
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: #ifdef NORMAL, HARD

Post by WhiteWolf »

Helmet wrote: November 30th, 2020, 11:43 pm I still think my original suggestion should be considered, though, as it agrees with the K.I.S.S principle espoused by the creator of BfW. Writing EASY to engage the NORMAL and HARD difficulty modes, for example, requires convoluted thinking.
I didn't completely understand what you meant by that, so I've read through the original posts too again, and I must ask: did you perhaps miss the tiny extra "n" in Lord-Knightmare's suggestion?
#ifdef X is an abbreviation for "if [X] is defined"
#ifndef X stands for "if [X] is NOT defined".
It's just a negation, which is all over in conditions in programming. It's not a super-long chain of conditions that's impossible to see through.

So you're not writing EASY to engage normal and hard. (Yeah, that would indeed be counter-intuitive). No, instead you write NOT EASY, which means to engage "all other difficulties". That would include nightmare too if your addon has 4 difficulties. (and any custom ones too if that's the case). So if you want to be as general as possible, and want to restrict it to just normal and hard by all means, make sure nightmare doesn't get into it if your code gets into such a context, then indeed Ravana's code is the one to use.

But in your example, you had 500 lines of code, wanted to include 4 in the middle, that's just:

Code: Select all

first 250 lines
#ifndef EASY
4 lines
#endif
other 250 lines
There's no need to wrap the first and second 250 lines in an #ifdef. That's the whole point. :)


Anyway, I don't think a comma separated list can be implemented in preprocessors. I'm not an expert, but their point is being simple - they're sooo simple that I doubt they could handle something as complex as a comma separated list.
Author of the Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Standalone works: The Ravagers - now for 1.14, with new bugs!
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

WhiteWolf wrote: December 1st, 2020, 9:57 am I didn't completely understand what you meant by that, so I've read through the original posts too again, and I must ask: did you perhaps miss the tiny extra "n" in Lord-Knightmare's suggestion?
GASP!
WhiteWolf wrote: December 1st, 2020, 9:57 am #ifdef X is an abbreviation for "if [X] is defined"
#ifndef X stands for "if [X] is NOT defined".
GASP!
WhiteWolf wrote: December 1st, 2020, 9:57 am So you're not writing EASY to engage normal and hard. (Yeah, that would indeed be counter-intuitive). No, instead you write NOT EASY, which means to engage "all other difficulties"....
There's no need to wrap the first and second 250 lines in an #ifdef. That's the whole point. :)
GASP!

Your suspicion was correct, WhiteWolf. I totally didn't see that tiny little "n" in Lord-Knightmare's post. And had I seen it, I probably would've thought it was a typo.

So...um...nevermind! :oops:

Thanks for explaining. Also, thanks for contemplating my problem and solving the subtle mystery at the heart of my confusion.

PS: I'm still going to use Ravana's solution. Check-out this beautiful crystal-clear code...

Code: Select all

#ifdef EASY
			type=Naga Warrior
#endif
#ifdef NORMAL_OR_HARD
			type=Naga Sicarius
#endif
gnombat
Posts: 320
Joined: June 10th, 2010, 8:49 pm

Re: #ifdef NORMAL, HARD

Post by gnombat »

Helmet wrote: November 30th, 2020, 7:56 pm Thanks. I guess I just don't see why WML needs to involve preprocessors or symbols.
Ravana wrote: November 30th, 2020, 10:24 pm I guess historical reasons why it is how it is.
Specifically, the preprocessor is a feature found in the C (and C++) programming language. The Wesnoth preprocessor is very similar in design and syntax to the C/C++ preprocessor. Presumably it was made that way so that C/C++ programmers would find it very familiar and easy to use. Of course, for people who aren't C/C++ programmers, the preprocessor may not make very much sense - why does it have this strange syntax that looks nothing like the rest of WML? As Ravana says above, it looks like that mostly for historical reasons.
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: #ifdef NORMAL, HARD

Post by Helmet »

gnombat wrote: December 1st, 2020, 1:28 pm Specifically, the preprocessor is a feature found in the C (and C++) programming language. The Wesnoth preprocessor is very similar in design and syntax to the C/C++ preprocessor. Presumably it was made that way so that C/C++ programmers would find it very familiar and easy to use. Of course, for people who aren't C/C++ programmers, the preprocessor may not make very much sense - why does it have this strange syntax that looks nothing like the rest of WML? As Ravana says above, it looks like that mostly for historical reasons.
Oh. Thanks for the explanation. Like you had guessed, I had been thinking, "Why does this code look nothing like the rest of WML?"

I tried to teach myself C++ once. It went about as well as teaching myself Russian.

Thankfully, WML uses a lot of "words."
Post Reply