rickparrish / Usurper

32 and 64bit ports of Usurper BBS door game version 0.20e
78 stars 18 forks source link

Zero hitpoints when levelling up, after choosing a different master #31

Open ndoody opened 1 year ago

ndoody commented 1 year ago

Hi, I'm on a BBS and they seem to be running version 0.25 compiled Dec '22.

I had chose a new master, Apollonia, I am a dwarf of Barbarian class. As soon as I choose the new master, I do not receive any hit points when I level up?

I did look through the code, excuse me for never seening pascal before, but my light understanding is that i represents hitpoints we should level up with. When we're a Barbarian i has a baseline of 7, which in the proceeding loops by the default master should be 7 hitpoints per level up. I note that if we change to Apollonia we have inc(i, 2) which if I understand correctly should increment i by 2 (so now we should be at 9?) and then loop through adding an extra 2 for each level up.

I have done a load of steroids, so I notice that anything under 70 for mental stability is punished with dec(i) which should deduct one. If I'm not mistaken again, we should get 8 hitpoints per level right?

What I'm actually getting is zero points per level, this happened for 4 levels so I switched back and now I'm getting 6 which would be the baseline minus the punishment for having a low mental stability.

So, is this a bug? I also tested on another BBS that is running the same version, compiled in Aug '21 and it's the same behaviour.

rickparrish commented 1 year ago

I'd need to actually step through to confirm, but at quick glance this looks like an off-by-one bug.

In LEVMAST.PAS the master array is [1..10], and Apollonia is the 6th element in that array.

But then in VARIOUS2.PAS the Raise_Player procedure's switch statement that deals with the master goes from 1 to 9, and Apollonia is 5 instead of 6.

So assuming there's no other math I'm missing when reading or writing the master values to account for this off-by-one setup, when you level up you're getting the logic in the 6th case statement, which is for Sachmez. This case statement sets i to 1, which is later decremented due to your mental health, resulting in no HP given.

If you have time to test, please set your master to Agni and see if that gives you the increase you're expecting. They're the 5th master in LEVMAST.PAS, so should be treated as Apollonia in VARIOUS2.PAS

ndoody commented 1 year ago

Thanks, I'd definitely like to learn more...I will try some alternate masters when I get a level up and money available to do so (starting to get expensive to change lol).

I did change to Gregorius and I notice I was getting 6 hitpoints per level, I would have expected to get minimum of 8. So does that suggest it's actually possibly Akrappa who is leaving i as default, the baseline for my class is 7 and then deduct 1 for my mental health leaving 6?

I'm looking through the code and trying to see exactly what you're seeing, can you quote parts of it so I can zoom in? Interested to understand pascal a little more, I've never written or used it...c# is about as close as I get.

rickparrish commented 1 year ago

There are three bits of code that are important to look at:

First off, we want to know what the user is seeing when they choose the master. That's happening here: https://github.com/rickparrish/Usurper/blob/9c205f60c105f09618bac8c772e27d6311ae8ca5/SOURCE/USURPER/LEVMAST.PAS#L173

So we can see that the hotkey 1 is linked to element 1 in the master array, hotkey 2 with master element 2, etc, and the only exception to this rule is hotkey 0 which matches master element 10.

Then if we look at the master array, we can see that Apollonia is element 6: https://github.com/rickparrish/Usurper/blob/9c205f60c105f09618bac8c772e27d6311ae8ca5/SOURCE/USURPER/LEVMAST.PAS#L42

So going back to that first link it means Apollonia would be displayed as hotkey 6, and further down in the method when it saves your new master, it would save the value 6.

Then the last bit of code to look at is the bit I think you've already seen, since you talked about the i variable and the mental health penalty, etc: https://github.com/rickparrish/Usurper/blob/9c205f60c105f09618bac8c772e27d6311ae8ca5/SOURCE/USURPER/VARIOUS2.PAS#L1594

This case statement runs from 0 to 9, which in theory is correct because those are the 10 possible values for the 10 different masters, but Jakob didn't line things up correctly with the master array, so in case 0 he's treating that as Akrappa, but based on what we saw in the previous links master value 0 is actually Gregorius. And in the case of Apollonia, selecting that would have stored a master value of 6 for your user, but when levelling up case 6 is instead Sachmez, resulting in the wrong attribute changes.

As for your change to Gregorius, what you described is exactly what happened, because Gregorius's hotkey is 0, and the case 0 statement is for Akrappa.

Earlier today I pushed an update to fix this, so if you let your sysop know there's a new pre-release version they'll be able to update and fix this bug.

ndoody commented 1 year ago

Perfect, thank you...I was looking in all the right places and I definitely got the waiting for keypress loop / selecting master and array from 1 to maxmasters where maxmasters = 10, so 1..10. I just didn't really get that switch/case statements relied on an order and the index would change the place rather than just taking the literal input value.

Would we get the same behavior in visual basic or c#, or something specific how it works in pascal? I don't recall it, but I'm not developer I just bits and pieces.

Thankyou for your explanation, I definitely get it...I was 99% there I think, I had just glazed over the exact code you've posted and I didn't twig it.

rickparrish commented 1 year ago

Sorry I didn't word that explanation well. The switch/case statements don't rely on order, so he could have handled case 5 first then case 3 next, etc.

The issue is that there was a mismatch between the code that saves your new master, and the code that adjust attributes when levelling up.

When you selected Apollonia as your master, you pressed 6, so your user record was updated with master=6.

Then when you levelled up, the case happy.master of line checked your current master value (happy is the variable holding your user record), which would still be 6.

That means the code in case 6 ran, but Jakob had that case set for Sachmez instead, so the wrong attribute changes were made.

ndoody commented 1 year ago

Ahh, I absolutely see see it now...as I looked at the historic code and your commit. 0 was akrappa but would be stored as 1 when you select 1 for your master, if choosing akrappa but were awarded for Singuman.

So in old/broken code I would choose 9 for Asanga, which would store 9, then I would be awarded the stats of gregorius whose case is 9 I believe?

Alright, well thankyou for supporting this after all these years.

I have some gameplay questions, but I don't think a gitlab forum is the right place for it - I'm questioning for example when we bring team members to the dungeons, why they don't use their own weapon and why the goolies seem to ignore their armor. Where's a good place to start that discussion?