I don't see a problem with #3 in terms of implementing it, however the issue is - what happens if the assignment being deleted is already one that would fail, but has somehow remained in the replay, with further actions at a later point (that would be interfered with by the above algorithm)?
Isn't that exactly the same as my #4? A failed cloner assignment is one that would've created clone -N but didn't. All future assignments in the replay to ID -N will also fail because there's no -N. You can elect to delete -N now, removing all assignments involving ID -N from the replay, then adjust the IDs of -(N+1) onwards. Or you can leave it in the replay as a defunct record. If you do leave it, you must still subtract one anyway for the next clone ID to use.
Basically there's a fixed relation between the ID to use for a newly created clone and how many cloner assignments (both successful and defunct) have been executed so far. This saves you from having to explicitly record the clone IDs into the records of the cloner assignments, at a cost of having to maintain this relationship correctly during any insertion/deletion of moves.
This is why I think a better approach is to attempt to uniquely generate an ID number for cloners.
That's fair. If you change the format so that for cloner assignments, you also store the new clone's ID in the replay record for the assignment, then all you have to do is to keep decrementing (ie. more negative) to get the next cloner ID to use, and it'd be unique. In other words:
- When you load a replay, scan through the cloner assignments (which would now contain the IDs used for the newly created clones) to find the lowest (ie. most negative) clone ID used. Subtract 1 from it to get the number (N) to use for the next cloner assignment. Note that this means N = -1 for the case where there's no replay or no cloner assignments in the replay.
- If the assignment comes from a replay, then ignore N and just use the stored clone ID for the new clone being created.
- For an assignment not coming from a replay (ie. from an actual player-executed assignment, or an inserted assignment during editing), use N for the clone ID and subtract 1 to update N afterwards.
In this system, you don't have to ever readjust any existing clone IDs in response to insertion or deletion of cloner assignments, since there's no longer a relationship to maintain between number of clones made so far and the IDs of the clones. You can still propagate deletes (if you want to) to delete all future moves on the deleted clone plus all of its descendant clones, since the cloner ID of the clone created is part of the replay record for a cloner assignment. Assignments that become invalid has no impact since any assignments from the replay don't change N, you just use the stored ID.
Off top of my head, I don't believe there's any simple system to assign unique clone IDs if you can't also store those IDs as part of the replay records of the cloner assignments.
Backwards compatibility on the replays would likely need to remain indefinitely; either this, or a "replay update" feature would need to be built into NL itself. While backwards compatibility is not a particularly difficult task, updating a replay without outright playing it back would be almost impossible (again, due to the possibility that some assignments in it are already invalid).
Yeah, unfortunately I don't see a way around this. The old format is based on indices, and failed cloner assignments will definitely affect indices in the same way a delete of a successful cloner assignment during replay editing can. And there's no way to predict whether the assignment is ok or not without outright playing it all back. This is always a problem regardless of what system you choose for the IDs of the clones.