Adding Oangband magic realms/spellbooks. What changes do I need to make?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Elfin Jedi
    Adept
    • Mar 2013
    • 102

    #46
    I believe I want !(a || b) && !c (if monster has race flag: invisible, or temporary effect: invisible, and player is unaware; then don't detect monster without detect invisible)

    Or else (!a || b) && !c (I don't know what the effect/meaning of the "!" is)

    Comment

    • Pete Mack
      Prophet
      • Apr 2007
      • 6883

      #47
      ! means NOT. So for proposition p, codeblocks A and B
      if (p) {B}
      else {A}
      is equivalent to
      if (!p) {A}
      else {B}

      My additional point was that
      !(a || b) && !c
      is a more complex expression than the other two ways of writing it. Either put all conditions in the parentheses, or none, as I tried to show in the previous post.

      Comment

      • Elfin Jedi
        Adept
        • Mar 2013
        • 102

        #48
        Ok, so if monster does not have race flag invisible or monster timed invisible, and does not have monster flag unaware, then detect the monster. Right?

        /* Detect all non-invisible, obvious monsters */
        if (!rf_has(mon->race->flags, RF_INVISIBLE) || (mon->m_timed[MON_TMD_INVISIBLE]) &&
        !mflag_has(mon->mflag, MFLAG_UNAWARE))
        {
        /* Hack -- Detect the monster */
        mflag_on(mon->mflag, MFLAG_MARK);
        mflag_on(mon->mflag, MFLAG_SHOW);

        So, in that case !a && !b && !c means if the monster does not have a AND does not have b AND does not have c then detect it vs. !(a || b || c) if the monster does not have a OR b OR c then detect it.

        Would !a && !b && !c mean that to go undetected a monster would have to have all three flags?

        And would !(a || b || c) mean that if the monster has any of these flags it goes undetected?

        Because in that case I like !(a || b || c) better.

        P.S.

        Ok, so looking at it more !a && !b && !c also should mean having any of those flags makes it undetected, so they really are completely equivalent in effect then?

        Comment

        • Pete Mack
          Prophet
          • Apr 2007
          • 6883

          #49
          They really are equivalent. This is a standard trick--do look at that Wikipedia page for De Morgan's laws. It is likely to help you understand this kind of manipulation. (It is very common--that you ran into it right off is no accident.)
          Edit:
          If you are new to this think of AND--&&-- as multiply and OR as add* where all numbers are zero or one. So NOT x becomes 1 - x. All the math that holds for addition and multiplication holds for AND an OR in this special number system.
          * Note: 1 + x = x in this arithmetic.
          Last edited by Pete Mack; July 14, 2016, 01:11.

          Comment

          • takkaria
            Veteran
            • Apr 2007
            • 1951

            #50
            Originally posted by Elfin Jedi
            Ok, so looking at it more !a && !b && !c also should mean having any of those flags makes it undetected, so they really are completely equivalent in effect then?
            Yes, !(a || b || c) and (!a && !b && !c) are totally equivalent.

            I made this table that may or may not help show why! On the left you've got all the possible values of a, b and c. Then in the middle you have the OR version, and on the right you have the AND version and why they result in the same outcome.
            Attached Files
            takkaria whispers something about options. -more-

            Comment

            • Elfin Jedi
              Adept
              • Mar 2013
              • 102

              #51
              Ok, I looked at De Morgan's laws and the table. I think I have a basic understanding of the concept now.

              I like this one: !(a || b || c) best, it looks shorter.

              There:

              /* Detect all non-invisible, obvious monsters */
              if (!rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]) ||
              !mflag_has (mon->mflag, MFLAG_UNAWARE))
              {
              /* Hack -- Detect the monster */
              mflag_on(mon->mflag, MFLAG_MARK);
              mflag_on(mon->mflag, MFLAG_SHOW);

              Comment

              • Pete Mack
                Prophet
                • Apr 2007
                • 6883

                #52
                Cool. This kind of thing--messed up parens, negation, etc--is a very common error in beginning programming. However, the "invariant" as you have written it in your comment is misleading. It should say "detect all visible monsters that are in range". "obvious" monster is misleading. Even better, "exclude monsters that are invisible or out of range", which is the way you wrote the expression. The earlier statement describes the expression using (!a && !b && !c.)

                Here is what is meant by invariant. It is a useful concept when thinking about conditional expressions.



                edited for clarity
                Last edited by Pete Mack; July 14, 2016, 19:25.

                Comment

                • Elfin Jedi
                  Adept
                  • Mar 2013
                  • 102

                  #53
                  I looked at the invariant page some, I'll have to study it more before I can get much use out of it, but in the meantime I've changed the comment for the "don't detect" check as well as 2 more invisibility checks:

                  effects.c:1365-1374

                  /* Only detect nearby monsters */
                  if (x < x1 || y < y1 || x > x2 || y > y2) continue;

                  /* Exclude monsters that are invisible or out of range */
                  if (!rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]) ||
                  !mflag_has (mon->mflag, MFLAG_UNAWARE))
                  {
                  /* Hack -- Detect the monster */
                  mflag_on(mon->mflag, MFLAG_MARK);
                  mflag_on(mon->mflag, MFLAG_SHOW);

                  And the other 2:

                  effects.c:1441-1444

                  /* Detect invisible monsters */
                  if (rf_has(mon->race->flags, RF_INVISIBLE) || mon->m_timed[MON_TMD_INVISIBLE] ) {
                  /* Take note that they are invisible */
                  rf_on(lore->flags, RF_INVISIBLE);

                  and:

                  mon-util.c:295-302

                  /* Handle "invisible" monsters */
                  if (rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]) ) {
                  /* See invisible */
                  if (player_of_has(player, OF_SEE_INVIS))
                  {
                  /* Easy to see */
                  easy = flag = TRUE;
                  }

                  Now when I turn on the debug options and summon a Memory moss it can say:

                  "The Memory moss disappears. The Memory moss is unaffected!",

                  "The Memory moss disappears. The Memory moss disappears!"

                  and:

                  "The Memory moss disappears.".

                  However, the Memory moss stays visible the whole time.

                  I'm also going to go back and edit the messages so that it has a different message for the action of casting the spell .

                  Comment

                  • Pete Mack
                    Prophet
                    • Apr 2007
                    • 6883

                    #54
                    You need to mark the square with the memory moss for display update when an event like that happens.

                    Comment

                    • takkaria
                      Veteran
                      • Apr 2007
                      • 1951

                      #55
                      Originally posted by Elfin Jedi
                      Ok, I looked at De Morgan's laws and the table. I think I have a basic understanding of the concept now.

                      I like this one: !(a || b || c) best, it looks shorter.

                      There:

                      /* Detect all non-invisible, obvious monsters */
                      if (!rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]) ||
                      !mflag_has (mon->mflag, MFLAG_UNAWARE))
                      {
                      /* Hack -- Detect the monster */
                      mflag_on(mon->mflag, MFLAG_MARK);
                      mflag_on(mon->mflag, MFLAG_SHOW);

                      Be careful with where you put the ||s.

                      Code:
                      !rf_has(mon->race->flags, RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE])
                      is very different to

                      Code:
                      !rf_has(mon->race->flags, RF_INVISIBLE) || !mon->m_timed[MON_TMD_INVISIBLE]
                      The first one checks if the monster has the flag 'RF_INVISIBLE || the value of the invisible timer'.* The second one checks the flag RF_INVISIBLE and the timer separately.

                      To write what you want in the form !(a || b ||c), you want:

                      Code:
                      	if (!(rf_has(mon->race->flags, RF_INVISIBLE) ||
                      		mon->m_timed[MON_TMD_INVISIBLE]) ||
                      		mflag_has(mon->mflag, MFLAG_UNAWARE))) {
                      Does that make sense?

                      Oh, and in answer to your previous comment, in the UK at least we call {} curly braces.

                      * If you want to understand what this expression actually does, here's an explanation. The way || works in C is that if either side of the OR are not zero, it evaluates to 1. Otherwise it evaluates to 0.

                      So in the expression
                      Code:
                      RF_INVISIBLE || mon->m_timed[MON_TMD_INVISIBLE]
                      RF_INVISIBLE is the internal number for the flag. All valid flags have a number above 0 (0 is used to mean 'no flag'), so RF_INVISIBLE will be above 0 too. The expression will thus evaluate to 1.

                      Flag 1 is the UNIQUE flag (you can see this yourself in list-mon-race-flags.h.) So the check will actually only activate when the monster is not a unique.
                      takkaria whispers something about options. -more-

                      Comment

                      • Pete Mack
                        Prophet
                        • Apr 2007
                        • 6883

                        #56
                        Whoops, sorry I missed that.

                        Comment

                        • Elfin Jedi
                          Adept
                          • Mar 2013
                          • 102

                          #57
                          Ok, I changed it.

                          Then I tested it to see whether it would detect Memory mosses (either invisible or visible) when they were out of LOS (which I didn't think to do before changing it) and found that Detect Monsters isn't detecting monsters at all now. Even when there are monsters (like a band of filthy street urchins) just on the other side of a wall.

                          Now I am confused.

                          Edit: But changing it back to what I had before works.

                          Comment

                          • Elfin Jedi
                            Adept
                            • Mar 2013
                            • 102

                            #58
                            This time I copied and pasted, and it gives me this error:

                            effects.c: In function 'effect_handler_DETECT_VISIBLE_MONSTERS':
                            effects.c:1370:40: error: expected statement before ')' token
                            mflag_has(mon->mflag, MFLAG_UNAWARE)))

                            Edit: Going to look up statement. Be back soon.

                            Comment

                            • Elfin Jedi
                              Adept
                              • Mar 2013
                              • 102

                              #59
                              Does it not recognize the c conditional as part of the if statement?

                              Comment

                              • Pete Mack
                                Prophet
                                • Apr 2007
                                • 6883

                                #60
                                Sure. But the negation has to apply to the entire expression, not just one term in the expression. So you need the parentheses to specify evaluation order, otherwise ! will have higher precedence (I.e.will evaluate first) than ||. Precedence really matters.

                                Comment

                                Working...
                                😀
                                😂
                                🥰
                                😘
                                🤢
                                😎
                                😞
                                😡
                                👍
                                👎