A-code undo/redo

## A-code undo/redo facility If the game defines UNDO as a verb, then the undo/redo A-code mechanism gets activated for that game. The REDO verb is then defined automatically, though it can be also defined by the game explicitly as a verb. In such circumstances, defining REDO as anything other than a verb is treated as an error. REDO can be used immediately after an UNDO command, to undo some or all of the UNDO. The general form of UNDO and REDO commands is as follows: verb UNDO [{||ALL|UNDO} verb REDO [{||ALL} The default number of turns to undo or redo is one, though a specific number can be specified. ALL means just that – undo all collected turn history or undo all of the preceding UNDO. "UNDO UNDO" is equivalent to REDO ALL. Information on the effects of an UNDO/REDO command is returned by an automatic variable UNDO.STATUS, which may but need not be explicitly defined by the game's code. The variable is considered to have four automatically declared flags: UNDO.INFO This flag is defined but not used by the kernel. It may be used by the game's code e.g. to enable or disable use of UNDO and REDO commands. UNDO.TRIM Set if requested number of turns has been trimmed. The value of UNDO.STATUS is set to the actual number of turns undone or redone. UNDO.INV Set if inventory contents changed, so that the game can note the fact. There is no equivalent flag for change of location, because that can be checked by the game's code by preserving the HERE value in a local variable and then it with the value of HERE after the UNDO/REDO. UNDO.BAD Set if the UNDO/REDO is given an illegal argument. Undo history is saved and restored as a part of game saving and restoring. However, should the game's number of objects, locations or global variables change, the undo history of games saved by an earlier version will be quietly ignored. Here is a simple example of using UNDO:
    action undo
      local uhere
      set uhere, here       # Preserve value of HERE in a local variable
      undo arg2             # Do the UNDO!
      ifgt undo.status, 0   # Something got undone
        ifflag undo.status, undo.trim
          say "Cannot undo that many turns!"
        fin
        say "Turns undone: $n.", undo.status
        ifne here, uhere
          say "You have relocated!"
        fin
        ifflag undo.status, undo.inv
          say "Your possessions have changed!"
        fin
        quit
      else                  # Nothing undone
        quip "Nothing happens."
      fin