Jump to content
NHL'94 Forums

Recommended Posts

Posted

For those who don't want to watch me ramble for over an hour on my stream (btw stream is here - https://www.twitch.tv/videos/2120586640)

Using the source code from 92 (Link - NHL Hockey Source Code), we are now able to find out how things work a lot easier than finding a needle in a haystack like we had done in the past. NHL94 has improved upon 92, but much of the code is the same (with some refinements and added things, like bonuses). The most important thing is we have an idea how the RAM is laid out (basically all the variables for the game).

 

How does checking work in 94?

Weight is involved. Where you are on the rink is involved (You're getting checked against the boards? You're getting knocked down). Checking rating is involved. Also, impact value is involved (how hard you are hitting depending on your velocity and your opponents velocity, and the distance between the 2 of you). Are you controlling the player checking, or is the AI?

Also, the weight bug (lets lighter players check heavier players, regardless of a lot of factors above) - 

 

 

Here's the checking formula for 94:

Check if checking player is in checking animation
If impact value is more than 20 decimal, the check will initiate. If not, there will only be momentum transferred between the 2.

Starting value for calculation (120 decimal or 240 decimal if player controlled)

- Subtract (Wgt * 8) of player checking
- Add (Wgt * 8) of player being checked
- Divide total by 2
- Check if player will hit the wall (see below)
- Subtract impact value

- If the total is 0 or negative, proceed to knock down.
- If total is positive, then check if player will hit wall. If he will, proceed to knock down.

- If total was positive, and player is not near a wall, then randomize the result from above (the RNG will choose a number >= 0 and < result from above)

- Load the checking attribute (which is Chk rating * 5 + bonuses (Hot/Cold and 3rd Period Bonus). Divide it by 2 (Value will be between 0 and 15)
- Next, subtract Checking value from above from the RNG result. If the answer is <= 0, then proceed to knock down. If positive, then check Agression attribute and see if there will be a penalty from the hit.

Knock down section also checks for penalty from contact, but there is slightly less of a chance of a penalty compared to them not getting knocked down. After this part of the code, it will check for toddle (related to stickhandling).

 

This checking formula is almost the same as it is in 92, except for the fact that some math is different (there's no bonuses, attributes are on a 0-15 scale instead of 0-6), the starting value for ALL checks is 60 decimal. In 94, the attributes are stored in RAM with a 0-30 scale (which is why you see a divide by 2 in a few places here).

What's the weight bug problem?  Lighter player can check heavier players with ease, when player controlled. This is because of the large boost given to the starting value. The subtracting and adding of the weight in this formula is done "byte" size, which means that value can never be over 255, it will overflow and 256 = 0 (it will start over at 0). Because of this, the rest of the calculation is pretty much thrown out the window (impact value will play a very small role in a weight bug check).

 

So how to fix the weight bug? Remove the boost to the starting value when player controlled. 

I believe this may have been left in during testing, since the formula itself is almost the save as in 92. If the starting value was set to 120 decimal for both AI and player controlled checks, we would see much more "realistic" results. Weight difference won't be a huge factor anymore (still a bit of a factor), but impact and checking attribute would play more of a role. 

 

What's impact value?

This is something I was able to figure out using the source code. The game tracks the velocity of the players (speed + direction). When it senses 2 players are close enough for contact, it will calculate a transfer of momentum between the players (when players hit, they slow down, bump each other back, etc). So it will calculate impact based on the velocity of both players, and the distance between them. The players speed is controlled by their acceleration, which in turn is controlled by Wgt and Agl attributes. So the faster a player is going, the more impact they will cause. If 2 skaters are skating at each other, the impact will be higher. If a player getting checked is skating away from the checker, the impact will be lower. If you hit the player near the end of your speed burst, the impact may be lower (not going as fast as you originally were). 

Funny thing is even with the weight bug, its actually harder for Theo Fleury (3 wgt) to check Marty McSorley (14 wgt), than it would be for him to check someone like Mats Sundin (7 wgt). He needs some impact to check Marty, where as with Mats, as long as he meets the minimum impact value to initiate the checking calculation, hes knocking him down.

Here are some examples with weight and impact:

Screenshot 2024-04-15 at 3.32.37 PM.png

4 wgt checking (player controlled) a 10 wgt with minimal impact just makes it to the knock down phase (-4). 4 wgt AI player can do it with a ton of impact though (and some RNG luck).

 

Screenshot 2024-04-15 at 3.34.35 PM.png

Closer weights here. 5 wgt AI checking a 7 wgt player with 50 impact value can definitely have a shot with some RNG luck (RNG result would be between 0 and 18 here), then subtracting the Checking attribute (0-15 scale after divide by 2). 

 

Screenshot 2024-04-15 at 3.39.43 PM.png

Marty McSorley might be able to survive this check from Theo Fleury with the right RNG and minimal impact.

 

Screenshot 2024-04-15 at 3.41.46 PM.png

AI controlled Mario Lemieux might struggle knocking down Mike Gartner with low impact. Gotta get a good RNG roll (low value here).

  • Love 2
  • Thanks 5
  • Wow 2
Posted
7 hours ago, AdamCatalyst said:

How does altering the RNG variance affect this?

 

The RNG function needs a value sent to it and returns a result. In the Hot/Cold thread, you are only changing the value being sent to the RNG function for Hot/Cold.

The RNG function has 2 different ways it can be used:

- Sending it a value, and it will give a result of (- value <= result < value)

- Sending it a value and it will give a result of ( 0 <= result < value)

 

Hot/Cold uses the first way, Checking is using it the second way. The RNG function is used all over the place. 

  • Thanks 1
  • 3 weeks later...
Posted

Could it be a potential alternative weight-bug fix to change the starting bonus value for a user controlled player from 240 to 120? And if so, do you have a sense of where that 240 might be in the assembled code?

Posted
4 hours ago, AdamCatalyst said:

Could it be a potential alternative weight-bug fix to change the starting bonus value for a user controlled player from 240 to 120? And if so, do you have a sense of where that 240 might be in the assembled code?

Yes, it would make (in my opinion) checking the way the game was intended. 

You can change 0x13D70 and 71 from E3 40 to 4E 71 (No Operation). This would overwrite the step where it makes it 240

  • Thanks 1
Posted
16 hours ago, chaos said:

Yes, it would make (in my opinion) checking the way the game was intended. 

You can change 0x13D70 and 71 from E3 40 to 4E 71 (No Operation). This would overwrite the step where it makes it 240

Thanks for this! Going to start play testing this mod. I certainly agree with your inference, that this may have been what was intended, and at the very least, seems to revert the logic to be similar enough to '92.

  • Like 1
  • 7 months later...
Posted
On 5/7/2024 at 1:15 PM, AdamCatalyst said:

Thanks for this! Going to start play testing this mod. I certainly agree with your inference, that this may have been what was intended, and at the very least, seems to revert the logic to be similar enough to '92.

@chaos This may be a daft question, but lately I've been play testing the above fix, and I'm struggling to tell if it is working as intended. Any quick thoughts on an experiment to prove it's behaving as we'd hope?

Posted
2 hours ago, AdamCatalyst said:

@chaos This may be a daft question, but lately I've been play testing the above fix, and I'm struggling to tell if it is working as intended. Any quick thoughts on an experiment to prove it's behaving as we'd hope?

Should be much harder for lighter guys to check heavier guys. Heavier guys should be able to check lighter guys

Posted

I don't know where my brain is at. Just change the ratings on some players, all min or max weight. Should be pretty clear. Thanks man. And Happy New Years to you!

  • Like 1
Posted

An Experiment

Hey man, so I've been playing with the aforementioned fix, and ran a few tests this morning. I thought you might be interested in the results.
 


Methods

Six different demos were run with the Control Group, three different demos Run with the Checking group, three different demos run wth the Weight group.

Control Group

  • using my v3.0 Beta.
  • demo mode.
  • using default teams of EDM & FLA (YES, I know the was a mistake, should have been same team vs same team)
  • 5 minutes
  • Penalties ON
  • Line changes OFF

Checking Group

  • Set EDM to 0 Checking for every player
  • Set FLA to 15 checking for each player.
  • No other changes from Control Group.

Weight Group

  • Set EDM to 0 Weight for every player
  • FLA to 15 Weight for each player.
  • No other changes from Control Group.
      

Results

Control Group

44 EDM Body Checks

49 FLA Body Checks
 

Checking Group

04 EDM Body Checks

58 FLA Body Checks
 

Weight Group

09 EDM Body Checks

31 FLA Body Checks

 


Conclusion 

Chaos's inferences seem spot-on. With the restored code, the Control Group had an asymmetry in Body Checks Thrown of approximately 1 to 1.11. Weight attribute asymmetry had a substantial effect, changing this ration to 1 to 3.44 (~300% increase). Checking attribute asymmetry had a massive effect on Body Checks asymmetry, changing the ratio to 1 to 14.50 (~1300% increase). While the experiment had a less than ideal sample size, and more variables could have been controlled, the effect size is substantial enough to confirm that this fix works as described by Chaos. However, because the sample size was so small, do not infer anything else from these numbers, regarding total checks per game, etc.

 


Appendix

Control Group screen-caps.

image.png

 

Checking Group (top row) / Weight Group (bottom row).

image.png

  • Love 2
Posted
On 5/6/2024 at 8:37 PM, chaos said:

Yes, it would make (in my opinion) checking the way the game was intended. 

You can change 0x13D70 and 71 from E3 40 to 4E 71 (No Operation). This would overwrite the step where it makes it 240

Agreed, my original fix was wrong. This new fix also fixes(eliminates) the CB check, right?

Posted (edited)
33 minutes ago, smozoma said:

Agreed, my original fix was wrong. This new fix also fixes(eliminates) the CB check, right?

Your improved weight bug fix wasn't wrong, it was the best solution we had for nearly two decades, improving the quality of countless games played.
 

Just because I am trying to understand code better, some hypothetical questions. Here is the original code.

082B 0003 0062 6700 0004 E340


The C B bug fix removed the branch after the Test.

082B 0003 0062 4E71 4E71 E340

 

The new weight bug fix removes the Bit Shift that doubles the value from 120 to 240.

082B 0003 0062 6700 0004 4E71

 

If I understand correctly, couldn't all this code be changed to No-Op?

Edited by AdamCatalyst
Posted
2 hours ago, AdamCatalyst said:

Your improved weight bug fix wasn't wrong, it was the best solution we had for nearly two decades, improving the quality of countless games played.
 

Just because I am trying to understand code better, some hypothetical questions. Here is the original code.

082B 0003 0062 6700 0004 E340


The C B bug fix removed the branch after the Test.

082B 0003 0062 4E71 4E71 E340

 

The new weight bug fix removes the Bit Shift that doubles the value from 120 to 240.

082B 0003 0062 6700 0004 4E71

 

If I understand correctly, couldn't all this code be changed to No-Op?

What the CB check fix does is just make all checks starting with the 240 base value.

The fix above removing the bit shift makes all checks use the 120 value.

You can 4E71 all of that if you want, and get the same effect as removing the bit shift

 

Posted
3 hours ago, smozoma said:

Agreed, my original fix was wrong. This new fix also fixes(eliminates) the CB check, right?

It would just make everything like a CB check, since CPU and player would use the 120 decimal as a base instead of the 240 for the player.

Also, lighter wgt players can still have a chance of knocking down heavier players if checking at speed. This would increase the impact of the check, and also use the Chk rating and RNG.

Posted

All this cool talk about new found knowledge and... Is it just me wondering if I can exploit this to make the CPU controlled players even more likely to throw the body?

Posted

Almost certainly, yes. Feed Claude.ai the code, and I suspect it will be able to isolate a key variable or equation that you can manipulate. 
 

 

  • 3 months later...
Posted

This is all great work, chaos. Thanks for all the clarification behind the scenes as well.

I would like to share what is hopefully an extension of what chaos has explained, that may be extra helpful to those who are more visual-based.

I've made a spreadsheet where one can just plug in the checking rating of the player doing the checking (and the impact number), and you can see on four color-coded graphs the likelihood of an open-ice check being successful. 

See it here: https://docs.google.com/spreadsheets/d/1VGPJbZE5Dlk87E0yK8JKRB0EMgrU1svd/edit?usp=drive_link&ouid=111094358044569353347&rtpof=true&sd=true

Before I begin explaining all of this, please remember that any time I use an actual number, I am describing the results with the parameters of a player whose Chk rating is 3, and with an impact value of 20. These are factors that you can play with in the spreadsheet.  Chaos has advised that the impact value is unknown, but has a minimum value of 20. We also know that the way the formula works is that higher speed leads to higher impact and a greater likelihood of a check. You can see how this changes as you play with the impact value. I have no idea what the maximum is and what would be a high or average value. I don't know if the range is from 20 to 30, or from 20 to 200. I can see, though, that for a player with a 1 checking rating, it only takes a 122 impact to change all four tables to full green. For a player with a 6 checking rating, 109 would do it. Since there should be no impact value that results in a guaranteed 100% hit, I would suspect that impact values do not exceed 100.

As you can see in the top-left table, the way that the game calculates the likelihood of a hit by a human-controlled player is, for lack of a better term, absolutely fucked. If it was as simple as, "the lighter you are, the better you are at hitting, and the heavier you are, the easier it is to knock you down", that would be easy to understand and follow a pattern that makes logical sense, even if it is completely counterintuitive. In fact, I believe a lot of us believed that for a very long time - I did until just a few days ago. But, as you can see on the top left hand graph, in the stock ROM, players have little to no chance of knocking over their own weight, one above, or lighter, but that immediately spikes to guaranteed success at +2 to +8 before tailing off gradually. Heavier players can knock down almost no one except their heavy brethren, but paradoxically it gets slightly easier the lighter the "checkee" is. 

Being that you have that huge swath of red right next to the green cells, there's no rhyme or reason to the checking formula in stock NHL 94, other than you can count on success with a light player, because most of their hits will be laid on players 2-8 weights heavier than them. 

From there, go to the bottom left table that shows what happens if the equation is flipped so that the checkee's weight is subtracted and the checker's weight is added. Logically, one would expect that this would make the game's checking fairer. And it does..... I mean sorta? And not in a logical way at all. Look at the super light 1 weight player. He really has a hard time knocking anyone over, which is good... but he is actually slightly better at hitting heavier players than lighter. A middleweight crushes the light players, but immediately turns into a lamb when picking on someone his own size. A heavy player crushes middleweights, while having a tougher time with the lightweights. Again, we have all that red next to all that green which makes no sense. We liked to think that this simple fix would make it so that "the heavier you are, the better you are at hitting, and the lighter you are, the easier it is to knock you down" - but that is definitely not true on this table either.

Side note, these two tables are exact inverses of each other. Notice that opposite corners have all the same numbers in them. A simple WBF does make the game better when you look at the overall checking success of each weight of player (in 1st table, 1s have average success of 73, average success against of 11, while 15s have the exact opposite. In the 2nd table, those results get reversed), but it does it in a completely illogical way. The reason for this is the byte math chaos described earlier that results in numbers over 255 wrapping around to 0. The starting value being 240 is the reason for this. When the starting value is 120 the result will not go over 255 and wrap around. 

On that note, look at the bottom right table. When you fix the weight bug using the simple method (change + to - and - to +) to make human-initiated checks work better, you completely wreck AI checking, which was actually working fine! Now you have 1s with an average success of 70 and a success against of 12, with 15s being the opposite. 

From there, look at the top right table that shows how AI hits work in the stock rom, how/why CB checks work, and how a proper weight bug fix would work. A proper weight bug fix, as described earlier in this thread, would be to just change the starting 240 to 120. if you do that, the game works as intended and is 100% logical. Look at how every player starts with a 19% chance of knocking their own weight over, and that gets progressively lower as the checkee's weight gets higher, and progressively higher as the checkee's weight gets lower. Look at those nice colors! No red beside green. Every number is similar to the numbers around it. This is exactly how they intended for NHL 94 to be played. Also, yes, this table is the exact inverse of the table below it.

It's remarkable to think about how much this game has going for it, that it could be so badly glitched and still become so popular. I mean, we love NHL 94 despite the weight bug, right? Not because of it. Playing with WBF is weird for a lot of people because it's so counter to what they know and have become used to, but that's only because of familiarity. If the ROM was never broken to begin with, and someone "fixed" it today by making it the way we know as stock, and tried to claim it made the game better, they'd get laughed off the forum. It really is too bad, because a WBF ROM is simply objectively better.

  • Thanks 1
Posted
15 hours ago, seventieslord said:

From there, look at the top right table that shows how AI hits work in the stock rom, how/why CB checks work, and how a proper weight bug fix would work. A proper weight bug fix, as described earlier in this thread, would be to just change the starting 240 to 120. if you do that, the game works as intended and is 100% logical. Look at how every player starts with a 19% chance of knocking their own weight over, and that gets progressively lower as the checkee's weight gets higher, and progressively higher as the checkee's weight gets lower. Look at those nice colors! No red beside green. Every number is similar to the numbers around it. This is exactly how they intended for NHL 94 to be played. Also, yes, this table is the exact inverse of the table below it.

I've been using this change in my v25.3.x ROMs, and it play tests the best of any solution I've used. Highly recommended.

  • Love 1
Posted
3 hours ago, AdamCatalyst said:

I've been using this change in my v25.3.x ROMs, and it play tests the best of any solution I've used. Highly recommended.

Is this a relatively new discovery? Have previous WBF roms been done using the "simple" method that is about 80% as flawed as the default calculation?

Posted
12 hours ago, seventieslord said:

Is this a relatively new discovery? Have previous WBF roms been done using the "simple" method that is about 80% as flawed as the default calculation?

Yes they all used the simple method.  I don't think anyone ever looked at the new way until I analyzed the code.

  • Love 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Who's Online   0 Members, 0 Anonymous, 12 Guests (See full list)

    • There are no registered users currently online
×
×
  • Create New...