Jump to content

Weidu question: PATCH_IF / ELSE


subtledoctor

Recommended Posts

I want to do something like this:

COPY_EXISTING ~stuff~ ~overrride~
  PATCH_IF (%variable% = 3) BEGIN
    [do stuff]
  END
  PATCH_IF (%varable% = 5) BEGIN
    [do other stuff]
  END
  ELSE BEGIN // if %variable% = any other value
    [do some different default stuff]
  END
BUT_ONLY
My question is, more or less, does that work? given that there's an END closing out each conditional PATCH_IF section, can the ELSE reach back and know to incorporate more than one?

 

Put another way: can we do this:

PATCH_IF
PATCH_IF
PATCH_IF
ELSE
...or are we restricted to this:

PATCH_IF
ELSE
Link to comment

I want to do something like this:

COPY_EXISTING ~stuff~ ~overrride~
  PATCH_IF (%variable% = 3) BEGIN
    [do stuff]
  END
  PATCH_IF (%varable% = 5) BEGIN
    [do other stuff]
  END
  ELSE BEGIN // if %variable% = any other value
    [do some different default stuff]
  END
BUT_ONLY
My question is, more or less, does that work? given that there's an END closing out each conditional PATCH_IF section, can the ELSE reach back and know to incorporate more than one?

 

Put another way: can we do this:

PATCH_IF
PATCH_IF
PATCH_IF
ELSE
...or are we restricted to this:

PATCH_IF
ELSE
Link to comment

Why would it be restricted to the second... of course you might want to ...

PATCH_IF (%variable% = 3 AND NOT %variable% = 5) BEGIN
patch stuff
END
PATCH_IF (%variable% = 5 AND NOT %variable% = 3) BEGIN
patch stuff
END
ELSE BEGIN
patch stuff
END 
Link to comment

Jarno isn't that already encompassed by the "=" ?

 

Question is, how does the "ELSE" know what it is referring to?

 

Let's say I want to patch some items; if they are swords, I want to color them all red; if they are long swords they should do extra slashing damage, if they are bastard swords they should do extra crushing damage, and any other swords should default to giving an AC bonus. Pseudocode:

COPY_EXISTING_REGEXP_GLOB ~all items~
  PATCH_IF (%type% = swords) BEGIN
    [set color to red]
  END 
  PATCH_IF (%proficiency% = long sword) BEGIN
    [add slashing damage]
  END 
  PATCH_IF (%proficiency% = bastard sword) BEGIN
    [add crushing damage]
  END ELSE BEGIN
    [give AC bonus]
  END
BUT_ONLY
I want any item with %type% = sword and %proficiency% = katana or scimitar or short sword etc. to be colored red and give an AC bonus. In other words the ELSE should an alternative to anything involving %proficiency%, but should work in concert with the section involving %type%. Will the above code confuse Weidu?
Link to comment

It depends on what you want to express with your code.

This code construct is guaranteed to execute only one of the available IF/ELSE blocks:

SET x = 1
PATCH_IF (x = 1) BEGIN
  // block executed
  SET x = 2
END ELSE PATCH_IF (x = 2) BEGIN
  // block NOT executed
  SET x = 3
END ELSE PATCH_IF (x = 3)
  // block NOT executed
  SET x = 4
END ELSE BEGIN
  // block NOT executed
  // ...
END

This code construct may execute one or more code blocks, depending on the condition:

SET x = 1
PATCH_IF (x = 1) BEGIN
  // block executed
  SET x = 2
END
PATCH_IF (x = 2) BEGIN
  // block executed
  SET x = 3
END
PATCH_IF (x = 3)
  // block executed
  SET x = 4
END ELSE BEGIN
  // block NOT executed
  // ...
END

As you can see the second construct may introduce unintended effects if you're not careful.

Btw, numeric variables don't have to be enclosed in percentages, so this code works just fine:

READ_LONG 0x1234 value
PATCH_IF (value = 77) BEGIN
END
Link to comment

Yes. It should be obvious for the first example. The IF/ELSE construct of the second example is basically only a simplified version of the first example, so the ELSE block will always execute if the IF condition evaluates to false. You can also add ELSE blocks to the remaining IF constructs of the second example. In this case all ELSE blocks will be executed, one after another.

Link to comment

The most straightforward (clear, unambiguous, readable), albeit inelegant, way to achieve this, would be to avoid the ELSE clause entirely (because it only applies to the previous IF), and instead use a variable and a final IF block.

 

For example:

 

SET DID_STUFF = 0

 

PATCH_IF (Condition A)

DO X

SET DID_STUFF = 1

END

 

PATCH_IF (Condition B)

DO Y

SET DID_STUFF = 1

END

 

PATCH_IF (DID_STUFF = 0)

DO THE THING THAT YOU WANTED TO DO IN THE ELSE CLAUSE

END

Link to comment

subtledoctor's first post had clauses that only tested one variable. His second post had clauses that test two different variables (type and proficiency). He wants a default clause that will only execute if all prior tests failed.

 

An IF, IF, IF. ELSE series (without ELSE IF clauses) will execute the ELSE clause if the preceding IF test was false, regardless of what happened with the prior IF clauses. In subtledoctor's example from his second post (type / proficiency), that could result in the ELSE clause executing even if the conditions for more than one of the IF clauses was true simultaneously (specifically, if type = swords and proficiency = long sword, color would be red, slashing damage would apply, and the ELSE clause would also fire giving AC bonus - not wanted).

PATTERN_MATCH will only execute one of the clauses - they are all mutually exclusive because they all test the same variable. This won't work if you want to test more than one variable or allow more than one clause to be executed.

I think he wants something equivalent to this:

If (condition A) // A is unrelated to B
Do X
Else If (condition B)
Do Y
Else If (condition A and B) // both A and B can be true
Do X and Y // duplicate action code from both of the clauses above
Else // condition A and B are both false
Do Z
End

An IF/ELSE IF/ELSE chain will only execute one of the clauses - they are all mutually exclusive. Unlike PATTERN_MATCH, this does allow testing different variables in each clause (each IF can test whatever you want). But to express "do 1 or more things that are not mutually exclusive, else if nothing was done, do this instead" using this format, you must test for each valid permutation of IF conditions and duplicate the actions in the clauses.

So the above example works (with IF / ELSE IF / ELSE) formulation, but you have to duplicate the "Do X" and "Do Y" actions in the "both" clause. You also have to make sure you include all permutations in the IF/ELSE IF/ELSE IF chain. The duplication of action code inside the blocks is undesirable.

 

My earlier suggestion (an IF/IF/IF chain, no ELSE, with a DID_STUFF variable to track what was done) avoids the duplication of action code, so I think it is a better solution for this kind of non-mutually-exclusive action series.

 

If I have misunderstood subtledoctor's request or if I am wrong in any particular, please tell me. Just trying to help.

Link to comment

No agb1 that is a very clear statement of exactly what I was looking for. And i can see how using a variable that way might be useful - in some circumstances. Though I don't think I need it for my intended use, now that I understand how ELSE PATCH_IF differs from merely using successive PATCH_IF clauses.

 

My intended use, not to be mysterious, is to rewrite my Yet Another Revised Armor System. i want to do something like this:

 

COPY_EXISTING_REGEXP GLOB ~^.+\.itm$~ ~override~
   PATCH_IF (SOURCE_SIZE > 0x71) BEGIN
      READ_SHORT 0x1c type
      PATCH_IF (type = 2) BEGIN
         READ_LONG 0x22 appearance
         PATCH_IF (%appearance% = 16690) BEGIN // leather armors
            READ_LONG 0x08 gen_name_strref
            PATCH_IF (%gen_name_strref% = [hide armor]) BEGIN
               [do stuff to hide armors]
            END
            PATCH_IF (%gen_name_strref% = [studded leather]) BEGIN
               [do stuff to studded leather armors]
            END
            ELSE BEGIN
               [all non-hide, non-studded treated as basic leather armor]
            END
         END
      END
   END
BUT_ONLY
From what I gather from this thread, I need to add an ELSE to the clause for studded leather.

 

Thanks folks!

Link to comment

I think he wants something equivalent to this:

 

If (condition A) // A is unrelated to B
  Do X
Else If (condition B)
  Do Y
Else If (condition A and B) // both A and B can be true
  Do X and Y // duplicate action code from both of the clauses above
Else // condition A and B are both false
  Do Z
End

 

If that was what was needed, you could remove the duplicated actions like this:

If (condition A || condition B)
  If (condition A)
    Do X
  End
  If (condition B)
    Do Y
  End
End
Else
  Do Z
End
However, the example with the type and proficiency is simpler:

 

Let's say I want to patch some items; if they are swords, I want to color them all red; if they are long swords they should do extra slashing damage, if they are bastard swords they should do extra crushing damage, and any other swords should default to giving an AC bonus. Pseudocode:

COPY_EXISTING_REGEXP_GLOB ~all items~
  PATCH_IF (%type% = swords) BEGIN
    [set color to red]
  END 
  PATCH_IF (%proficiency% = long sword) BEGIN
    [add slashing damage]
  END 
  PATCH_IF (%proficiency% = bastard sword) BEGIN
    [add crushing damage]
  END ELSE BEGIN
    [give AC bonus]
  END
BUT_ONLY

 

If (type == swords)
  Set color to red
  If (proficiency == long_sword)
    Add slashing damage
  End
  Else If (proficiency == bastard_sword)
    Add crushing damage
  End
  Else
    Give AC bonus
  End
End
Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...