Author Topic: evaluate() vs (*f)() troubles in MudOS  (Read 3748 times)

Offline Nulvect

  • BFF
  • ***
  • Posts: 127
    • View Profile
evaluate() vs (*f)() troubles in MudOS
« on: March 16, 2010, 01:26:23 PM »
So I'm trying to clean up some old code for magical weapons, and we have the following line:
Code: [Select]
x += to_int( call_other(weap, ({ (*f)(), attackers[0] }) ) );
The f variable is a function pointer which is both defined in and owned by the 'weap' object in 99.99% of cases. It is bound to the weapon using bind() whenever possible. This line works, inexplicably. Writing out (*f)() should call the function at that point, replace it with its return value (which is an int), then try to do call_other(weap, ({ 35, attackers[0] }) ) or some such which would return 0 since there's no function named 35. But it doesn't; it works, and adds the return value of the function f to the x variable, though the function does not actually get the attackers[0] as an argument.

I decided to fix this with a more easily read line:
Code: [Select]
x += to_int( evaluate(f, attackers[0]) );
Which has utterly failed to work, even if I remove the attackers[0] function argument. The function f is never called. So the code that should not be working, is, and the code that should be, is not. I've verified that the f is indeed a function pointer and not a string, double checked the man page and the code for call_other to be sure it cannot accept function pointers or ints as arguments, done several tests, and never gotten an error message. I'm baffled.

Can anyone shed some light on this from another point of view? MudOS v22.2b14, highly modified NM3 lib.

Offline hamlet

  • Acquaintance
  • *
  • Posts: 46
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #1 on: March 17, 2010, 06:25:33 AM »
I think we would need to see more code.  I can't get (*f)() to work in that context at all unless it returns a string.  both on FluffOS and v22.2b9.

Where does f get set?

Offline Nulvect

  • BFF
  • ***
  • Posts: 127
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #2 on: March 17, 2010, 10:41:34 AM »
Code: [Select]
    //Function calls for weapon specials
    if(!(f=(mixed)weap->query_hit())) return x;
    if(stringp(f)) message("my_action", f, this_object());
    else
      x += to_int(call_other(weap, ({ (*f)(), attackers[0] })));

That's the full block, but the only change I've made to the whole file is the one line I talked about.

For reference, the query_hit() and corresponding set_hit() functions in the weapon:
Code: [Select]
mixed query_hit() { return __Weapon["hit"]; }

void set_hit(mixed val) {
    if (functionp(val) && !(functionp(val) & FP_LOCAL || functionp(val) & FP_NOT_BINDABLE)) {
      function f = bind(val, this_object());
      if (functionp(f)) val = f;
    }
    __Weapon["hit"] = val;
}
(and yes, the bind() works, I set valid_bind() up to let anything rebind a function to itself)

Offline Tricky

  • BFF
  • ***
  • Posts: 189
  • I like what I code and I code what I like!
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #3 on: March 17, 2010, 01:45:20 PM »
Silly question, but have you just tried...
Code: [Select]
    //Function calls for weapon specials
    if (!(f = (mixed)weap->query_hit())) return x;

    if (stringp(f)) message("my_action", f, this_object());
    else if (functionp(f))
      x += to_int(weap->f(attackers[0]));

Tricky

Offline wodan

  • BFF
  • ***
  • Posts: 434
  • Drink and code, you know you want to!
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #4 on: March 19, 2010, 10:21:35 AM »
If anyone is going to reproduce this they'll need the function that is calling set_hit as well, there's still no sign of the actual function pointers/functions in the code you posted.

Offline Nulvect

  • BFF
  • ***
  • Posts: 127
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #5 on: March 19, 2010, 11:24:58 AM »
Tricky:
No, I haven't, mostly because I want the flexibility of being able to call any function pointer I pass in - I don't want it to have to be in the weapon itself, though that is the normal case.

wodan:
The set_hit() is called as follows, in each individual weapon, inside create():
Code: [Select]
set_hit( (: this_object(), "special_hit" :) );
Oddly enough, when I use
Code: [Select]
(: special_hit :) notation instead, it messes up combat. The function gets called, but my combat round doesn't come out and additional hits (like when wielding two weapons) don't happen at all. I'll investigate further down this path.

Offline wodan

  • BFF
  • ***
  • Posts: 434
  • Drink and code, you know you want to!
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #6 on: March 19, 2010, 02:30:54 PM »
that explains the whole thing, your first version returns the string "special_hit" which is then used in call_other for the call
which also explains why your evaluate didn't work as expected.
if you use the second version with the x += to_int( evaluate(f, attackers[0]) );
it should work as intended.

Offline Nulvect

  • BFF
  • ***
  • Posts: 127
    • View Profile
Re: evaluate() vs (*f)() troubles in MudOS
« Reply #7 on: March 19, 2010, 04:38:37 PM »
Awesome, thanks. Looks like every builder we've ever had has set them up incorrectly - probably instructed to by whoever put the calling code in. Time to fix some code (and maybe some coders too).