Copyright (C)1997,2001,2002 by Eric Sunshine <sunshine@sunshineco.com

TODO.txt

TODO
----
[GENERAL]
- Change player path finding code so that it prefers straighter paths over
  twistier paths, when multiple minimum-cost paths exist.
- Anti-alias the hexagonal and triangular tiles.  They have a case of the
  jaggies.
- Create a common "appkit" directory and move as much code there as possible in
  order to reduce future maintenance costs.
- The AppKit SokoMatrix class and its subclasses need not maintain a grid of
  cached image pointers.  It is simpler and less resource-consuming to merely
  ask the SokoPuzzle for the cell's type when needed.  (This is the way the
  C++Builder port works.)
- Add support for allowing users to easily employ additional puzzle sets.
  Supporting extension sets will require eliminating the current "level" based
  scheme for dealing with puzzles.  This means that the "highest" and "next"
  puzzle concepts need to be re-thought.  The puzzle parser will need to be
  augmented to deal with comments and additional information in the puzzle
  files.  Furthermore, the UI should display the puzzle author's comments so
  that the author gets appropriate credit.  Note that some puzzle comments
  contain 8-bit characters in the author's names, so ensure that the proper
  character encoding is used (probably whichever character encoding is default
  with X-windows).  Support puzzle sets in which all puzzles appear in a single
  file, since this is a common way to distribute puzzles.  The parser will need
  to be augmented to deal with these conglomerate files.  It will also be
  necessary to generalize the UI sufficiently to allow the user to choose a
  puzzle from one of these sets.
- Add an inspector panel which displays various pieces of inforomation about
  the active puzzle window, such as current history in LuRd format, author
  comments, current scores, possibly puzzle count and dimensions.  Provide user
  with an obvious mechanism for copying the LuRd solution to the pasteboard
  (probably via a button on the inspector panel).
- Add a facility for easily exporting the history string.  Consider hooking up
  Edit/Copy or History/Export.  These could copy the history "lurd" to the
  pasteboard, or save to file.  (Also see To-Do item regarding inspector
  panel.)
- Once the program can deal with extension puzzle sets, distribute additional
  sets after getting permission from their authors.
- Consider responding to mouse-scroll-wheel on platforms which support it.
  Scrolling up should perform redo operations, and scrolling down should undo.
  Question: Should the mouse-wheel perform move- or push-undo/redo operations?
- Consider allowing right-mouse-down to perform the normal right-mouse-down
  action for the platform if the event occurs in a "null" tile on the
  SokoBoard.
- Record each "best group" of scores, rather than recording each individaul
  "best" score in save file.  This will allow us to detect when a solution is
  better than a previous solution even if it's not the "best" for an individual
  score.
- Consider slowing down the animation.  It is so fast now that it is often not
  even visible.
    #define ANIM_THRESHOLD (100UL)
    struct timeval t;
    if (gettimeofday( &t, 0 ) == 0)
	{
	long const d =
	    (t.tv_sec - lastSecond) * 1000000 + (t.tv_usec - lastMicrosecond);
	if (d < ANIM_THRESHOLD)
	    {
	    struct timeval x;
	    long p = ANIM_THRESHOLD - d;
	    x.tv_sec = 0;
	    x.tv_usec = p;
	    select( 0, 0, 0, 0, &x );
	    t.tv_usec += p;
	    if (t.tv_usec > 1000000)
		{
		t.tv_sec++;
		t.tv_usec -= 1000000;
		}
	    }
	lastSecond = t.tv_sec;
	lastMicrosecond = t.tv_usec;
	}
    SOKO_FLUSH;
- Consider adding a control to the preferences panel to allow user to control
  animation speed.  Note that if user can make animation speed very slow, then
  it will be necessary to provide user with a mechanism for aborting _all_
  animation (not just playbacks, as is currently the case).
- Probably add a file extension (.sokoscore) to the SCORES file at some point.
- Perhaps provide a preferences option to disable tool-tips.
- Consider renaming undo/redo-push to undo/redo-smart.  "Smart" is probably a
  more applicable name than "push".
- Perhaps display read-only expansions for $(SokoSave) and $(SokoUser) on
  preferences panel.
- Add a preview feature when opening puzzles.
- Add a puzzle editor.  The editor should provide a play-test capability.
- Perhaps add support for skins/tilesets.  An important aspect of this would be
  to add a larger version of the "classic" SokoSave skin for people using mouse
  pads and TrackPoint devices, since it is more difficult to easily and
  precisely position the mouse on the small SokoSave tiles when using those
  devices.
- Consider saving each "best" solution in the save-file.  A "best" solution is
  one which got a high-score.  Since there are currently four metrics, this
  means that there could be up to four "best" solutions.  Note, however, that
  this idea complicates the user interface, since there would have to be some
  way for the user to select which solution should be used for the game.
- Consider saving the solution for a puzzle along with its score in the SCORES
  file.  This also might require storing the actual puzzle data along with the
  solution, so that a game can be replayed directly from the SCORES file.
- Port to X-Windows/KDE/GNOME.
- Possibly port to BeOS.
- Try to be smarter about automatically saving the game when solved.  It would
  be very unfriendly to automatically overwrite a well-played game with one not
  so well played.
- Consider changing extensions in puzzle directory from .sokomaze to .xsb.
- Use C-style comments in the common C code, rather than C++ style.
- Localize the project.
- Perhaps user should be able to browse filesystem via GUI to set paths on
  preferences panel, rather than having to type from memory.  However, this may
  not be entirely practical since some paths (such as the one to the SCORES
  file) may not yet exist.  Put further consideration into this issue.
- Consider making the wall segments continuous instead of discrete blocks.
  This might look okay for classic square-tiled puzzles, but I'm not sure that
  I like the looks of it for hexagonal-tiles puzzles.  Requires further
  consideration.
- Possibly optimize crate path finding for Trioban puzzles.  It is possible to
  cut in half the number of checks made to see if the player can reach a
  particular edge of a triangular crate by caching and re-using the result of a
  previous test.  Even though a crate can be moved in six directions, the
  player can only push from three sides of the crate, thus it is necessary to
  perform only three tests to see if the player can reach the crate, rather
  than performing all six tests.  Note that successfully and unsuccessful
  attempts by the player to reach a particular side of the crate can be cached.
  When I first implemented Trioban support, I did perform this optimization,
  but it added a significant amount of complexity to the crate path finding
  code, was highly fragile (I never did get it working with 100% correctness),
  and it was confusing.  Therefore, I removed the code.

COMPLETED
---------
v19
[GENERAL]
- Augment path finding for crates so that it can discover arbitrarily complex
  paths which overlap upon themselves any number of times, rather than being
  limited only to non-overlapping paths.
[OPENSTEP]
- Add a script to automate the process of creating MacOS/X .dmg archives.

v18
[GENERAL]
- Add Triboan support.
- Upgrade trim_scores.sh to handle run and focus scores, and to also deal
  gracefully when those scores are blank or -1.  [Paul wrote a new
  trim_scores.cc program to replace the old trim_scores.sh.]
- SokoPuzzle should hold onto meta-data from the puzzle file, rather than
  throwing it away.  Client should be allowed access to this data.
- SokoPuzzle should parse meta-data and maintain a list of key/value tuples.
  Clients should be allowed access to this data.
- Add some mechanism for disabling high-score recording and auto-save for
  puzzle designers.  While creating a new puzzle, designers often load a game,
  play it, solve it, change it, re-load it, etc.  During this iterative
  process, it is annoying to have a high-score panel pop-up.  Also, the
  high-score will be incorrect if the author then changes the puzzle.  One
  possibility is to recognize a keyword in the puzzle file, such as "Pragma:".
  Some options are "Pragma: no-high-score" and "Pragma: no-auto-save".
- SokoPuzzle should write puzzle's meta-data to save file.
- Move hexagon and triangle geometry utility code out of port-specific classes
  and into the common directory.  This code, which does hit detection and such
  for hexagonal and triangular grids is sufficiently general that it can be
  shared by all ports.
- SokoHexTri images should be using a light-gray strip alongside the white
  strip, rather than a double-white strip.
- Create SokoPuzzleTri.ico.  Use this icon for file associations in project
  files and CustomInfo.plist.
- Add triangular tiles to help file.  Describe Trioban support.
- Augment FILE_SYNTAX.txt for Trioban.
- Update FILE_SYNTAX.txt to mention meta-data in puzzle and save files.
- Add credit headers to distributed Hexoban and Trioban puzzles.
[CBUILDER]
- Augment SokoSave.iss so that it copies new `hexocet' and `trioban' puzzle
  directories.
- Create SokoGridHexagon.rc, SokoGridSquare.rc, and SokoGridTriangle.rc and
  move the BITMAP entries to those files from SokoBoard.rc.
- Only notify the Windows workspace once after registering all file
  associations, rather than notifying it after each registration.
[OPENSTEP]
- Add 2-, 8-, 12-bit equivalents for new triangular TIFF tiles.
- Only notify the Windows workspace once after registering all file
  associations, rather than notifying it after each registration.
[NEXTSTEP]
- Add 2-, 8-, 12-bit equivalents for new triangular TIFF tiles.

v17
[GENERAL]
- Don't fill areas outside the puzzle with wall segments.  Doing so causes some
  "artistic" effect to be lost with some puzzles.
- Puzzle parser should be sufficiently robust to determine whether a hexagonal
  puzzle is using the conventional even-on-even/odd-on-odd rule or the
  even-on-odd/odd-on-even rule.  This is a good idea, since there is a fair
  chance that people won't respect the established convention.
- As an interim step to full puzzle-set support, augment the loader so that it
  ignores comment lines in files (such as those in many .xsb files).  Define a
  comment line as a line that begins with any non-puzzle character (with
  optional leading whitespace).
- Use the original puzzle tokens in the save files rather than the internal
  SokoPuzzle tokens.  This will require bumping the save file version.
- Add support for the new hexagonal-style puzzles.
- Recognize these additional file extensions: .xsb, .hsb, .sokohex.
- Flatten the wall segment graphic.  In its present form, it tends to overwhelm
  the puzzle board.
- Figure out how keyboard control should work for hexagonal puzzles.
- The Animate switch should control all animation.  Currently, it only controls
  animation of lengthy playback sessions, however, for consistency, it should
  also control even the short playbacks (such as those from undo/redo push) and
  even the normal movement animation.
- For consistency, point-and-click crate movement should fall into crate-drag
  mode, just as point-and-click player movement falls into player drag mode.
- No need to store the push and move counts in the save file, since this
  information can be easily derived from the history.
- No need to store the history-max, since this is merely a detail of a
  particular program run (i.e. the amount of memory allocated for the history),
  but is not otherwise meaningful for the saved game.
- Ditch RLE compression in save file since it makes it difficult or people to
  transport "lurd" solutions between different Sokoban implementations.
- Keep track of these new metrics: (1) Number of "runs", which is the number of
  times the player has touched a crate and then started pushing it.  Once the
  player leaves the crate, that run ends.  (2) Number of times player's "focus"
  has changed crates.
- Add run-count and focus-count to NewScore panel.
- Add run-count and focus-count to Score panel.
- Add run-count and focus-count to SCORES file.
- Add attributions to help file for all puzzles distributed with the program.
- Fix FILE_SYNTAX.txt to indicate what puzzle comments are.
- Fix the wall image and the example images in the help file so that they
  display the newer flattened wall.
- Update documentation to explain run-count and focus/change-count.
- Create a script to create the "source code" package from the RCS package.
  Some obvious tasks for this script include:
    * Convert all text files in cbuilder directory to CRLF endings.
    * Remove all README_BINARY files.
    * Remove README_RCS file.
    * Remove all RCS directories.
    * Remove util directory.
- Update copyright message on all Info panels.
- NewScore panel should remove file extension from displayed puzzle name.
- Add tool-tips to score fields on SokoBoard.
- Consider tranforming all unreachable tiles in version 1 save games to "empty"
  when loaded.  This will make those games appear more like newer saved games.
[CBUILDER]
- Apply additional gamma correction to game tiles.  They should be a bit
  brighter.
- Stop copying README_BINARY.txt with the ISS setup script.  It isn't really
  necessary.  Also having that README file present in the source package is
  inconsistent since the other README_BINARY files are not present.
- Add a SokoPuzzleHex.ico and appropriate file associations.
- Rework C++Builder SokoBoard controls to match new layout of NextStep /
  OpenStep / MacOS/X SokoBoard.
[OPENSTEP]
- Make 24-, 12-, 8-, and 2-bit versions of new hexagonal tiles.
- Add hexagonal TIFF document icon.
- Add hexagonal ICO document icon.
- Add new flie associations to CustomInfo.plist.
- Increase Name and Notes box heights slighly on SokoNewScore.  They look a bit
  squashed on Aqua.
[NEXTSTEP]
- Make 24-, 12-, 8-, and 2-bit versions of new hexagonal tiles.
- Add hexagonal TIFF document icon.

v16
[OPENSTEP]
- Eliminate the unnecesary button in the center of the directional buttons
  on SokoBoard.
[NEXTSTEP]
- Eliminate the unnecesary button in the center of the directional buttons
  on SokoBoard.

v15
[GENERAL]
- Break core game logic out of GUI code and generalize it so that the same core
  code can be used by any platform.
- SokoSave on Unix can't read .sokosave files from Windows.  Make sure that all
  platforms can read all files no matter what platform a file originated on.
  LF for Unix, CRLF for Windows, CR for Macintosh.
- Recognize "+" as player-safe.  XSokoban uses "+" for player-safe, rather than
  "^" recognized by SokoSave.
- For safety, SCORES should be written out immediately after a new score is
  recorded, rather than only writing it at program termination time.
- Sasquatch IV puzzle 25 contains an unreachable crate, but the crate is
  already on a goal square.  However, SokoSave considers this crate unreachable
  and will not load the puzzle.  Should make a special case of this so that a
  crate already in a goal doesn't matter.
- Create wrappers for the core game library so that it can be accessed easily
  from C, Objective-C, and C++.
- Consider making email addresses (and names) on Info panel into active links
  which launch the mail program.  The email addresses should appear underlined
  (or maybe only underline upon fly-over).
- Consider adding a URL to the Info panel which points at high-speed-sofware
  and which launches the web browser when clicked.  The URL should appear
  underlined (or maybe only underline upon fly-over).
- Programmatically load the correct tag values into the movement buttons rather
  than relying upon them having the correct values from the designer.
- The new dirty cell mechanism in SokoPuzzle is probably too efficient.  I
  suspect that it will not allow cells to be repainted even when "animation" is
  enabled, or simply when the player is moving any distance in response to a
  normal movement request.  Unless I am mistaken, cells will only be redrawn
  after all movement has occurred.  Need some way to force a refresh to occur
  at desired times.  Check this out and think it over.
- Perhaps augment soko_collapse() so that it also recognizes $(HOME).  In fact,
  have it recognize several well-known environment variables such as HOME,
  TEMP, and TMP.
- Perhaps call soko_collapse() for all paths on preference panel, rather than
  only "puzzle path".  [In fact, I moved this logic into SokoFile so that
  SokoCore is now responsible for collapsing all "special" paths, rather than
  placing the onus of path manipulation upon the UI element.]
- Update SokoCore.dep for files utilizing SokoPool.
- Figure out how to implement player and crate dragging in SokoCore and how it
  should relate to platform-specific ports.
- Can probably eliminate start_row and start_col from SokoDragState.
- Create icons for .sokomaze and .sokosave so that they can be distinguished
  from the application and from each other on platforms (like Windows) which
  hide the file extension by default.  Create both ICO and TIFF formats.
- Update comments in SokoPuzzle.c to reflect all the changes to event handling
  and dragging.
- Figure out how to implement playback cancellation in SokoCore and how to
  integrate it with the cover application.
- Have SokoScore trim and collapse strings before recording them in the score
  table.
- Add a "Next Puzzle" menu item and toolbar shortcut, which open the puzzle
  that comes "next" after the puzzle in the active window.  It should use the
  same logic as the program does when starting up, except that the puzzle
  number will depend upon the currently active puzzle, rather than the puzzle
  number from the user's preferences.
- When opening the "default" puzzle at launch time, the current behavior is
  sub-optimal.  The current technique is to simply open a .sokomaze file with
  the level number recorded as the "highest" level.  Unfortunately, if the user
  then tries to open a saved game file with the same level number, the program
  doesn't actually open the saved game because it thinks it's already open.
  This makes it very difficult for the user to continue a saved game which
  matches the "highest" level.  The user first has to close the "new" game and
  then open the "saved" game.  This is even further complicated on the Windows
  platform where closing the "new" game would cause the program to terminate if
  that was the only open menu-bearing window.  Since it is probable that a user
  may save a game before actually arriving at the solution (and thus
  incrementing the "highest" level) with the intention of returning to that
  game later, we should make it as simple as possible for the user to do so.
  The logic should change so that at launch time, the program first checks for
  a "saved" game matching the "highest" level and open that if present.  If
  not, then fall back to the current behavior of opening a new game.
- It looks like the "playback_abort" element of the playback state structure in
  SokoPuzzle does not play a meaningful role.  Remove it.
- For safety, user defaults should be committed immediately, rather than at
  termination time.  This includes the column order and size settings on the
  scores panel.
- Ensure that document files, such as HISTORY, BUGS, and TODO, get distributed
  with each port.  For OpenStep/NextStep, have the project file copy these to
  the application wrapper.  For C++Builder, have the InnoSetup script copy them
  to the output directory.
[CBUILDER]
- Create a native Windows port of SokoSave using C++Builder.
- Add code to minimize windows to taskbar rather than desktop.
- Add code to forcibly hide the main form's taskbar button except when the
  application is actually hidden.  (In which case, there must be some way to
  re-activate the application.  At all other times, this button is not needed
  since the taskbar will contain buttons for the on-screen SokoSave windows.)
- Use better colors on bitmaps or try to figure out how to apply the correct
  gamma value.  The current colors look awful on Windows since it does not
  gamma alpha correction.  [Used GIMP to adjust the gamme value to 1.6.]
- Adjust project settings so that the executable is really stand-alone (does
  not require any Borland DLLs or BPLs).  Presumably, this can be done by
  disabling the "Use dynamic RTL" and "Build with Runtime packages" switches.
- Write code to display Release and Build numbers on Info panel.
- TTrackBar runs in "continuous" mode.  Although this may be considered nice in
  a few circumstances, it makes it impossible to specify as an atomic operation
  that some portion of the game should be replayed.  Unfortunately, there
  doesn't seem to be any way to disable "continuous" mode, though.  Some custom
  coding will probably be required.  [Created a subclass of TTrackBar which
  publishes a new OnEndTracking event.  Now SokoBoard listens only for this
  event and replays the history upon receipt, rather than replying continuously
  as it did when listening for the OnChange event.]
- Implement menu item validation (enabling/disabling).  [Implemented for items
  on History menu.  I don't believe that any other items require validation, so
  I consider this task complete.]
- Write code to cascade windows as they are opened.
- Write code to implement Cascade functionality from Window menu.
- Write code to update Window menu as puzzles are opened and closed.  Possibly
  also include Scores and About panels, and maybe even Preferences.
- Write code to remove items from the Window menu.
- Write code to actually respond to selection of window on Window menu.
- Sort the items added to the Window menu.
- Prevent multiple instances of program from running.
- Hook up Save and Save As menu items.  Also make sure that Save dialog
  respects users last directory choice.  Don't reset the directory each time
  the dialog is launched.
- Add a Save All menu item.
- Use transparent pixels in the upper-right and lower-left corners of the icons
  rather than some dark color.
- Probably shorten name of SokoSaveGame.ico to SokoGame.ico.
- Add a shortcut toolbar for quickly starting new games, opening saved games,
  saving games, launching the scores panel, and launching the help file.
- Add a pop-up menu to SokoBoard which can toggle presence of toolbar.
- Ensure that toolbar is present or absent at puzzle launch time as required by
  user preference.  Furthermore, ensure that popup menu item displays the
  correct verb depending upon the presense of the toolbar.
- When the "Show Toolbar" switch is toggled on preference panel, adjust all
  open puzzle boards.  Also remember to adjust display on popup menu.
- Load toolbar bitmaps programmatically at run-time.
- Change behavior of SokoPrefDelegate::user_path() so that it uses path named
  "My Documents" if available, rather than expanding that path to some absolute
  directory.  This will make it behave more like soko_collapse().  [Instead, I
  introduced the new pseudo-variable $(SokoUser) which is the expansion of
  SokoSetting::user_path(), just as the existing $(SokoSave) is the expansion
  of SokoSetting::factory_path().]
- VCL doesn't remember the FilterIndex value of the Open and Save panels
  between invocations, so save/restore this information manually.
- Have preference panel track its own dirty status so that it can prompt the
  user for "Save", "Don't Save", or "Cancel" when closing the panel with the
  title bar's close button.
- If the user completes a level and the "highest level" is incremented, this
  information needs to be reflected on the preference panel the next time it is
  launched.  It also needs to be reflected if the panel is already on-screen.
- Implement auto-high-score registration.
- What happens when puzzle is solved during dragging?  It would probably be
  undesirable to launch new-score panel while dragging is still in progress.
  For this case, delay launch of said panel.
- Should probably catch key-down in SokoNewScore (in addition to key-up which
  is already trapped) since it is possible to create an empty Name field and
  press OK while a key is down.
- Remember username from New Score panel as default for that panel as a
  convenience to users of Windows 9x who don't actually login with a login
  name.
- Programmatically register file extensions at run-time.
- Rename SokoPrefDelegate to something shorter.  [Renamed to SokoDefaults.]
- Create an InnoSetup installer script for SokoSave.
- Ensure that form's content area expands properly if user's visual settings
  change (such as if menu font becomes very large).  [Now catches the
  WM_SETTINGCHANGE message and resizes the window as needed.]
- Write TSokoBoardForm::choose_puzzle() for case when no puzzle can be opened
  automatically at launch time.
- Ensure that puzzle grid retains keyboard focus at all times in order to
  ensure that player can be moved via keyboard.  I have implemented the
  alternate approach of using TForm's KeyPreview feature to intercept
  keystrokes, thus it doesn't matter which control has keyboard focus; the
  arrow keys will still be correctly interpreted.  I am undecided if I like
  this approach, though, since it still allows other controls to have focus and
  to display the focus rectangle.
- Whenever any SokoSave window is activated, VCL brings forward _all_ SokoSave
  windows.  I find this behavior very annoying.  Figure out some way to prevent
  other windows from having their Z-order adjusted.  [Fixed by setting each
  window's parent handle to the desktop window rather than the application's
  hidden window.  Unfortunately, this broke the "Hide" or "Minimize All"
  feature which I got for free via TApplication::Minimize(), so I had to code
  up my own Hide function.]
- Enable "Optimize Mode" before creating final package.
- Augment TSokoForm so that it understands a small number of keyboard
  shortcuts.  This will allow a window to respond a few useful shortcuts even
  if the window does not have a menu.  Implement the following shortcuts:
  ctrl+w = close; ctrl+h = minimize all; ctrl+m = minimize; shift+ctrl+c =
  cascade.
- Make any needed final adjustments to the installation script.  In particular,
  add an uninstall icon so that the Win2000 Add/Remove Software window shows
  the SokoSave icon rather than some generic icon.
- The Scores panel appears initially mostly off-screen on low-resolution
  displays, such as those at 800x600 or 640x480.  [Now uses poScreenCenter
  instead of poDesigned for Score panel.]
- Create "disabled" images for the "arrow" buttons.  These are needed because
  the way in which Win98 automatically generates disabled images from the
  enabled counterparts results in very bizarre and ugly looking images.
  Neither WinNT, nor Win2000 suffer from this problem, however.
- Save/restore order and width of columns on score panel.
- SokoForm should also handle Ctrl+Q in addition to other special keys.
[OPENSTEP]
- Re-write OpenStep port so that it utilizes the new core game library rather
  than implementing that logic directly.
- Remember username from New Score panel as default for that panel as a
  convenience to users of Windows 9x who don't actually login with a login
  name.
- Remember the directory from which a new game was loaded during a session, and
  seed the New Game open panel with that location.  This will make it more
  convenient for the user to start new games from a directory other than the
  default New Game directory.
- Programmatically register file extensions at run-time.
- Fix the project file so that it copies `sokohelp' to the application wrapper.
- Add a "Help" menu item.  Implement associated functionality.
- Implement get/set level in SokoPref.
- Break new-score entry panel and functionality out of SokoScores and into its
  own module.
- Implement high-score recording.
- Implement open-default-puzzle functionality for use by SokoApp so that it can
  automatically opens the user's next puzzle.
- Add "Next Puzzle" menu item.  Add the associated functionality.
- Use NSSearchPathForDirectoriesInDomains() to resolve $(SokoUser) if
  available.  It is available on MacOS/X Server 1.0 (Rhapsody) and MacOS/X
  (Cocoa).  On Rhapsody, create a SokoSave subdirectory of the result of
  NSSearchPathForDirectoriesInDomains().  On MacOS/X, take the result of
  NSSearchPathForDirectoriesInDomains() and append "Application Support" before
  appending "SokoSave".  On Windows, use "My Documents", if available,
  otherwise try other directories, such as $(HOME), $(TEMP), $(TMP), the root
  directory of the drive in which the "windows" directory lives, or the root
  directory of the current path.
- When registering file associations on Windows, use an appropriate description
  for each association, rather than the generic "SokoSave Document".
- On MacOS/X and cousins, test if user can cause puzzle view to become occluded
  by changing global display preference.  [None of the display preferences on
  MacOS/X Server 1.0 (Rhapsody) cause trouble.  In fact, changes to these
  preferences are not propagated live; they only take affect the next time the
  program is launched.  If, in the future, these changes are propagated live,
  the only change which may cause problems might be with window title font
  since it changes the overall height of the window.  If this AppKit doesn't
  handle this case properly, then it is conceivable that the puzzle view might
  become occluded at that time.  As for MacOS/X, I was unable to test that
  platform since I still don't have access to it.]
- Probably rename SokoSave_main.m to SokoSave.m.
- On Windows, ensure that the puzzle view does not get occluded by the menu if
  the user changes display preferences via the Control Panel.  For instance,
  the user might assign a larger font to the menu, or the menu might wrap, thus
  occluding the puzzle view.  [Added SokoWindow-windows.m in support of this.
  It sends a notification when an appropriate WM_SETTINGCHANGED message is
  received by the window.  SokoBoard listens for this notification and resizes
  the window as appropriate.]
- Add post-install rule to makefile to remove RCS directory from installed
  resources such as `help' directory (and `puzzle' directory if that uses RCS).
[NEXTSTEP]
- Re-write NextStep port so that it utilizes the new core game library rather
  than implementing that logic directly.
- Remember the directory from which a new game was loaded during a session, and
  seed the New Game open panel with that location.  This will make it more
  convenient for the user to start new games from a directory other than the
  default New Game directory.
- Fix the project file so that it copies `sokohelp' to the application wrapper.
- Add a "Help" menu item.  Implement associated functionality.
- Break new-score entry panel and functionality out of SokoScores and into its
  own module.
- Add "Next Puzzle" menu item.  Add the associated functionality.
- Verify that +setNextLevel: works even when preference panel is on-screen and
  "level" field is first responder.
- Verify that SokoNewPanel correctly processes -textDidGetKeys:isEmpty:.
- See if Slider bug from OpenStep also exists in NextStep.  If so, it will be
  necessary to disable Slider in -advancePlayback:.  [It does indeed exist.]
- Position TableScroll's keyboard cursor at newly added row when a score is
  recorded.
- Verify that adding a new score correctly redraws the TableScroll in all
  positions.
- Probably rename SokoSave_main.m to SokoSave.m.
- Add post-install rule to makefile to remove RCS directory from installed
  resources such as `help' directory (and `puzzle' directory if that uses RCS).

v12
[GENERAL]
- Allow Escape key to deselect crate, in addition to the other methods
  for deselecting a crate.  (Paul requested this feature.)
- Document crate deselection methods in help file.
- Document that arrow keys on keyboard may be used to move player in
  help file.
[OPENSTEP]
- Test-compile on MacOS/X.  [Compiles cleanly, but I still need a
  project file and MacOS/X main-menu nib for the port to be complete.  Will
  also probably need to adjust some window layouts for the larger buttons used
  by MacOS/X.]

v11
[GENERAL]
- Convert from Objective-C++ to Objective-C.
- Implement undo- and redo-push.
- Add a "Stop" button to allow cancellation of playback.
- Implement player dragging.  Also, augment existing point-and-click
  player movement so that player can be dragged immediately from destination
  location if mouse button remains down.
- Implement point-and-click create movement.  As the primary goal, it
  should compute the shortest crate path.  As a secondary goal, it should
  compute the shortest player path needed to satisfy the primary goal.
- Implement crate dragging.  This can be a simple extension of
  point-and-click crate movement.
- Allow quick-push-crate to be invoked with primary mouse button plus
  a modifier key.  This will allow this feature to be invoked even from
  single-button mice.
- Rewrite all puzzle-related code to work with any size puzzles,
  rather than being subject to hard-coded maximum dimensions.
[OPENSTEP]
- Port to MacOS/X Server 1.0 (Mach/Windows) [Rhapsody/YellowBox].
- Update nibs to latest UI layout guidelines.
- On Windows, programmatically register file associations.
[NEXTSTEP]
- Implement menu item validation machinery.

v10
[GENERAL]
- Add a preference item to reset the stored Level.
- Cancel button on preferences panel should revert fields to saved
  values.
- Okay button on prefrences panel should dismiss the panel.
- Preferences panel should mark itself dirty when value is changed,
  and prompt for save when closed with close button.
- The automatic saving of the game when the user completes the level
  should be a user-option.
[OPENSTEP]
- Need a Windows-specific main menu.
- Need a Rhapsody-specific main menu.
- SokoBoard should implement -validateMenuItem: in order to properly
  enable and disable the Undo, Redo, and Save menu items.
- SokoApp should implement -validateMenuItem: in order to properly
  enable and disable the Save All menu item.
- Fix mkdirs() to work with Windoze UNC paths.
- Verify that this package works on Yellow Box.
