replays bug(s)

Open-source port of PoP that runs natively on Windows, Linux, etc.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

replays bug(s)

Post by Norbert »

There's a bug related to the replays. I happens while fighting guards. Without looking at the code, my guess is that it's related to the guards' randomness. I can record a playthrough where I win that includes fighting guards, and then when I play it back I can lose. Maybe consistently lose, maybe not, I haven't looked into it in detail. But there's definitely a problem.

Another issue related to replays. When I play a recording, I'd like to be able to Alt+Tab away from the replay and check back after a bit. When I Alt+Tab back to SDLPoP and release Alt before Tab, the replay stops.

By the way, Falcury, we briefly discussed via private message the idea of allowing immediate/exact recording when levels start. Isn't this already possible? I tried "prince megahit 5 record" and it seems to work. Of course, this is just via command-line (for now), but still.
Falcury
Calif
Calif
Posts: 565
Joined: June 25th, 2009, 10:01 pm

Re: replays bug(s)

Post by Falcury »

Norbert wrote:There's a bug related to the replays. I happens while fighting guards. Without looking at the code, my guess is that it's related to the guards' randomness. I can record a playthrough where I win that includes fighting guards, and then when I play it back I can lose. Maybe consistently lose, maybe not, I haven't looked into it in detail. But there's definitely a problem.
Yeah that is odd... Is there a specific way that I can try to reproduce this?
Does it occur after specific events?
Norbert wrote:Another issue related to replays. When I play a recording, I'd like to be able to Alt+Tab away from the replay and check back after a bit. When I Alt+Tab back to SDLPoP and release Alt before Tab, the replay stops.
OK, I should try to reproduce this. (Maybe Tab shouldn't be the hotkey for cycling to the next replay?)
Norbert wrote:By the way, Falcury, we briefly discussed via private message the idea of allowing immediate/exact recording when levels start. Isn't this already possible? I tried "prince megahit 5 record" and it seems to work. Of course, this is just via command-line (for now), but still.
Yeah, in that way you can indeed start exactly at the start of the level.
Of course you can't end the recording the same way...
Here's a thought: perhaps Ctrl+Shift+Tab could act as a 'delayed' stop/start for the recording? I.e. you would press Ctrl+Shift+Tab, it would display the message "READY" or something like that, and as soon as you press Ctrl+A, the recording would start. And when you have finished the level, you could press Ctrl+Shift+Tab again, and the recording would end exactly when the level ends.

Speaking of replay bugs, here's a potential other problem: what about the duration of the feather fall effect? It depends on how long the sound plays, but players could mess with the exact duration (for example by pressing escape in-game). But this information is not stored in the replay, and so the replay may start to run out of sync from that point.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

Falcury wrote:Yeah that is odd... Is there a specific way that I can try to reproduce this?
I do know that I was at 2 HP (out of 3), then the guard hit me once, and the fight ended with me having 1 HP.
Also, I did some blocking, plus I moved towards the guard during the fight.
During the replay, the guard managed to hit the prince twice, and the prince died.
Falcury wrote:Here's a thought: perhaps Ctrl+Shift+Tab could act as a 'delayed' stop/start for the recording?
If recording always stops when the prince reaches the top of the exit stairs, then Ctrl+Tab could continue to function as it does now, with the addition that pressing it while not in a level initiates the delayed ("READY") start. "Not in a level" being the title sequence, any of the cut scenes, and after the prince has climbed the stairs. Together with the command-line option, this should be enough, I think.
Falcury wrote:[duration of] the feather fall effect [...] depends on how long the sound plays
Maybe the code that relies on the sound should be commented out?
That a static duration in frames (or milliseconds) is used instead.
I can't really give any useful suggestions here, I'm afraid; I know too little about the (feather and recording/replay) code.
User avatar
oitofelix
Wise Scribe
Wise Scribe
Posts: 227
Joined: February 17th, 2016, 1:59 pm
Location: Brazil
Contact:

Re: replays bug(s)

Post by oitofelix »

Given that Norbert recently implemented support for SDLPoP replays at popot.org and that SDLPoP replay file format needs improvements, I would like to invite SDLPoP developers to work on a common specification for a replay file format that both SDLPoP and MININIM (and possibly other implementations) can use. What do you think?
Bruno Félix Rezende Ribeiro (oitofelix)
MININIM author
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

oitofelix wrote:[...] and that SDLPoP replay file format needs improvements
Yeah, only minor improvements though. Generally speaking, the format should already be fine, also for MININIM, and just needs to be documented. But, now that it has become clear that use of replay files may not remain limited to SDLPoP, it's definitely a good idea to broaden the discussion and get input from you. Hopefully this won't delay things on SDLPoP's side. For improvement, I requested a magic number (file signature), plus for the format to use its own version number instead of a version related to SDLPoP. The latter coincidentally also makes the format more suitable for broader use.

Input controls are represented by a structure for each frame:

Code: Select all

struct {
  sbyte x : 2; /*** 2 bits; -1, 0 or +1 ***/
  sbyte y : 2; /*** 2 bits; -1, 0 or +1 ***/
  byte shift : 1; /*** 1 bit; 0 or 1 ***/
  byte special : 3; /*** 3 bits; currently only used for 'restart level' ***/
};
If I understand it correctly, frame duration can remain implementation-dependent.
(SDLPoP uses 5/60 sec. in non-combat, 6/60 sec. in combat.)
User avatar
oitofelix
Wise Scribe
Wise Scribe
Posts: 227
Joined: February 17th, 2016, 1:59 pm
Location: Brazil
Contact:

Re: replays bug(s)

Post by oitofelix »

Norbert wrote:Yeah, only minor improvements though. Generally speaking, the format should already be fine, also for MININIM, and just needs to be documented.
Unfortunately that's not the case. First let me clarify something you probably already know. It's unrealistic to expect that MININIM replays will work (in the sense of replaying the level as it was recorded) on SDLPoP, or vice versa, even if they share a file format that both can interpret. In general, two independent implementations won't ever be able to share a replay file like that, even if they implement strictly the same set of features. That's because playing one implementation is not the same thing as playing another, and there is no information available in the file format (whatever format we could possibly agree on) that may teach the target implementation how to translate a foreign recording. There are just too much differences in the implementation details. Only very advanced AI could do something like that.

For instance, at a high level, MININIM implements movements SDLPoP doesn't (like jump turns and take sword anywhere). Those can't be meaningfully translated by SDLPoP. The converse is also true, although in principle MININIM implements all movements available in SDLPoP. At a somewhat low level, animation is different, physics is different, therefore we are likely to obtain very different results while playing SDLPoP replays on MININIM. Each small difference at each frame scales very fast to complete chaos in the end.

Therefore, it's a hopeless task to support sharing of replays between independent implementations. However, this doesn't mean all implementations couldn't share the same replay file format.

Such file format must be expressive and stable enough to support all current implementation features and potentially any future versions thereof, no matter what features get added over time. The most simple and reliable way of accomplishing this is to record the full input state (keyboard, mouse, joystick), probably the random seed, and whatever implementation dependent information is needed, at each frame.

This may in principle be seen as overkill, but it pays off because any implementation using such format won't ever (in principle) face the need to change it. With such format one can record anything that is possible to execute in a given implementation, not only simple plays. For instance, entire level editor sessions (MININIM and SDLPoP have level editors) may be recorded. The way I see it, editing a level is also playing the game. Think about it. The applications of such general format are limited only by what the engine is capable of. We get a big return for a relatively small investment.
Norbert wrote:If I understand it correctly, frame duration can remain implementation-dependent.
I think so.
Norbert wrote:(SDLPoP uses 5/60 sec. in non-combat, 6/60 sec. in combat.)
MININIM always uses 1/12. That may be justified by the different fight mechanics.
Bruno Félix Rezende Ribeiro (oitofelix)
MININIM author
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

Both implementations create movement using Shift and key presses that indicate movement on one of the axis.
In my view this means the format can remain basic and is almost finished.
If I'm wrong, I'll leave it up to you and Falcury to discuss changes.
User avatar
oitofelix
Wise Scribe
Wise Scribe
Posts: 227
Joined: February 17th, 2016, 1:59 pm
Location: Brazil
Contact:

Re: replays bug(s)

Post by oitofelix »

Norbert wrote:Both implementations create movement using Shift and key presses that indicate movement on one of the axis.
In my view this means the format can remain basic and is almost finished.
If I'm wrong, I'll leave it up to you and Falcury to discuss changes.
That wouldn't account for taking the sword anywhere, for example. The general format would still be "basic", (just a bigger array of keys), the only effective difference being that it would be ultimate (and a lot more useful).
Bruno Félix Rezende Ribeiro (oitofelix)
MININIM author
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

oitofelix wrote:That wouldn't account for taking the sword anywhere, for example.
Why not?
User avatar
oitofelix
Wise Scribe
Wise Scribe
Posts: 227
Joined: February 17th, 2016, 1:59 pm
Location: Brazil
Contact:

Re: replays bug(s)

Post by oitofelix »

Norbert wrote:
oitofelix wrote:That wouldn't account for taking the sword anywhere, for example.
Why not?
Because the return key is used for that, and in the format one has only the axes and shift.
Bruno Félix Rezende Ribeiro (oitofelix)
MININIM author
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

oitofelix wrote:
Norbert wrote:
oitofelix wrote:That wouldn't account for taking the sword anywhere, for example.
Why not?
Because the return key is used for that, and in the format one has only the axes and shift.
Okay, so the shift byte can also have 0x02 for your Enter.
Magic number, replay format version, name or number o/t program that created the file, and then struct stuff.
As I wrote though, I'm going to leave this to you and Falcury.
My last post in this thread.
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: replays bug(s)

Post by David »

Norbert wrote:There's a bug related to the replays. I happens while fighting guards. Without looking at the code, my guess is that it's related to the guards' randomness. I can record a playthrough where I win that includes fighting guards, and then when I play it back I can lose. Maybe consistently lose, maybe not, I haven't looked into it in detail. But there's definitely a problem.
I was thinking that maybe random_seed is not saved into replays (and savestates), but it is saved.

My other guess was that random_seed might be still uninitialized when you start the recording.
(It is initialized by prandom if it's not initialized yet.)
But prandom() is explicitly called (to initialize the seed) in init_game_main(), before you could interact the game.

I tried this now but I can't reproduce it.
Maybe you should post an example replay file?
(But then, we still could not see how it was recorded. Maybe record it into a video as well or something...)

As a side note, I *did* see something like this in SNES9x: viewtopic.php?p=16318#p16318
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

David wrote:Maybe you should post an example replay file?
https://github.com/NagyD/SDLPoP/issues/111
Falcury
Calif
Calif
Posts: 565
Joined: June 25th, 2009, 10:01 pm

Re: replays bug(s)

Post by Falcury »

Hey, I found a possible cause of the crashes: it seems that recordings from 64-bit and 32-bit SDLPoP binaries do not mix, because the size of size_t is different for 32 and 64 bit versions. The fix should be simple (just always use unsigned 32 bits for size variables in the replay format).

I have attached a version of Norbert's test replay where I have truncated the size_t variables by four bytes using a hex editor (so it should work on 32-bit versions of SDLPoP).
Attachments
m0000164_l03_u0001.zip
(1.29 KiB) Downloaded 58 times
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: replays bug(s)

Post by Norbert »

Norbert wrote:My last post in this thread.
I see I already broke my own promise above.
That's because this thread was (just) about SDLPoP replay bug(s), and I do want to discuss and comment on those.

Anyway...
-----
Add to data.h:
Uint32 rtime;
-----
Start init_game() in seg003.c with:
rtime = SDL_GetTicks();
-----
Add to add_replay_move() in replay.c, after "moves[curr_tick] = curr_move.bits;":
printf ("[%i] >%i< >%i< >%i< >%i<\n",
SDL_GetTicks() - rtime,
curr_move.x, curr_move.y, curr_move.shift, curr_move.special);
-----
Add to do_replay_move() in replay.c, before "++curr_tick;":
printf ("[%i] >%i< >%i< >%i< >%i<\n",
SDL_GetTicks() - rtime,
curr_move.x, curr_move.y, curr_move.shift, curr_move.special);
-----

Then I see that recording starts with:
[266] >0< >0< >0< >0<

While replaying starts with:
[115] >0< >0< >0< >0<

This can't be right, right?
Falcury wrote:I have attached a version of Norbert's test replay where I have truncated the size_t variables by four bytes using a hex editor (so it should work on 32-bit versions of SDLPoP).
This replay file gives a segmentation fault for me.
(Probably unsurprising, but just for the record.)
Post Reply