17 Feb, 2009, boblinski wrote in the 1st comment:
Votes: 0
Hi there, as you will probably tell.. I'm new to coding..

bool can_see (CHAR_DATA * ch, CHAR_DATA * victim)
{
/* RT changed so that WIZ_INVIS has levels */
if (ch == victim)
return TRUE;

if (get_trust (ch) < victim->invis_level)
return FALSE;


if (get_trust (ch) < victim->incog_level
&& ch->in_room != victim->in_room) return FALSE;

if ((!IS_NPC (ch) && IS_SET (ch->act, PLR_HOLYLIGHT))
|| (IS_NPC (ch) && IS_IMMORTAL (ch)))
return TRUE;

if (IS_AFFECTED (ch, AFF_BLIND))
return FALSE;

if (room_is_dark (ch->in_room)
&& IS_AFFECTED (ch, AFF_INFRARED))
return FALSE;

if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& !IS_AFFECTED (ch, AFF_DETECT_INVIS))
return FALSE;

return TRUE;
}


1) "ch" is the player trying to see people?
2) "victim" player that isn't able to be seen?

3) how do I make this last section compare levels and if the players level is too low, they can't see through the invis (even with detect_invis?
– am I even close with this–>

if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& !IS_AFFECTED (ch, AFF_DETECT_INVIS)
&& ch->level >= victim->level))
return FALSE;
17 Feb, 2009, Scandum wrote in the 2nd comment:
Votes: 0
boblinski said:
3) how do I make this last section compare levels and if the players level is too low, they can't see through the invis (even with detect_invis?

You mean the spell level?

I think the alanthia codebase has this added, you could look at its source code which is in the rom dir in the code repository.
17 Feb, 2009, boblinski wrote in the 3rd comment:
Votes: 0
Scandum said:
You mean the spell level?


I want it to compare Player levels..

So.. if player 'Bob' is invis and level 40… then anyone level 39 and below CaNnot see him.

But if Bob is invis and level 40… anyone level 40 and above WITH detect_invis affect… CaN see him.
17 Feb, 2009, Stormy wrote in the 4th comment:
Votes: 0
if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& (!IS_AFFECTED (ch, AFF_DETECT_INVIS)
|| ch->level < victim->level))
return FALSE;


I think this is what you're looking for.
17 Feb, 2009, boblinski wrote in the 5th comment:
Votes: 0
That worked. I'm now trying to add in an INT check… ie- the characters INT needs to be the same or higher to be able to see invis people…

This is what I did..
if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& (!IS_AFFECTED (ch, AFF_DETECT_INVIS)
|| ch->level < victim->level)
|| (get_curr_stat(ch, STAT_INT) < get_curr_stat(victim, STAT_INT)))
return FALSE;


It seems to work, but I get this when I boot up-
$ make
gcc -Wall -O -ggdb -DNOCRYPT -DQMFIXES -c -o obj/handler.o handler.c
handler.c: In function `can_see':
handler.c:2650: warning: suggest parentheses around && within ||
rm -f rom
17 Feb, 2009, Sharmair wrote in the 6th comment:
Votes: 0
The warning is basically warning you that you are using a syntax that the writer of the compiler
thinks is not well understood by the coder and might not be what is intended. In this case the
precedence order of && and || (&& has a higher precedence) so it is suggesting that you put
parentheses around it to make it clear to someone looking at the code what you really mean.

It is probably a good thing it gave the warning, as the code probably is not working the way you
intended in this case (unless you do in fact intend a character to not be able so see someone of
a higher int invis or not). What you are saying here is: the looker can't see the victim if case1
OR case2 where case1 is the invis check you had before and case2 is if the looker has less int
then the victim with no relation to invis at all. You probably want to move that last || into the
() with the other || like:
if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& (!IS_AFFECTED (ch, AFF_DETECT_INVIS)
|| ch->level < victim->level
|| (get_curr_stat(ch, STAT_INT) < get_curr_stat(victim, STAT_INT))))
return FALSE;

In review, replacing your terms with letters, what you were doing is
if (a AND (b OR c)) OR d
but what you probably intended is
if a AND (b OR c OR d)
17 Feb, 2009, boblinski wrote in the 7th comment:
Votes: 0
Will that section stop people seeing invis people if their INT is too low?
17 Feb, 2009, David Haley wrote in the 8th comment:
Votes: 0
What exactly do you want the code to do? (Is the difference between the two parenthesizing methods clear?)
17 Feb, 2009, boblinski wrote in the 9th comment:
Votes: 0
no. i don't see the difference between || and && sorry.

I want this code to check if someone can see an invis person.
the things that must be true for a ch to see a victim are–>

vict must_have- AFF_DETECT_INVIS
ch level >= vict level
ch INT >= vict INT


Sorry if I'm unclear. I'm still getting used to explaining code problems and presenting them clearly.
17 Feb, 2009, David Haley wrote in the 10th comment:
Votes: 0
&& means "and". That is, a && b is true if both a and b are true.
|| means "or". That is, a || b is true if either (or both) a or b are true.

&& has higher precedence than ||, so a && b || c is true if either (or both) a&&b or c are true.
That is different from a && (b || c), which is true if both:
(1) a is true
(2) either b or c is true (or both)

So the first thing you need to do is explain in English what you want your condition to be. For example,
A cannot see B if:
(1) B is invisible
AND
(2a) A has lower level than B
or
(2b) A has lower intelligence than B
etc.
17 Feb, 2009, Hades_Kane wrote in the 11th comment:
Votes: 0
&& basically means "and" while || basically means "or"

I think this is what you want:

if(IS_AFFECTED(victim,AFF_INVISIBLE)
&& (!IS_AFFECTED(ch,AFF_DETECT_INVIS)
|| (IS_AFFECTED(ch,AFF_DETECT_INVIS)
&& ch->level < victim->level
|| get_curr_stat(ch, STAT_INT) < get_curr_stat(victim, STAT_INT))))
return FALSE;


So this is how I would explain how this works:

if (victim is invisible)
AND
(ch doesn't have detect invis) OR (ch DOES have detect invis, but [<ch is too low level> OR <ch has too low int>]
then return false

I might not have explained it very well, but from what you have described, that seems to be what you are after. If you still don't understand -how- what I wrote works, then I would encourage you to say so, so that maybe someone else a little better at explaining these things can help you understand how it works, because understanding -how- is vital to you being able to solve problems like this on your own in the future. As you may be able to tell, the positioning of your parentheses is crucial in getting the code to understand how you are wanting all of the 'and's and 'or's to be handled.

Hope I helped!
18 Feb, 2009, Sharmair wrote in the 12th comment:
Votes: 0
The code I gave in my last post should do what you want. Here, I will post it again:
if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& (!IS_AFFECTED (ch, AFF_DETECT_INVIS)
|| ch->level < victim->level
|| (get_curr_stat(ch, STAT_INT) < get_curr_stat(victim, STAT_INT))))
return FALSE;

The code Hades_Kane gave should also work, but has an unneeded term and will probably
give that same warning you were getting before. To attempt to explain it better, I will give
some logic formulas using && as AND, || as OR, Vi as your victim invis term, Ld as your looker
having detect invis, Lll as your looker having lower level term, Lil as your looker having
lower int and ! meaning NOT.
The code I have here would be:
Vi && (!Ld || Lll || Lil)
The code Hades_Kane gave would be (as written):
Vi && (!Ld || (Ld && Lll || Lil))
In that most inner () you have both an && and ||, and that is the same syntax that was giving
you the warning before (though in this case, the evaluation with or without the suggested ()
will be what you intended). I will put them in here to show the order of evaluation:
Vi && (!Ld || ((Ld && Lll) || Lil))
Now, in that first level of () we have:
!Ld || ((Ld && Lll) || Lil)
That is an OR of two terms. If that !Ld is true, this part of the expression is known to be true,
so the rest will not be evaluated. So the right part will only be evaluated if !Ld is false, and
that means Ld is true, so that is not needed. A true AND anything will be the anything, so
you can write the full expression as:
Vi && (!Ld || (Lll || Lil))
And that inner level of () are unneeded so it will become:
Vi && (!Ld || Lll || Lil)
The same logically as the code I gave here.

Another way that can make figuring this type of thing out is looking at the reverse condition.
for the case the looker CAN see (based on invis in this case) the victim would be:
!Vi || (Ld && Llhe && Lihe)
Which would read as: the looker can see the victim if the victim is not invis (again note this
is only the part about invis) OR the looker has all three conditions of having detect invis AND
having higher then or equal level AND having higher then or equal int. Some times it is easier
to figure it out one way then reverse the logic. You switch the && and ||, add or take away !
from true/false terms and use the reverse arithmetic conditionals.

I hope this was somewhat helpful in explaining a bit about how all this works, but don't be
afraid to ask if something is still unclear.
23 Feb, 2009, boblinski wrote in the 13th comment:
Votes: 0
I've been attempting to add in a system wherein it compares characters INT, and for each INT -difference- there is less chance of a character seeing the player.

This is where I am at the moment, but it's currently not working..

if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& (!IS_AFFECTED (ch, AFF_DETECT_INVIS)
|| ch->level < victim->level
|| (((get_curr_stat(victim, STAT_INT) - get_curr_stat(ch, STAT_INT)) * 10) < number_percent())))
return FALSE;


For each INT the the ch has -less- that the victim.. I want 10% -less- chance of seeing the player.

IE: victim_INT=20, ch_INT=20… chance of seeing=100%

victim_INT=20, ch_INT=17… chance of seeing=70%
23 Feb, 2009, KaVir wrote in the 14th comment:
Votes: 0
boblinski said:
For each INT the the ch has -less- that the victim.. I want 10% -less- chance of seeing the player.

It'll look like a bug if you do that, as the person's name will randomly be displayed as "someone" every so often. If you want variable strength invisibility I suggest using fixed numbers, or - if it really must be random - randomise it when the spell is cast.
23 Feb, 2009, boblinski wrote in the 15th comment:
Votes: 0
It'll look like a bug if you do that, as the person's name will randomly be displayed as "someone" every so often.
Quote
Why does it do this? Is there no way to fix it?
23 Feb, 2009, KaVir wrote in the 16th comment:
Votes: 0
It does it because you're randomly deciding each time whether or not to display the invisible player's name - so sometimes their name will show up, and sometimes you'll just see "someone". One solution to avoiding it is, as I suggested, to use fixed numbers. That way you either see someone or you don't, it doesn't keep changing every time their name pops up.
23 Feb, 2009, boblinski wrote in the 17th comment:
Votes: 0
Do you think you could explain in a little more detail?

//

I'm currently using the following:
if (IS_AFFECTED (victim, AFF_INVISIBLE)
&& (!IS_AFFECTED (ch, AFF_DETECT_INVIS)
|| ch->level < victim->level
|| (((get_curr_stat(victim, STAT_INT) - get_curr_stat(ch, STAT_INT)) * 10) > number_percent())))
return FALSE;


I tested on my mud and got the following results:
Quote
The Void
You are floating in nothing.

[Exits: none]
(Invis) Wizas the Master Mage is here.

<14732hp 9826m 10826mv> look

The Void
You are floating in nothing.

[Exits: none]
(Invis) Wizas the Master Mage is here.

<14732hp 9826m 10826mv> look

The Void
You are floating in nothing.

[Exits: none]
(Invis) someone the Master Mage is here.

<14732hp 9826m 10826mv> look

The Void
You are floating in nothing.

[Exits: none]

<14732hp 9826m 10826mv> look

The Void
You are floating in nothing.

[Exits: none]
(Invis) someone the Master Mage is here.

<14732hp 9826m 10826mv> look

The Void
You are floating in nothing.

[Exits: none]
(Invis) Wizas the Master Mage is here.

<14732hp 9826m 10826mv> look

The Void
You are floating in nothing.

[Exits: none]
(Invis) Wizas the Master Mage is here.


Please note:
Wizas has 20 INT
The 'look'ing char has 18 INT
Both are of equal level.
23 Feb, 2009, Sharmair wrote in the 18th comment:
Votes: 0
Well, I think your output pretty much shows the issue he was talking about. In your
example you have an 81% chance of seeing the victim on EVERY check made, so in
most cases you see the victim ok, but sometimes the check (there seems to be more
then one check made on each look) for if you can see a character in the list goes ok,
but the check for name fails and you see someone, and once in your example the
check for list visibility failed and you saw nothing at all.

You could make it work more consistently a few ways. If I was going to do something
like this, I would use a consistent random number probably based on the victim and
room. This random number would return the same random number for the same looker
looking at a specific victim in a specific room. The code I work with already has the
code for this, and is used for things like picking locks and such.

You could also keep track of the first check made and use that for every time the
code checks for visibility, but keeping track of the numbers for different lookers vs
victims per spell use might be a bit more complex then what you are ready for yet.

Oh, if you wanted this example to be 80% that > should be >=.
23 Feb, 2009, Hades_Kane wrote in the 19th comment:
Votes: 0
If seeing someone invis was random or not, I'd just spam "look" a whole bunch of times until I could see the person, or spam "kill <character>" until the game randomly decided that I could pass the check to see them.

So doing that would basically be defeating the purpose of it with there being such an easy way around it. That might be something you want to consider.
23 Feb, 2009, KaVir wrote in the 20th comment:
Votes: 0
boblinski said:
Do you think you could explain in a little more detail?

I mean that it'll keep alternating between their name and "someone", which would look really odd. Imagine a fight scene like this:

You stare at someone, your crystalline eyes glimmering with malice.
Bob the spectral dragon mentally blocks your dread gaze.

You swing at Bob the spectral dragon's face with your tetsubo warclub.
Someone flies under your bash.

Someone swings at your left arm with his front left foot.
His claws bounce harmlessly off your crystalline skin.
Bob the spectral dragon rakes the claws of his front right foot down your right arm, scratching crystal.

Bob the spectral dragon coils his long tail tightly around your chest.
someone squeezes his tail around your chest, cracking ribs.


Perhaps invisibility wears off during combat for you, but the same scenario could occur during a conversation (is there an invisible imm talking with you in the room, or is that your friend who occasionally appears as "someone"?).

I think it's just less confusing if the detect vs invis always has the same outcome for any particular casting of the spell. If you want to add a random element, then just add a small modifier to the strength of the invisibility, so that sometimes your invisibility spell is more effective than other times.

So if your detect strength >= their invis strength, you can always see them. But the invis strength varies each time you cast the spell. You could instead do this with detect invis, or even both.
0.0/24