ruffle icon indicating copy to clipboard operation
ruffle copied to clipboard

The CPU is breaking the Gomoku rules in Wuzi Chess.

Open jmousy opened this issue 4 years ago • 13 comments

Describe the bug wuzichess

When playing Wuzi Chess (same as Gomoku rules), on a CPU turn, the CPU stone is overlaid at the same location on the player's stone.

It was difficult to explain, so I attached a Gif that was slowed down. In the Ruffle version, you can see that the white stones are overlaid with black stones.

There is no such problem in the Original Version, and it happens very frequently in Ruffle. The problem can be easily reproduced by placing the stone diagonally along the line of the stone placed by the CPU.

WuziChess.zip

Expected behavior The game should proceed according to the normal Gomoku rules.

Is the problem with the Ruffle desktop app, extension, or self-hosted version? Probably happens on all platforms

What platform are you using?

  • Desktop: Windows 10 x64, Google Chrome (Latest), Ruffle Nightly 2021-02-06

jmousy avatar Feb 06 '21 10:02 jmousy

Many thanks for your report, @jooy0224.

For some strange reason, Ruffle replaces white stones with black ones.

I’m afraid it’s not easy to detect why this value change happens.

ousia avatar Feb 06 '21 11:02 ousia

The underlying cause here is that when the player places a stone the variable _root.table is updated with a 1 in the position where the stone was placed so the CPU knows which positions are taken. This happens in "DefineButton2 (19)/BUTTONCONDACTION:16" with the following code _root.table[ypos][xpos] = 1, in Flash Player xpos/ypos are correctly set, however in Ruffle they are set to undefined. Changing that line to _root.table[_root.ypos][_root.xpos] = 1 stops the CPU player from overwriting the players moves.

CUB3D avatar Feb 08 '21 02:02 CUB3D

Exactly the same problem occurs in another version of the game called Five Secret Stones: https://github.com/ruffle-rs/ruffle/files/9865345/five.zip

n0samu avatar Oct 30 '22 05:10 n0samu

Seems like the code in DefineButton2 (19) doesn't operate in the right scope? For instance, if you add this:

testme = 123;
trace(_root.testme); // 123 in FP, undefined in Ruffle
trace(this); // empty string in FP, "_level0.b(int)" in Ruffle
trace(this.testme); // undefined in FP, 123 in Ruffle
trace(_level0.b123); // _level0.b123 in FP and Ruffle

Toad06 avatar Oct 30 '22 18:10 Toad06

I feel like this might be related to #1029 somehow, what do you think?

n0samu avatar Oct 31 '22 00:10 n0samu

In fact, this seems to be another instance of #3839 (again 😢) - the code I posted above gives different results depending on the position it is pasted in DefineButton2 (19):

trace(this); // "_level0.b(int)" in FP and Ruffle
removeMovieClip(_root.b add _root.num); // removeMovieClip issue is about to strike again!
trace(this); // empty string in FP, "_level0.b(int)" in Ruffle
(...)
_root.table[ypos][xpos] = 1; // xpos, ypos should now be read from "_root", not "_level0.b(int)"

Toad06 avatar Nov 22 '22 14:11 Toad06

Alright, thanks for checking!

n0samu avatar Nov 23 '22 03:11 n0samu

Hmm... I checked on the 2023-03-02 Nightly Selfhosted build, but I'm still having issues. 😭

The problem can easily be reproduced by placing stones diagonally to block the attack by the CPU. Tested with the SWF attached to the description above.

image

jmousy avatar Mar 02 '23 12:03 jmousy

Thanks for testing. The issue I posted in my previous comment is only partially fixed: trace(this) now displays results that match Flash Player, but the xpos and ypos variables are not read from the right scope.

_root.xpos = (int(this._x + 0.5) - 15) / 20 - 1;
// (...)
trace(xpos); // undefined in FP and Ruffle
removeMovieClip(_root.b add _root.num);
trace(xpos); // a number in FP, undefined in Ruffle
// (...)
_root.table[ypos][xpos] = 1;

Toad06 avatar Mar 02 '23 13:03 Toad06

Looks like the game somehow broke again between when I last tested it and when the PR was merged. Hopefully @CUB3D can take a look!

n0samu avatar Mar 02 '23 13:03 n0samu

_root.xpos = (int(this._x + 0.5) - 15) / 20 - 1;
// (...)
trace(xpos); // undefined in FP
removeMovieClip(_root.b add _root.num);
trace(xpos); // a number in FP
// (...)
_root.table[ypos][xpos] = 1;

Looks like the game somehow broke again between when I last tested it and when the PR was merged.

This was indeed working with 6a5eb43274b58cdd55814a2621f94e14be951130. However, the behavior wasn't correct either as both of the trace(xpos) were returning a number (so the first xpos was no longer read from the right scope).

The game then breaks again in af9810c22edea7bef4fbcfdca5829238f921d486, and both of the trace(xpos) are now returning undefined (issue with the second xpos).

Toad06 avatar Mar 03 '23 22:03 Toad06

This debug assert is probably relevant to the scoping issue: thread 'main' panicked at 'Scope::set: No top-level movie clip scope', core/src/avm1/scope.rs:200:13

   2: ruffle_core::avm1::scope::Scope::set
             at ./core/src/avm1/scope.rs:200:13
   3: ruffle_core::avm1::scope::Scope::set
             at ./core/src/avm1/scope.rs:195:13
   4: ruffle_core::avm1::activation::Activation::set_variable
             at ./core/src/avm1/activation.rs:2780:9
   5: ruffle_core::avm1::activation::Activation::action_set_variable
             at ./core/src/avm1/activation.rs:1907:9
   6: ruffle_core::avm1::activation::Activation::do_action
             at ./core/src/avm1/activation.rs:533:40
   7: ruffle_core::avm1::activation::Activation::run_actions
             at ./core/src/avm1/activation.rs:424:26
   8: ruffle_core::avm1::runtime::Avm1::run_stack_frame_for_action

Lord-McSweeney avatar May 06 '23 19:05 Lord-McSweeney

@olux997 mentioned another version of the game with the same problem: https://github.com/ruffle-rs/ruffle/files/12271961/5.zip

n0samu avatar Aug 08 '23 01:08 n0samu

Fixed by #20837

Lord-McSweeney avatar Jul 17 '25 18:07 Lord-McSweeney