Copyright (C)1997,2001,2002 by Eric Sunshine <sunshine@sunshineco.com>
Copyright (C)1997 by Paul McCarthy <zarnuk@high-speed-software.com>

HISTORY.txt

----------------------------------------------------------------- RELEASES ----

5.1, v19, www.high-speed-software.com, 2002/05/06
5.0, v18, www.high-speed-software.com, 2002/02/19
4.0, v17, www.high-speed-software.com, 2002/01/30
3.1, v16, www.high-speed-software.com, 2002/01/18
3.0, v15, www.high-speed-software.com, 2001/12/24
2.3, v14, www.high-speed-software.com, 2001/08/28
2.2, v13, www.high-speed-software.com, 2001/08/21
2.1, v12, www.high-speed-software.com, 2001/08/20
2.0, v11, www.high-speed-software.com, 2001/08/19
1.1, v10, next-ftp.peak.org, 1997/12/10
1.0, v09, next-ftp.peak.org, 1997/11/13

------------------------------------------------------------------- LEGEND ----

History entries are grouped into the following categories.  Each category may
refer to one or more platforms, as noted below.

GENERAL
    All SokoSave ports and platforms.
CBUILDER
    C++Builder (Windows)
OPENSTEP
    MacOS/X (Mach) [Cocoa]
    MacOS/X Server 1.0 (Mach/Windows) [Rhapsody/YellowBox]
    OpenStep 4.2 (Mach/Windows)
NEXTSTEP
    NextStep 3.3 (Mach)

------------------------------------------------------------------ HISTORY ----

*** RELEASE 5.1 ***
v19 2002-05-06 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Augmented the path finding code for crates so that it is now capable of
	discovering arbitrarily complex paths which overlap upon themselves any
	number of times.  Previously, it was limited to finding only
	non-overlapping paths.
    Updated user documentation to reflect the enhanced path finding capability.
    Included additional Hexoban puzzles:
	Aymeric Du Peloux: 10 additional Hexocet, for total of 20.
	Francois Marques:   6 additional Heloban, for total of 16.
	Francois Marques:   7 additional Heroban, for total of 10.
	David W. Skinner:   7 additional, for total of 16.
    ---- CBUILDER -------------------------------------------------------------
    Fixed v17 Win9x problem where animation of Hexoban and Trioban puzzles
	involved unsightly "flashing" which resulted from Windows first
	painting the on-screen hexagonal and triangular tiles black before
	blitting in the actual tile.  To work around the problem,
	SokoGridHexagon and SokoGridTriangle now maintain a backing-store in
	which the puzzle image is rendered.  When the on-screen image needs to
	be repainted, only non-transparent rectangles are blitted to the
	screen.  This patch cuts animation speed effectively in half for
	Hexoban and Trioban puzzles, but the visual quality of the animation is
	much improved.  This problem did not affect WinNT or Win2000.
    Worked around a potential problem where the RCS directories from "help"
	"help/image" were being copied into the installer program if those
	directories were present.  This is a limitation of InnoSetup, in which
	it is not possible to both recurse into subdirectories and filter out
	certain entries (such as the RCS directories).  For now, I removed the
	recursion from the rule which copies the help files into the installer
	program.  This is not a perfect solution, however.
    ---- OPENSTEP -------------------------------------------------------------
    Added script for creation of MacOS/X disk image (.dmg) archive.
    ---- NEXTSTEP -------------------------------------------------------------
    Fixed v15 bug: -[SokoScores formatInt:] was formatting number into one
	buffer but then returning pointer to a different buffer.
    Fixed v15 bug: SokoScores was reporting a "buffer count" of two to
	MiscTableScroll, but -formatInt: only maintained two buffers, though it
	really needed eight (two each for four numeric columns).  Rather than
	allocating 512 bytes for these static buffers, which are very rarely
	used, I instead eliminated the "buffer count" optimization altogether.

    Changed Files:
    * cbuilder/SokoBoard.{h|cpp}
    * cbuilder/SokoGrid.{h|cpp}
    * cbuilder/SokoGridHexagon.{h|cpp}
    * cbuilder/SokoGridTriangle.{h|cpp}
    * cbuilder/SokoSave.iss
    * common/SokoPuzzle.c
    * help/SokoHelp.html
    * nextstep/SokoScores.m
    * openstep/README_BINARY_MACOSX.txt
    + puzzle/hexoban/dws[010-016].hsb
    + puzzle/hexoban/heloban[11-16].hsb
    + puzzle/hexoban/heroban[03-10].hsb
    + puzzle/hexoban/hexocet[11-20].hsb
    + puzzle/sunshine/sunshine001.xsb
    + puzzle/sunshine/sunshine002.hsb
    + puzzle/sunshine/sunshine003.tsb
    + util/make_dmg.sh

*** RELEASE 5.0 ***
v18 2002-02-19 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Added support for new triangular-style Trioban puzzles.
    Fixed bug: Wrong scores were recorded after loading a saved game and
	achieving a new high score for one of the metrics.  Problem was that it
	was sending the "best" scores for all metrics to the SCORES file entry
	for this game, rather than the actual scores for each metric for this
	game.  (v17 bug)
    Fixed bug: Least-cost player movement in crate path finding was broken.
	There was a case where it would not choose the path with least
	player-movement cost.  Problem was that shortest_crate_path() was not
	tracking sufficient information.  It was only tracking the minimum
	player-movement cost from cell to cell but did not know from which
	previous cell that cost arose.  This was a problem during the final
	path gleaning step when walking backward over the flood-fill if it came
	to a cell at which player-movement cost was the same from more than one
	approach.  It was unable to decide which approach was less costly for
	the previous push over which it had just walked backward.  (v11 bug)
    Fixed bug: Auto-detection of even-on-even/odd-on-even for Hexoban puzzles
	did not work when meta-data appeared in the file before the puzzle
	data.
    SokoPuzzle now maintains the raw meta-data from the puzzle file rather than
	merely ignoring it.  Clients may access the raw data via the new
	SokoPuzzle meta_data() method.
    SokoPuzzle now parses a puzzle's meta-data and builds a list of key/value
	tuples from it.  The tuples are extracted from lines which resemble
	"Keyword: value", optionally preceded by any number of semi-colons
	(`;') since many existing puzzle sets use this format.  Clients may
	look up keywords (case insensitive) or retrieve the entire list of
	key/value tuples.
    SokoPuzzle now recognizes the following (case insensitive) "pragmas" in
	puzzle files and save files.  These pragmas may be useful for puzzle
	authors at design time, since they allow the author to disable
	behaviors which are typically undesirable and/or annoying during the
	iterative edit-test-edit-test design cycle.
	    Pragma: no-high-score
		Inhibits recording high scores and prevents launch of "New
		Score" panel.
	    Pragma: no-auto-save
		Inhibits automatic saving of game when solved.
	    Pragma: no-auto-advance
		Inhibits advancing the user's "highest" level.
    SokoPuzzle now exports all meta-data from the original puzzle file to the
	saved-game file.
    Consolidated all of the geometry-related utility code into the new
	SokoGeometry facility.  This mechanism provides hit-testing and
	coverage-testing facilities for square-, hexagonal-, and
	triangular-tiled grids.  All high-level GUI code now utilizes these
	facilities rather than relying upon their own copy/paste
	implementations.
    Consolidated the user-interface movement constraints into SokoPuzzle rather
	than having the same code repeated in each port.  This code decides
	whether or not the direction movement buttons in the user-interface
	should be enabled depending upon cell type, orientation, etc.  Added
	the SokoPuzzle methods can_move_constrained() and
	can_move_diagonal_constrained() to complement the existing can_move()
	and can_move_diagonal().
    Previously, for square puzzles, the diagonal movement buttons in the
	user-interface would be disabled if any pushes were involved in the
	diagonal movement.  This is no longer the case.
    Unified the appearance of the SokoWall image throughout project.  In some
	cases, the "highlighted" border was composed of two rows of white
	pixels, whereas in other cases, it was white plus light grey.  Now it
	is white plus light grey throughout.
    Fixed bug: SokoPuzzle was leaking a file descriptor each time a puzzle was
	loaded.
    Updated FILE_SYNTAX.txt to mention Trioban puzzles and meta-data, and to
	better explain the "best" scores in the save file.
    Paul wrote a new trim_scores.cc program to replace the old trim_scores.sh
	script.  This program correctly deals with the new "runs" and "focus"
	scores (even when they are -1 indicating that the scores were absent),
	and also supports a new "solution" field in the score record (though
	the solution is not yet stored with the score).
    Aymeric du Peloux <aymeric.dupeloux@smile.fr> sent his Hexocet puzzles 1
	through 10 for inclusion in SokoSave.  These replace the adp001 through
	adp008 puzzles included with v17.  Note, however, that puzzle 8 has
	changed.
    Folded in new high scores from Paul and Eric.
    ---- CBUILDER -------------------------------------------------------------
    Moved the BITMAP declarations for the tiles out of SokoBoard.rc and into
	the new SokoGridSquare.rc, SokoGridHexagon.rc, and SokoGridTriangle.rc.
    Fixed bug: Some of the file mask descriptions on the new/open panels had
	an errant leading semi-colon.
    Now notifies Windows shell after all file associations have been made,
	rather than after each registration.
    Made the SokoSave.iss setup script more robust.  Now takes advantage of
	the "recursesubdirs" flags to ensure that all subdirectories of
	`puzzle' and `help' are included in the setup program, instead of
	naming each subdirectory manually.
    ---- OPENSTEP -------------------------------------------------------------
    Fixed inconsistency where the normal and "goal" tiles were swapped on some
	of the 2-bit gray document icons.
    Now notifies Windows shell after all file associations have been made,
	rather than after each registration.
    ---- NEXTSTEP -------------------------------------------------------------
    Fixed inconsistency where the normal and "goal" tiles were swapped on some
	of the 2-bit gray document icons.

    Changed Files:
    * cbuilder/README.txt
    * cbuilder/README_BINARY.txt
    * cbuilder/SokoApp.{h|cpp}
    * cbuilder/SokoBoard.{cpp|rc}
    + cbuilder/SokoCrateTri{N|S}.bmp
    + cbuilder/SokoCrate{Safe|Selected|SafeSelected}Tri{N|S}.bmp
    + cbuilder/Soko{Empty|EmptySafe}Tri{N|S}.bmp
    * cbuilder/SokoGridHexagon.{c|cpp}
    + cbuilder/SokoGridHexagon.rc
    * cbuilder/SokoGridSquare.cpp
    + cbuilder/SokoGridSquare.rc
    + cbuilder/SokoGridTriangle.{h|cpp|rc}
    + cbuilder/Soko{Player|PlayerSafe}Tri{N|S}.bmp
    + cbuilder/SokoPuzzleTri.ico
    * cbuilder/SokoSave.{bpr|cpp|iss|rc}
    + cbuilder/SokoWallTri{N|S}.bmp
    * common/SokoCore.dep
    + common/SokoGeometry.{h|c}
    * common/SokoPuzzle.{h|c}
    * FILE_SYNTAX.txt
    * help/SokoHelp.html
    + help/images/Soko{Crate|CrateSelected}TriN.gif
    + help/images/Soko{Empty|ExmptySafe}TriN.gif
    + help/images/SokoPlayerTriN.gif
    * help/images/SokoSave.png
    + help/images/SokoWallTriN.gif
    * nextstep/Makefile
    * nextstep/Makefile.preamble
    * nextstep/PB.project
    * nextstep/README.txt
    * nextstep/README_BINARY.txt
    * nextstep/SokoBoard.m
    + nextstep/SokoCrateTri{N|S}.tiff
    + nextstep/SokoCrate{Safe|Selected|SafeSelected}Tri{N|S}.tiff
    + nextstep/Soko{Empty|EmptySafe}Tri{N|S}.tiff
    * nextstep/SokoGame.tiff
    * nextstep/SokoMatrix.{h|m}
    * nextstep/SokoMatrixHexagon.{h|m}
    * nextstep/SokoMatrixSquare.{h|m}
    + nextstep/SokoMatrixTriangle.{h|m}
    + nextstep/Soko{Player|PlayerSafe}Tri{N|S}.tiff
    * nextstep/SokoPuzzle.tiff
    + nextstep/SokoPuzzleTri.tiff
    * nextstep/SokoSave.{iconheader|tiff}
    * nextstep/SokoWall.tiff
    + nextstep/SokoWallTri{N|S}.tiff
    * openstep/CustomInfo.plist
    * openstep/Makefile
    * openstep/PB.project
    * openstep/README.txt
    * openstep/README_BINARY_MACOSX.txt
    * openstep/README_BINARY_MACOSXS_MACH.txt
    * openstep/README_BINARY_MACOSXS_WIN.txt
    * openstep/README_BINARY_OPENSTEP_MACH.txt
    * openstep/README_BINARY_OPENSTEP_WIN.txt
    * openstep/SokoApp.m
    * openstep/SokoApp-windows.c
    * openstep/SokoBoard.m
    + openstep/SokoCrateTri{N|S}.tiff
    + openstep/SokoCrate{Safe|Selected|SafeSelected}Tri{N|S}.tiff
    + openstep/Soko{Empty|EmptySafe}Tri{N|S}.tiff
    * openstep/SokoGame.{tiff|icns}
    * openstep/SokoMatrix.{h|m}
    * openstep/SokoMatrixHexagon.{h|m}
    * openstep/SokoMatrixSquare.{h|m}
    + openstep/SokoMatrixTriangle.{h|m}
    + openstep/Soko{Player|PlayerSafe}Tri{N|S}.tiff
    * openstep/SokoPuzzle.{tiff|icns}
    + openstep/SokoPuzzleTri.{tiff|icns|ico}
    * openstep/SokoSave.pbproj/project.pbxproj
    * openstep/SokoSave.{iconheader|tiff|icns}
    * openstep/SokoWall.tiff
    + openstep/SokoWallTri{N|S}.tiff
    - puzzle/hexoban/adp00[1-8].hsb
    + puzzle/hexoban/hexocet/hexocet[01-10].hsb
    + puzzle/trioban/
    * README.txt
    * README_RCS.txt
    * SCORES
    - util/trim_scores.sh
    + util/trim_scores.cc

*** RELEASE 4.0 ***
v17 2002-01-30 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    No longer fills areas outside the puzzle with wall segments.  Doing so
	causes some "artistic" effect to be lost from some puzzles.  Added
	SokoCellType SOKO_CELL_NULL to support of this.
    Flattened the wall segment graphic.  Its previous extreme 3D effect tended
	to overwhelm the puzzle board.
    Added support for the new hexagonal-style Hexoban puzzles.
    Made puzzle parser sufficiently robust to determine whether a hexagonal
	puzzle is using the conventional even-on-even/odd-on-odd rule or the
	unconventional even-on-odd/odd-on-even rule.  Since there is an chance
	that puzzle designers will not follow convention, it is safest to
	recognize both styles and adjust dynamically.
    Added SokoPuzzleStyle enumeration to SokoPuzzle.  Styles are
	SOKO_STYLE_SQUARE and SOKO_STYLE_HEXAGON.
    Now recognize these additional file extensions: .xsb, .hsb, .sokohex.
    Added new document icon for .hsb and .sokohex extensions.
    Removed soko_get_puzzle_extension() and soko_get_save_extension() from
	SokoFile.
    Relocated functionality of soko_save_filename_for_puzzle(),
	soko_puzzle_name_for_level(), and soko_level_for_puzzle_name() from
	SokoFile to SokoPuzzle, where they are class methods of SokoPuzzle.
    Added get_puzzle_extensions(), get_puzzle_extensions_count(), and
	get_save_extension() as class methods to SokoPuzzle.  There are now
	multiple recognized puzzle extensions, rather than just the one
	(.sokomaze).
    Added file_is_puzzle(), file_is_save_game(), and get_file_style() class
	methods to SokoPuzzle.
    Added soko_extension_part() to SokoUtil.
    As an interim step to full puzzle-set support, the puzzle loader now
	ignores comment lines in files (such as those in many .xsb files).  A
	comment is defined as a line that begins with any non-puzzle character
	(with optional leading whitespace).
    Extended keyboard movement support.  Numeric keypad can now be used, as
	well as standard arrow keys.  Added key equivalents for hexagonal
	puzzles.
    Augmented the behavior of the "Animate" switch so that it now controls all
	animation, rather than only controlling animation of lengthy playback
	sessions, which was the case previously.
    For consistency, point-and-click crate movement now falls into crate-drag
	mode, just as point-and-click player movement falls into player drag
	mode.
    Removed unused CELL_HEIGHT and CELL_WIDTH constants from SokoPuzzle.c.
    SokoPuzzle now calculates two new scores in addition to "moves" and
	"pushes".  The "runs" score is the number of straight lines in which
	crates have been pushed.  Looked at another way, it is the number of
	turns crates have made while being pushed.  The "focus" score is the
	number of times the player's focus has changed from one crate to
	another.
    Now records "runs" and "focus" scores in save file.
    Now records puzzle-style ("square" or "hexagon") in save file.
    The following pieces of information are no longer recorded in the save file
	since they can be derived automatically from other recorded data:
	history-max, current-move-count, current-push-count, puzzle-height,
	puzzle-width.
    No longer compresses the history or the puzzle representation in the save
	file.
    Now uses the original puzzle tokens to encode the puzzle in the save files
	rather than the internal SokoPuzzle tokens.  This means that the puzzle
	representation in the save file is now human-readable.
    Bumped the save file version number to 2 in response to all the changes to
	the save file format.  (Still capable of reading version 1 files.)
    Broke down and rewrote the save-file parser in order to simplify and
	modularize it.  (It was getting far too complex in its old monolithic
	form.)
    Parser of version 1 saved puzzles now transforms unreachable tiles to
	"empty" at load time.  This gives version 1 saved games an appearance
	consistent with newer games (where empty space surrounding the puzzle
	is left empty), rather than using the old appearance where all
	unreachable tiles were marked as walls.
    Upgraded the documentation to explain hexagonal support and to explain that
	numeric keypad can now be used for movement.
    Fixed bug in handling of "best" move/push count in save file.  Was
	incorrectly updating both numbers even if only one was bettered.  For,
	for example, if a game had "best" counts of 100/10, and player achieved
	90/20, then "best" counts of 90/20 would be recorded, even though they
	should have been 90/10.
    Added soko_read_line_terminator() to SokoUtil.  Unlike soko_read_line()
	which always null-terminates the returned string even if the input line
	would have overflowed the buffer, this function allows control over the
	termination.
    SokoScore now records "runs" and "focus" scores in SCORES file.
    Added "runs" and "focus" scores controls to SokoBoard.
    Added "runs" and "focus" scores columns to scores panel and to "New Score"
	panel.
    Added discussion of new score metrics to help file.
    Updated FILE_SYNTAX.txt to to explain the format of hexagonal puzzles, and
	to reflect the changes to the save file format and score file format.
    Did more fine-tuning of the gamma of the help file images.
    Updated the movement example images in help to reflect new appearance of
	tiles and game board.
    Added "hexoban" subdirectory of "puzzle" which contains all known hexagonal
	puzzles.  Added appropriate attributions to the help file for puzzle
	authors.
    Added the script make_src_pkg.sh which extracts the source files from RCS
	and prepares them for release as a source-code package.  One of the
	important aspects of this script is conversion of text files in the
	cbuilder directory to CRLF line-termination.  It also removes files
	which have no meaning in the bare source code distribution.
    Now strips the file extension from the puzzle name on the new-score panel.
    Updated the README files to mention hexagonal support.
    Updated pack.sh so that it tags entire RCS directories at once, rather than
	tagging each file individually.
    ---- CBUILDER -------------------------------------------------------------
    Applied more gamma correction to the puzzle tiles to make them slightly
	lighter.
    No longer uses TDrawGrid for display of puzzle.
    Added TSokoGrid, a subclass of TGraphicControl which is the base class for
	grids which display puzzle boards.
    Added TSokoGridSquare, a subclass of TSokoGrid, which knows how to draw
	square-tiled puzzles, and perform appropriate hit-testing.
    Added TSokoGridHexagon, a subclass of TSokoGrid, which knows how to draw
	hexagon-tiled puzzles, and perform appropriate hit-testing.
    Fixed a number of aesthetic problems which showed up when using larger
	control sizes and fonts.  Controls would clobber one another and text
	would be clipped.  The problems were particularly acute when using
	"Large Fonts" from the Windows Display/Advanced settings.
    Added `user_resizing' property to SokoForm which is `true' during a user-
	initiated window resize operation.  This provides clients with the
	capability to make constraint decisions based upon the agent which is
	resizing a window, rather than always applying constraints, regardless
	of whether resizing was initiated by the user or by Windows (for
	instance, if font metrics had changed).
    SokoScores now adjusts row height of the TStringGrid, if necessary, to
	account for large fonts.
    SokoPref controls no longer become all jumbled together if user has
	selected large fonts.  Also, added a TPanel behind all of the controls
	to keep them from falling off bottom of window when user changes Window
	display scheme.
    SokoNewScore controls no longer become all jumbled together if user has
	selected large fonts.  Also, added a TPanel behind all of the controls
	to keep them from falling off bottom of window when user changes Window
	display scheme.
    SokoBoard's score labels now have AutoSize enabled.  This allows them to
	grow as needed when user has selected a large font size, thus
	preventing the text on the labels from being clipped.
    Updated copyright notice on SokoInfo panel.
    The ISS setup script no longer copies README_BINARY.txt into the output
	directory.  Having that README file present in the source package was
	inconsistent since the other README_BINARY files are not present.
    ---- OPENSTEP -------------------------------------------------------------
    Rewrote SokoMatrix.  It is now a generic base class for rendering grids.
	No longer based upon NSMatrix (which was only capable of supporting
	rectangular cells).  Custom rendering is now done, rather than relying
	upon NSMatrix.  Consequently, animation speed has increased by a factor
	of five or more.
    Added SokoMatrixSquare, a subclass of SokoMatrix, which knows how to draw
	square-tiled puzzles, and perform appropriate hit-testing.
    Added SokoMatrixHexagon, a subclass of SokoMatrix, which knows how to draw
	hexagon-tiled puzzles, and perform appropriate hit-testing.
    Added descriptions for new .sokohex, .xsb, and .hsb file associations to
	CustomInfo.plist.  Also removed hard-coded .ico extension from icon
	names in this list, since the extensions were meaningful only for
	Windows.
    ---- NEXTSTEP -------------------------------------------------------------
    Rewrote SokoMatrix.  It is now a generic base class for rendering grids.
	No longer based upon Matrix (which was only capable of supporting
	rectangular cells).  Custom rendering is now done, rather than relying
	upon Matrix.  Consequently, animation speed has increased by a factor
	of five or more.
    Added SokoMatrixSquare, a subclass of SokoMatrix, which knows how to draw
	square-tiled puzzles, and perform appropriate hit-testing.
    Added SokoMatrixHexagon, a subclass of SokoMatrix, which knows how to draw
	hexagon-tiled puzzles, and perform appropriate hit-testing.

    Changed Files:
    * cbuilder/README.txt
    * cbuilder/README_BINARY.txt
    * cbuilder/SokoApp.cpp
    * cbuilder/SokoBoard.{h|cpp|rc|dfm}
    * cbuilder/Soko{Crate|CrateSafe|CrateSelected|CrateSafeSelected}.bmp
    + cbuilder/Soko{Crate|CrateSafe|CrateSelected|CrateSafeSelected}Hex.bmp
    * cbuilder/Soko{Empty|EmptySafe}.bmp
    + cbuilder/Soko{Empty|EmptySafe}Hex.bmp
    * cbuilder/SokoForm.{h|cpp}
    + cbuilder/SokoGrid.{h|cpp}
    + cbuilder/SokoGridHexagon.{h|cpp}
    + cbuilder/SokoGridSquare.{h|cpp}
    * cbuilder/SokoInfo.dfm
    * cbuilder/SokoNewScore.{h|cpp|dfm}
    * cbuilder/Soko{Player|PlayerSafe}.bmp
    + cbuilder/Soko{Player|PlayerSafe}Hex.bmp
    * cbuilder/SokoPref.{h|cpp|dfm}
    + cbuilder/SokoPuzzleHex.ico
    * cbuilder/SokoSave.{bmp|bpr|cpp|iss|rc}
    * cbuilder/SokoScores.{h|cpp|dfm}
    * cbuilder/SokoWall.bmp
    + cbuilder/SokoWallHex.bmp
    * common/SokoDefs.h
    * common/SokoFile.{h|c}
    * common/SokoPuzzle.{h|c}
    * common/SokoScore.{h|c}
    * common/SokoUtil.{h|c}
    * common/SokoWrap.h
    * FILE_SYNTAX.txt
    * help/SokoHelp.html
    * help/images/SokoCrate.png
    * help/images/SokoCrateSelected.png
    + help/images/Soko{Crate|CrateSelected}Hex.gif
    + help/images/Soko{Empty|ExmptySafe}Hex.gif
    * help/images/SokoEmpty.png
    * help/images/SokoEmptySafe.png
    * help/images/SokoExample{1|2|3}.gif
    > help/images/SokoExample{1|2|3}.png --> SokoExample{1|2|3}.gif
    * help/images/SokoPlayer.png
    + help/images/SokoPlayerHex.gif
    * help/images/SokoSave.png
    * help/images/SokoWall.png
    + help/images/SokoWallHex.gif
    * nextstep/Makefile
    * nextstep/PB.project
    * nextstep/README.txt
    * nextstep/README_BINARY.txt
    * nextstep/SokoBoard.{h|m|nib}
    + nextstep/Soko{Crate|CrateSafe|CrateSelected|CrateSafeSelected}Hex.tiff
    + nextstep/Soko{Empty|EmptySafe}Hex.tiff
    * nextstep/SokoMatrix.{h|m}
    + nextstep/SokoMatrixHexagon.{h|m}
    + nextstep/SokoMatrixSquare.{h|m}
    * nextstep/SokoNewScore.{h|m|nib}
    + nextstep/Soko{Player|PlayerSafe}Hex.tiff
    + nextstep/SokoPuzzleHex.{tiff|icns}
    * nextstep/SokoSave.iconheader
    * nextstep/SokoScores.{h|m|nib}
    * nextstep/SokoWall.tiff
    + nextstep/SokoWallHex.tiff
    * openstep/CustomInfo.plist
    * openstep/Makefile
    * openstep/PB.project
    * openstep/README.txt
    * openstep/README_BINARY_MACOSX.txt
    * openstep/README_BINARY_MACOSXS_MACH.txt
    * openstep/README_BINARY_MACOSXS_WIN.txt
    * openstep/README_BINARY_OPENSTEP_MACH.txt
    * openstep/README_BINARY_OPENSTEP_WIN.txt
    * openstep/SokoApp.m
    * openstep/SokoBoard.{h|m|nib}
    * openstep/SokoConfig.h
    + openstep/Soko{Crate|CrateSafe|CrateSelected|CrateSafeSelected}Hex.tiff
    + openstep/Soko{Empty|EmptySafe}Hex.tiff
    * openstep/SokoMatrix.{h|m}
    + openstep/SokoMatrixHexagon.{h|m}
    + openstep/SokoMatrixSquare.{h|m}
    * openstep/SokoNewScore.{h|m|nib}
    + openstep/Soko{Player|PlayerSafe}Hex.tiff
    + openstep/SokoPuzzleHex.{icns|ico|tiff}
    * openstep/SokoSave.iconheader
    * openstep/SokoSave.pbproj/project.pbxproj
    * openstep/SokoScores.{h|m|nib}
    * openstep/SokoWall.tiff
    + openstep/SokoWallHex.tiff
    + puzzle/hexoban
    * README.txt
    * README_RCS.txt
    + util/make_src_pkg.sh
    * util/pack.sh

*** RELEASE 3.1 ***
v16 2002-01-18 sunshine@sunshineco.com
    ---- OPENSTEP -------------------------------------------------------------
    MacOS/X is now officially supported.  Matt Reda <mreda@mac.com> created the
	project file and Aqua-compatible main-menu nib for MacOS/X.  He also
	patiently and iteratively provided important feedback about the
	appearance of SokoSave's windows and controls in the Aqua environment.
    Added SokoSave-aqua.nib, which is the main-menu nib for MacOS/X.
    Added InfoPlist.strings, which is localization information for the MacOS/X
	Info.plist.
    Added SokoSave.pbproj and SokoSave.pbproj/project.pbxproj which is the
	ProjectBuilder project resource for MacOS/X.
    Added SokoGame.icns, SokoPuzzle.icns, and SokoSave.icns, which are the
	icons for the MacOS/X file associations.
    Adjusted sizes and layout of controls on SokoBoard and SokoPref windows to
	ensure that they look correct on Aqua.  (Controls in Aqua tend to
	require more screen real-estate and surrounding whitespace.)
    Added code to -[SokoBoard configureControls] to set a few control
	attributes for nicer appearance on Aqua.
    Worked around problem on MacOS/X where open panel would not allow user to
        browse to "puzzle" directory inside application wrapper.
    Fixed bug: +[SokoBoard openPuzzle:] was calling SokoPuzzle_destroy() with a
	null pointer.  (v15 bug)
    Updated copyright notice on SokoInfo panel.
    Updated pack_binaries.sh and unpack.sh to work with new .icns files.
    Fixed bug: Makefile `install' target crashed when building normal source
	code distribution (as opposed to RCS distribution).
    ---- NEXTSTEP -------------------------------------------------------------
    Fixed bug: +[SokoBoard openPuzzle:] was calling SokoPuzzle_destroy() with a
	null pointer.  (v15 bug)
    Updated copyright notice on SokoInfo panel.
    Updated SokoBoard and SokoPref window layouts to match changes in OpenStep
	port.
    Fixed bug: Makefile `install' target crashed when building normal source
	code distribution (as opposed to RCS distribution).

    Changed Files:
    * cbuilder/README.txt
    * nextstep/README.txt
    * nextstep/SokoBoard.{m|nib}
    * nextstep/SokoInfo.nib
    * nextstep/SokoPref.nib
    + openstep/InfoPlist.strings                (MacOS/X resource)
    * openstep/README.txt
    + openstep/README_BINARY_MACOSX.txt
    * openstep/SokoBoard.{m|nib}
    * openstep/SokoGame.icns
    * openstep/SokoInfo.nib
    * openstep/SokoPref.nib
    * openstep/SokoPuzzle.icns
    + openstep/SokoSave.icns
    + openstep/SokoSave.pbproj/                 (MacOS/X project resource)
    + openstep/SokoSave.pbproj/project.pbxproj
    + openstep/SokoSave-aqua.nib                (MacOS/X main menu)
    * pack_binaries.sh
    * unpack.sh

*** RELEASE 3.0 ***
v15 2001-12-24 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Extracted core game logic out of GUI code and generalized it so that the
	same core code can be used by any platform.  Logic from SokoBoard.m now
	resides in SokoPuzzle.c, etc.
    Augmented all input/output logic so that it now deals gracefully with line
	terminators from all common platforms; Unix (LF), Macintosh (CR), and
	Windows/DOS (CRLF).
    SokoPuzzle now understands the token "+" as player-safe, since this is what
	is used by XSokoban, and used in numerous existing add-on puzzles.  The
	"^" token which was historically understood by SokoSave is still
	recognized, but is no longer published in the documentation.
    For safety, SCORES is now written out immediately after a new score is
	recorded, rather than only at program termination time.
    SokoPuzzle no longer complains about loading puzzles with unreachable
	crates, provided that those crates are already on goal squares.  This
	allows some existing add-on puzzles to be used with SokoSave.
    Created wrappers for the new core game library so that it can be accessed
	easily from C, Objective-C, and C++.
    Email addresses (and names) on Info panel are now active links which launch
	the mail program.  The email addresses appears underlined as the mouse
	flies over it.
    Added a SokoSave URL to the Info panel.  The URL is an active link which
	launches the web browser when clicked.  The URL appears underlined as
	the mouse flies over it.
    Replaced the terminology "maze" with "puzzle" throughout the project,
	including source code, documentation, and all user-visible UI elements.
	The only remaining place where "maze" is still used is in the file
	extension ".sokomaze".  I haven't decided what, if anything, to do
	about that, yet.
    Converted the documentation from RTFD format to HTML format.  Documentation
	is no longer embedded in a scrollable text object on the Info panel.
	Instead, a "Help" menu item now displays the help file via a web
	browser.
    Cleaned up and clarified the Help document a bit.  Fixed a grammatical
	error or two.  Added a "Credits" section to the "Conclusion".
    Added the new pseudo-variable $(SokoUser) which points at the user's
	"personal" file space.  This is where user-specific SokoSave files are
	stored by default.  This variable complements the existing $(SokoSave)
	variable.
    Added SokoPool which is a memory pool object.  This is used heavily by the
	string manipulation functions in SokoUtil to ensure that composed
	pathnames and strings do not go out of scope before the client is
	finished with them.  This replaces the old statically allocated,
	circular array of pathname buffers which was used in the past.
    Renamed soko_collapse() to soko_collapse_path(). Renamed soko_expand() to
	soko_expand_path().
    The path setting functions in SokoFile now invoke soko_collapse_path() on
	all set operations.  This ensures that all paths displayed on the
	preferences panel are properly collapsed, and removes the onus of this
	task from the UI code.  Previously, soko_collapse_path() was only
	called by the UI code for the puzzle path.
    Added soko_collapse() to SokoUtil.  This function trims leading and
	trailing whitespace from a string and collapses all internal whitespace
	to a single space.
    Added soko_trim(), soko_ltrim() and soko_rtrim() to SokoUtil.
    Added portable soko_stricmp() and soko_strnicmp() to replace non-portable
	use of strcasecmp() and/or stricmp().
    Renamed soko_starts_with() and soko_ends_with() to soko_has_prefix() and
	soko_has_suffix(), respectively.  Also added an input flag which
	controls case-sensitivity of these functions.
    Added soko_normalize_path() and soko_denormalize_path() to SokoUtil.  All
	path manipulation functions now utilize these functions in order to
	ensure correctness of path parsing and composition on all platforms.
    SokoPuzzle now stores the original .sokomaze path in the .sokosave file in
	normalized form rather than platform-specific form.
    Moved soko_filename_part(), soko_directory_part(), soko_basename(), and
	soko_mkdir() from SokoFile to SokoUtil.  Augmented these functions so
	that they work correctly with pathnames from Unix, Macintosh, and
	Windows (including Microsoft's UNC-style pathnames).
    Added soko_add_path_component(), soko_add_path_extension(),
	soko_replace_path_extension(), soko_remove_path_extension(), and
	soko_path_exists() to SokoUtil.  These functions deal correctly with
	pathnames from Unix, Macintosh, and Windows (including Microsoft's
	UNC-style pathnames).
    Added soko_readline() to SokoUtil.  This function is a replacement for
	fgets().  It correctly handles Unix (LF), Macintosh (CR), and
	Windows/DOS (CRLF) line terminators.
    Renamed soko_get_maze_extension() and soko_get_maze_directory() in SokoFile
	to soko_get_puzzle_extension() and soko_get_puzzle_directory(),
	respectively.
    Added soko_set_puzzle_directory(), soko_set_save_directory(), and
	soko_set_score_file() to SokoFile in order to complement the existing
	"get" functions and to centralize control over these settings.
    Added soko_get_default_puzzle_directory(), get_default_save_directory(),
	and soko_get_default_score_file() to SokoFile.  These functions return
	values appropriate for the corresponding fields on the Preferences
	panel of each port when the "Defaults" button is pressed.
    Renamed soko_save_filename_for_maze_name() and soko_maze_name_for_level()
	in SokoFile to to soko_save_filename_for_puzzle_name() and
	soko_puzzle_name_for_level(), respectively.
    Added soko_level_for_puzzle_name() to SokoFile.  This function is used by
	the new "Next Puzzle" menu item and shortcut.
    Augmented soko_collapse_path() so that it also knows how to emit
	$(SokoUser), $(HOME), $(TEMP), and $(TMP), in addition to the existing
	$(SokoSave).
    Added SokoSetting implementation which provides a platform-independent API
	for accessing user settings and well-known paths, such as $(SokoSave)
	and $(SokoUser).
    Created 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.  Created both ICO and TIFF
	formats.
    SokoScore now trims and collapses strings before recording them in the
	score table.
    Added a "Next Puzzle" menu item (and toolbar shortcut), which opens the
	puzzle that comes "next" after the puzzle in the active window.
    Changed the logic used to locate the puzzle which is opened automatically
	at program launch time.  Previously, it simply opened a .sokomaze file
	with the level number recorded as the "highest" level.  Unfortunately,
	if the user then tried to open a saved game file with the same level
	number, the program would not actually open the saved game because it
	thought that the game was already open.  This made it very difficult
	for the user to continue a saved game which matched the "highest"
	level.  The user first has to close the "new" game and then open the
	"saved" game.  This problem was even further complicated on the Windows
	platform where closing the "new" game would cause the program to
	terminate if that was the only menu-bearing window.  Since it is
	probable that a user may save a game before actually arriving at the
	solution with the intention of returning to that game later, the
	program now makes it much easier to return to the saved game.  Now, at
	launch time, the program first checks for a "saved" game matching the
	"highest" level and open that if present.  If not, then it falls back
	to opening a new game.
    For safety, user defaults (including score panel column order and widths)
	are now committed immediately, rather than at termination time.
    Rewrote solved-check logic in SokoPuzzle so that it is now much more
	optimal; no longer needs to scan entire puzzle each time it wants to
	check if puzzle is solved.
    Fixed bug: Puzzle would not become "unsolved" when a crate was moved away
	from a goal square after already having been solved.  Fixed so that it
	now correctly reflects all changes to the solved state.
    Completely re-worked playback animation logic.  The pseudo-modal loop which
	specially filtered and dispatched events is no longer used.  Instead,
	animation is now driven from the main event loop and occurs in tandem
	with the receipt and processing of normal user events.  Rather than
	trying to restrict and filter user events, all events are now handled
	as usual, except that some events may have the side-effect of aborting
	playback.  There are now several different mechanisms for aborting
	playback: pressing the stop button, pressing Escape, clicking in the
	puzzle view, switching to a different window, deactivating the
	application (for instance, by clicking on the window of a another
	application, or hiding SokoSave).
    Updated FILE_SYNTAX.txt to reflect the recent changes and to correct or
	clarify some of the discussion.
    Merged NextStep and OpenStep history files into conglomerate HISTORY.txt.
	Also merged in history entries for the new C++Builder port.  Did the
	same merging for BUGS.txt and TODO.txt.
    Moved the utility shells scripts (pack_binaries.sh, trim_scores.sh, etc.)
	into the new "util" subdirectory.
    Rewrote unpack.sh, pack_binaries.sh, and unpack_binaries.sh to deal with
	all of the new binary files present in the conglomerate source code
	package.
    Rewrote pack.sh to deal with the new package layout and directory names
	(i.e. the "Maze" directory became "puzzle").  Automatically updates
	the new "sokocore" SokoBuild.h and SokoRelease.h files with the build
	and release numbers input by the user.  (The old PACKAGE_NUMBER file is
	gone.)  Removed the hard-coded Unix pathnames in order to improve
	portability.  Merged the old freeze.sh directly into pack.sh.
    Fixed trim_scores.sh so that it no longer throws away scores from puzzles
	whose names are not entirely numeric.  Also made trim_scores.sh a bit
	more portable by removing hard-coded Unix pathnames.
    Folded in new high-scores from Eric.
    Rewrote and/or updated all of the README files for both source and binary
	distributions to reflect the new conglomerate package.
    ---- CBUILDER -------------------------------------------------------------
    Created a native Windows port of SokoSave using C++Builder.  The back-end
	logic for this port is provided by the new "sokocore" common code which
	used to be merged with the UI code for the OpenStep/NextStep ports.
	From the user-experience, this port is nearly identical to the existing
	OpenStep and NextStep ports.  Builds successfully with C++Builder
	versions 4 and 5.
    Added a shortcut toolbar for quickly starting new games, opening saved
	games, saving games, launching the scores panel, and launching the help
	file.  Added a toggle-switch to the preferences panel to control
	presence of toolbar.  From the user-standpoint, this is the only major
	difference from the OpenStep/NextStep ports, since they do not feature
	a shortcut toolbar.
    Created an InnoSetup installer script for SokoSave.  This scripts
	facilitates the creation of a stand-alone "setup" program
	(soksetup.exe) for SokoSave.  With this program, Windows users can
	download and install SokoSave in a fashion in which they are already
	familiar.
    ---- OPENSTEP -------------------------------------------------------------
    Rewrote the OpenStep port so that it utilizes the new "sokocore" game
	library rather than implementing that logic directly.
    Now remembers 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
	username.
    Now remembers the directory from which a new game was loaded during a
	session, and seeds the New Game open panel with that location.  This
	makes it more convenient for the user to start new games from a
	directory other than the default New Game directory.  (It was very
	annoying for the program to revert to the factory directory each time
	New Game was invoked.)
    Added a "Help" menu item which opens the HTML help file in a web browser.
	Previously, the help information was contained in an RTFD file and
	loaded directly into a text object on the Info panel.
    Added SokoAlerter which provides a convenience function used by the new
	SokoPuzzleDelegate and SokoScoreDelegate implementations to send alert
	messages to the user from those core modules.
    Added new small ICO to SokoSave.ico.  Also re-drew large ICO.
    Split new-score entry panel and functionality out of SokoScores and into
	its own module, SokoNewScore.
    No longer assumes that default location for user-files is $(HOME)/Library,
	in all cases.  Now uses NSSearchPathForDirectoriesInDomains() to
	resolve $(SokoUser) if available.  It is available on MacOS/X (Cocoa)
	and MacOS/X Server 1.0 (Rhapsody).  On MacOS/X, "Application
	Support/SokoSave" is appended to the result of
	NSSearchPathForDirectoriesInDomains().  In other cases, only "SokoSave"
	is appended.  For Windows, $(SokoUser) expands to the "personal" folder
	(typically "My Documents"), if it exists.  If not, then it expands to
	the first of the following which exist: $(HOME), $(TEMP), $(TMP), root
	of drive containing "windows" directory, or root of current drive.
    Renamed old SokoWindows.c to SokoApp-windows.c since this Windows-specific
	module is related to SokoApp.  (Also, this helps to disambiguate it
	from the new SokoWindow class and implementation file.)
    When registering file associations on Windows, now uses an appropriate
	description for each association, rather than the generic "SokoSave
	Document".  Added CustomInfo.plist which contains an appropriate
	description for each file extension.
    Added SokoWindow and SokoPanel, which are subclasses of NSWindow and
	NSPanel, respectively.  All windows and panels throughout the
	application are now instances of these classes.  This allows bugs in
	the AppKit window and panel classes to be overcome more easily.  For
	instance, the Windows port works around several Windows-specific AppKit
	bugs by overriding certain methods in these classes.
    Directional movement buttons on SokoBoard window are now connected to
	-directionPressed: and diagonalPressed:, rather than each being
	connected to a dedicated method.
    Renamed -[SokoBoard inspectPlaybackSlider:] to -inspectSlider:.
    Connected the "Animate" switch on SokoBoard to the new -[SokoBoard
	animateToggled:] method.
    Added the SokoURL class for use by the Info panel.  This class displays
	fly-over, clickable URLs.  On MacOS/X, it knows how to dispatch any URL
	understood by -[NSWorkspace openURL:].  On Windows, it knows how to
	dispatch any URL understood by ShellExecute().  On MacOS/X Server 1.0
	(Rhapsody), OpenStep/Mach, and NextStep, it knows how to dispatch
	mailto: URLs directly; all others are handed off to OmniWeb's "Open
	URL" service.
    Renamed "window" instance variable to "panel" for all classes and nibs in
	which a panel is actually used (everything but SokoBoard, in fact).
    On Windows, now ensures 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.  This is accomplished
	by catching the WM_SETTINGCHANGED message from Windows and adjusting
	the window frame as needed.
    Worked around an AppKit bug on Windows which appeared in this release when
	small versions of the icons were incorporated into the ICO files.  The
	AppKit failed to use these small icons in the window title bars.
	Instead, it used a scrunched version of the large icon, which was quite
	ugly.
    Worked around an AppKit bug on Windows in which the Preferences panel would
	suddenly appear on the "Window" menu when -setDocumentEdited: was
	invoked even though panels are not supposed to appear on this menu.
	This problem was further compounded by the fact that the menu item
	would remain dangling on the menu even after the Preferences panel was
	closed.
    Worked around an AppKit bug on Windows 9x which caused the window size of
	SokoBoard windows to become completely corrupt when miniaturized.  This
	bug only seems to affect non-resizeable windows (such as SokoBoard) and
	only occurs on Windows 9x.  (Windows NT and 2000 are not afflicted.)
    Renamed SokoSave_main.m to SokoSave.m.
    ---- NEXTSTEP -------------------------------------------------------------
    Rewrote the NextStep port so that it utilizes the new "sokocore" game
	library rather than implementing that logic directly.
    Now remembers username from New Score panel as default for that panel as a
	convenience to users rather than always seeding it with the username.
    Now remembers the directory from which a new game was loaded during a
	session, and seeds the New Game open panel with that location.  This
	makes it more convenient for the user to start new games from a
	directory other than the default New Game directory.  (It was very
	annoying for the program to revert to the factory directory each time
	New Game was invoked.)
    Added a "Help" menu item which opens the HTML help file in a web browser.
	Previously, the help information was contained in an RTFD file and
	loaded directly into a text object on the Info panel.
    Added SokoAlerter which provides a convenience function used by the new
	SokoPuzzleDelegate and SokoScoreDelegate implementations to send alert
	messages to the user from those core modules.
    Split new-score entry panel and functionality out of SokoScores and into
	its own module, SokoNewScore.
    Now positions MiscTableScroll's keyboard cursor at newly added row when a
	score is recorded.
    Changed MiscTableScroll on score panel to use lazy-mode rather than
	eager-mode since lazy-mode is more appropriate for use with the new
	common SokoScore object from the "sokocore" library.
    Added SokoWindow and SokoPanel which are subclasses of Window and Panel,
	respectively.  All windows and panels throughout the application are
	now instances of these classes.  Although these classes currently
	implement no extra functionality, they provide convenient hooks for the
	addition of new functionality in the future, if needed.
    Directional movement buttons on SokoBoard window are now connected to
	-directionPressed: and diagonalPressed:, rather than each being
	connected to a dedicated method.
    Renamed -[SokoBoard inspectPlaybackSlider:] to -inspectSlider:.
    Connected the "Animate" switch on SokoBoard to the new -[SokoBoard
	animateToggled:] method.
    Added the SokoURL class for use by the Info panel.  This class displays
	fly-over, clickable URLs.  It handles mailto: URLs directly; all others
	are handed off to OmniWeb's "Open URL" service.
    Renamed "window" instance variable to "panel" for all classes and nibs in
	which a panel is actually used (everything but SokoBoard, in fact).
    Renamed SokoScores "scroll" instance variable to "tableScroll".
    No longer unnecessarily links with the libMedia and libIndexing libraries.
    Renamed SokoSave_main.m to SokoSave.m.

    Changed Files:
    * BUGS.txt (now conglomeration of items from all ports)
    + cbuilder/ (C++Builder port repository)
    + cbuilder/clean.bat
    + cbuilder/SokoAlerter.{h|cpp}
    + cbuilder/SokoApp.{h|cpp|dfm}
    + cbuilder/SokoArrow{Down|DownLeft|DownRight}.bmp
    + cbuilder/SokoArrow{Left|LeftLeft}.bmp
    + cbuilder/SokoArrow{Right|RightRight}.bmp
    + cbuilder/SokoArrow{Up|UpLeft|UpRight}.bmp
    + cbuilder/SokoBoard.{h|cpp|dfm|rc}
    + cbuilder/Soko{Crate|CrateSafe|CrateSelected|CrateSafeSelected}.bmp
    + cbuilder/SokoDefaults.{h|cpp}
    + cbuilder/Soko{Empty|EmptySafe}.bmp
    + cbuilder/SokoForm.{h|cpp}
    + cbuilder/SokoGame.ico
    + cbuilder/SokoHelp.bmp
    + cbuilder/SokoHighScores.bmp
    + cbuilder/SokoInfo.{h|cpp|dfm|rc}
    + cbuilder/SokoNewGame.bmp
    + cbuilder/SokoNewScore.{h|cpp|dfm}
    + cbuilder/SokoNextPuzzle.bmp
    + cbuilder/SokoOpenGame.bmp
    + cbuilder/Soko{Player|PlayerSafe}.bmp
    + cbuilder/SokoPref.{h|cpp|dfm}
    + cbuilder/SokoPuzzle.ico
    + cbuilder/SokoRendezvous.{h|cpp}
    + cbuilder/SokoSaveGame.bmp
    + cbuilder/SokoSave.{cpp|bmp|bpr|ico|iss|rc}
    + cbuilder/SokoScores.{h|cpp|dfm}
    + cbuilder/SokoTrackBar.{h|cpp}
    + cbuilder/SokoURL.{h|cpp}
    + cbuilder/SokoWall.bmp
    + common/ ("sokocore" repository; common implementation files)
    + common/SokoAssert.h
    + common/SokoBuild.h
    + common/SokoCore.dep
    + common/SokoDefs.h
    + common/SokoEncode.{h|c} (relocated from OpenStep/NextStep ports.)
    + common/SokoFile.{h|c}   (extracted from SokoFile.m;  plus much new code)
    + common/SokoPool.{h|c}
    + common/SokoPuzzle.{h|c} (extracted from SokoBoard.m; plus much new code)
    + common/SokoRelease.h
    + common/SokoScore.{h|c}  (extracted from SokoScore.m; plus much new code)
    + common/SokoSetting.{h|c}
    + common/SokoUtil.{h|c}   (extracted from SokoUtil.m;  plus much new code)
    + common/SokoWrap.h
    * FILE_SYNTAX.txt
    + help/ (user documentation repository)
    + help/SokoHelp.html (converted from SokoHelp.rtfd; plus improvements)
    + help/images/SokoArrow{Left|LeftLeft|Right|RightRight}.gif
    + help/images/Soko{Crate|CrateSelected}.png
    + help/images/Soko{Empty|EmptySafe}.png
    + help/images/SokoExample{1|2|3}.png
    + help/images/SokoPlayer.png
    + help/images/SokoSave.png
    + help/images/SokoWall.png
    * HISTORY.txt (now conglomeration of items from all ports)
    > Maze/ --> puzzle/ (.sokomaze puzzle repository)
    + nextstep/ (NextStep port repository)
    * nextstep/Makefile
    + nextstep/Makefile.{preamble|postamble}
    * nextstep/PB.project
    + nextstep/SokoAlerter.{h|m}
    * nextstep/SokoApp.{h|m}
    * nextstep/SokoBoard.{h|m|nib}
    - nextstep/SokoDefs.h
    - nextstep/SokoEncode.{h|c}
    - nextstep/SokoFiles.{h|m}
    + nextstep/SokoGame.tiff
    + nextstep/SokoHand.tiff
    - nextstep/SokoHelp.rtfd
    * nextstep/SokoInfo.{h|m|nib}
    * nextstep/SokoMatrix.{h|m}
    + nextstep/SokoNewScore.{h|m}nib}
    * nextstep/SokoPref.{h|m|nib}
    + nextstep/SokoPuzzle.tiff
    * nextstep/SokoSave.{iconheader|nib}
    > nextstep/SokoSave_main.m --> SokoSave.m
    > nextstep/SokoScore.{h|m|nib} --> SokoScores.{h|m|nib}
    * nextstep/SokoScores.{h|m|nib}
    + nextstep/SokoURL.{h|m}
    + nextstep/SokoURL-nextstep.m
    - nextstep/SokoUtil.{h|m}
    + nextstep/SokoWindow.{h|m}
    + openstep/ (OpenStep port repository)
    + openstep/CustomInfo.plist
    * openstep/Makefile
    * openstep/Makefile.{preamble|postamble}
    * openstep/PB.project
    + openstep/SokoAlerter.{h|m}
    * openstep/SokoApp.{h|m}
    * openstep/SokoApp-windows.c
    * openstep/SokoBoard.{h|m|nib}
    * openstep/SokoConfig.h
    > openstep/SokoDefs.h --> openstep/SokoConfig.h
    - openstep/SokoEncode.{h|c}
    - openstep/SokoFiles.{h|m}
    + openstep/SokoGame.{ico|tiff}
    + openstep/SokoHand.tiff
    * openstep/SokoInfo.{h|m|nib}
    * openstep/SokoMatrix.{h|m}
    + openstep/SokoNewScore.{h|m|nib}
    * openstep/SokoPref.{h|m|nib}
    + openstep/SokoPref-{macintosh|openstep|rhapsody}.m
    + openstep/SokoPref-windows.c
    + openstep/SokoPuzzle.{ico|tiff}
    * openstep/SokoSave.{ico|iconheader|nib}
    * openstep/SokoSave-{macintosh|windows}.nib
    > openstep/SokoScore.{h|m|nib} --> SokoScores.{h|m|nib}
    * openstep/SokoScores.{h|m|nib}
    + openstep/SokoURL.{h|m}
    + openstep/SokoURL-{macintosh|openstep|rhapsody|windows}.m
    + openstep/SokoWindow.{h|m}
    + openstep/SokoWindow-windows.m
    - openstep/SokoWindows.h
    > openstep/SokoWindows.c --> SokoApp-windows.c
    - OPENSTEP-BUGS.txt    (merged into BUGS.txt)
    - OPENSTEP-HISTORY.txt (merged into HISTORY.txt)
    - OPENSTEP-TODO.txt    (merged into TODO.txt)
    * SCORES
    * TODO.txt (now conglomeration of items from all ports)
    * util/pack.sh
    * util/pack_binaries.sh
    * util/trim_scores.sh
    * util/unpack.sh
    * util/unpack_binaries.sh

*** RELEASE 2.3 ***
v14 2001-08-28 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Fixed a memory smashing bug.  +[SokoBoard preparePathFinding::] was not
	setting its `preallocated_area' variable in all cases.  This method is
	supposed to ensure that the shared flood-fill structures have
	sufficient capacity for the largest puzzle currently open, however this
	bug caused the structures to be reallocated for each puzzle opened.  If
	a small puzzle was opened while a larger puzzle was already opened, the
	smaller structures would replace the larger ones needed by the larger
	puzzle, with the result that flood-fill operations for the larger
	puzzle would clobber memory.  A secondary side-effect of this bug was
	that the flood-fill structures were leaked each time a new puzzle was
	opened.
    Merged new 12- and 24-bit selected-crate images from Paul into
	SokoCrateSelected.tiff and SokoCrateSafeSelected.tiff.  Paul used a
	slightly different shade of yellow for the highlighting than did I for
	the original images.
    ---- OPENSTEP -------------------------------------------------------------
    Fixed bug: -[SokoBoard makeMatrix] was leaking the 'protoCell'.
    Fixed bug: SokoFiles' expand_macro() was leaking a mutable copy of the
	`alphanmericCharacterSet'.
    Added a new Makefile.preamble to overcome a problem which is common on
	Microsoft Windows.  If the HOME environment variable contains any
	backslashes, the Apple/NeXT makefiles will crash.  To fix this, the the
	backslashes are translated to forward slashes.
    Added a warning to README_ABOUT_SOURCE_CODE and README_ABOUT_RCS regarding
	the negative impact of spaces in pathnames on the Apple/NeXT makefiles.

    Changed Files:
    * Makefile
    + Makefile.preamble (OpenStep)
    * PB.project
    * README
    * README_ABOUT_RCS
    * README_ABOUT_SOURCE_CODE
    * README_MACOSXS
    * README_OPENSTEP
    * RELEASE_NUMBER
    * SokoBoard.m
    * SokoCrateSelected.tiff
    * SokoCrateSafeSelected.tiff
    * SokoFiles.m
    * SokoHelp.rtfd

*** RELEASE 2.2 ***
v13 2001-08-21 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Fixed springiness on "Animate" and "Stop" controls on SokoBoard window.
	This got botched when I swapped the position of these two controls at
	the last minute in v11.

    Changed Files:
    * README
    * README_ABOUT_RCS
    * README_ABOUT_SOURCE_CODE
    * README_MACOSXS
    * README_OPENSTEP
    * RELEASE_NUMBER
    * SokoBoard.nib

*** RELEASE 2.1 ***
v12 2001-08-20 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Pressing Escape during normal game-play now deselects the selected crate.
	(As of v11, Escape also aborts an active history playback session.).
    Fixed bug: -[SokoBoard preparePathFinding::] declared variable
	`preallocated_area' without a type (which defaulted to `int').
    SokoHelp.rtfd now explains how to deselect a crate.
    SokoHelp.rtfd now mentions that arrow keys on keyboard may be used to move
	player.
    ---- OPENSTEP -------------------------------------------------------------
    Now compiles cleanly on MacOS/X (though I do not yet have a project file or
	main-menu nib for MacOS/X).  Clean compilation on MacOS/X required
	importing several additional headers into SokoBoard.m, SokoInfo.m, and
	SokoScore.m.  Also, had to work around problem caused by change in
	prototype of -applicationShouldTerminate: between MacOS/X Server 1.0
	and MacOS/X.  Instead, SokoApp.m now implements
	-applicationWillTerminate: which has the same prototype on both
	platforms.

    Changed Files:
    * README
    * README_ABOUT_RCS
    * README_ABOUT_SOURCE_CODE
    * README_MACOSXS
    * README_OPENSTEP
    * RELEASE_NUMBER
    * SokoApp.m
    * SokoBoard.m
    * SokoHelp.rtfd
    * SokoInfo.m
    * SokoScore.m

*** RELEASE 2.0 ***
v11 2001-08-19 sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Merged in a bunch of new scores from Paul's and Eric's recent games.
    Converted from Objective-C++ to pure Objective-C.  Changed file extensions
	from .M to .m, and .cc to .c.  This change makes it easier to support
	both GNUstep and MacOS/X, neither of which feature an Objective-C++
	compiler (though MacOS/X will reportedly support Objective-C++ at some
	point in the future).
    Renamed the following functions in order to avoid potential symbolic
	collisions in the target environment:
	    collapse --> soko_collapse
	    directoryPart --> soko_directory_part
	    expand --> soko_expand
	    filenamePart --> soko_filename_part
	    getFactoryScoresFile --> soko_get_factory_scores_file
	    getMazeDirectory --> soko_get_maze_directory
	    getMazeExtension --> soko_get_maze_extension
	    getSaveDirectory --> soko_get_save_directory
	    getSaveExtension --> soko_get_save_extension
	    getScoresFile --> soko_get_scores_file
	    mazeNameForLevel --> soko_maze_name_for_level
	    mkdirs --> soko_mkdirs
	    runLengthDecodeChar --> soko_run_length_decode_char
	    runLengthDecodeString --> soko_run_length_decode_string
	    runLengthEncodeChar --> soko_run_length_encode_char
	    runLengthEncodeString --> soko_run_length_encode_string
	    saveFileNameForMazeName --> soko_save_filename_for_maze_name
    Implemented "smart" undo/redo-push.  Undo-push behaves as follows.  If the
	last action was a move, then that move is undone along with all other
	moves until a push action is encountered, which is not undone.  If the
	last action was a push, then that push is undone along with all other
	pushes in the same direction until either a move or a push in a
	different direction is encountered.  Redo-push behaves in a
	symmetrically complementary fashion.
    Added undo/redo-push buttons to SokoBoard.nib.  These buttons display
	double-arrow left and right images which were added to the project.
    Renamed "Redo" and "Undo" menu items to "Redo Move" and "Undo Move".
    Added "Redo Push" and "Undo Push" menu items.
    Added a "History" submenu and moved the undo/redo items there from "Edit".
    Renamed Sokoboard's -redoPressed: and -undoPressed: to -redoMove: and
	-undoMove: respectively.
    Eliminated SokoBoard's -redo: and -undo: methods.  The "Redo Move" and
	"Undo Move" menu items are now connected directly to -redoMove: and
	-undoMove:, instead of going indirectly through -redo: and -undo:.  As
	a side-effect, this also fixes the problem on MacOS/X Server 1.0
	(Rhapsody/YellowBox) where NSWindow's new undocumented -undo: and
	-redo: methods prevented these methods from ever reaching SokoBoard.
    Added -redoPush: and -undoPush: to SokoBoard.
    SokoBoard's -appendMoveToHistory:isPush: no longer calls realloc() with a
	null pointer.  Although calling realloc() with a null pointer is
	documented as being acceptable, doing so results in a crash on some
	platforms.  Instead, now uses malloc() for this special case.
    Eliminated the ellipses "..." from the "Info Panel" ("About SokoSave") and
	"Scores" menu items since, although these items launch panels, they do
	not require any additional user input.
    Renamed the SokoBoard instance variables NUMROWS and NUMCOLS to numRows
	and numCols, respectively.
    Added a "Soko" prefix to the filenames of all image.
    Ditched the "Large" prefix from the "arrow" image filenames.  So, for
	instance, LargeArrowRight.tiff became SokoArrowRight.tiff.
    Changed the title of the Info panel from "Info" to "SokoSave Info" so that
	it is more meaningful when miniaturized.
    Changed the title of the Scores panel from "Scores" to "SokoSave Scores" so
	that it is more meaningful when miniaturized.
    Now sets the miniwindow icon for the Scores panel.
    Renamed SokoBoard's history_max, history_len, and history_pos to
	historyMax, historyLen, and historyPos, respectively, in order to match
	naming convention of other instance variables.
    The static `checked' variable in SokoApp.m is now an instance variable of
	the SokoApp class and has been renamed to `autoOpenMaze'.
    Changed the behavior of -[SokoBoard pushCrateTo::] slightly.  This method
	is triggered when the user right-clicks on an empty cell in order to
	push an intervening crate onto that cell.  The old behavior
	unconditionally assumed that the player was always pushing a crate even
	if there was no crate between the player and the destination cell.  The
	result was that the player would unconditionally stop moving one cell
	shy of the destination.  With the new behavior, the player moves onto
	the destination cell if no crate is being pushed.  If a crate is being
	pushed, then the player stops one cell shy of the destination as usual
	(since the crate winds up in the destination cell).
    Added a "Stop" button to the history playback control box on the SokoBoard
	window.  The Stop button can be used to abort any lengthy playback
	triggered by either the playback slider or the undo/redo-push
	mechanism.  A pseudo-modal session runs during playback which polls the
	event queue and dispatches certain events, thus allowing the Stop
	button to remain active.  Keyboard events are also monitored, and the
	Escape key is recognized as an alternate playback abort command.  As a
	nice side-effect of running this pseudo-modal session, the "busy" mouse
	cursor is no longer triggered during lengthy playbacks.
    Added a new player movement mechanism.  The player can now be dragged with
	the mouse.  If the mouse is dragged to an empty cell, then the player
	is moved to that cell via the shortest path.  However, if the player is
	adjacent to a crate and the mouse is dragged atop the crate, then the
	player pushes the crate.  This behavior seems to have a very intuitive
	feel.
    Augmented the existing point-and-click player movement so that, in addition
	to the player moving to the destination cell, the user may then drag
	the mouse from that point and the player will follow.
    Added a new automated point-and-click crate movement mechanism which is
	quite similar to the existing point-and-click player movement
	mechanism.  However, the constraints are more severe and the actual
	implementation is considerably more complex.  To invoke this mode, the
	user clicks on the crate which she wants moved.  The crate is then
	highlighted on-screen, and is considered the "selected crate".  Next,
	the user clicks on the desired destination cell and the player
	automatically pushes the crate to the destination cell by the shortest
	path possible, if such a path exists.  The constraints on automated
	crate movement are more severe because, not only must the player be
	able to reach the crate, but the player must also be able to push the
	crate to each intermediate position along the chosen path.  Stated
	specifically, in order for a push in a particular direction to be
	valid, the player must be able to reach the appropriate edge of the
	crate, and the cell on the far side of the crate must be empty.  As an
	extra benefit, the actual implementation also satisfies the secondary
	goal of minimizing the overall number of moves required to satisfy the
	primary goal of minimizing the number of pushes required to move the
	crate to its destination.  Minimizing the number of moves as a
	secondary goal added a fair amount of complexity to the
	shortest-crate-path algorithm, but I think that it was worth the
	effort.  After selecting a crate, if the user decides that she does not
	want to move that crate after all, it can be deseletected by clicking
	on it a second time, clicking on a different crate, clicking on some
	invalid or unreachable cell, or by employing some other movement or
	history playback mechanism.  Finally, the crate selection algorithm is
	smart enough to only allow selection of crates by the user which are
	both reachable and pushable by the player.  In other words, a path from
	the player to at least one edge of the crate must exist, and the cell
	on the far side of an accessible edge must be empty.  If these
	constraints are not met, then the crate is not movable, and can not,
	therefore, be selected.
    Added a new crate movement mechanism.  Crates can now be dragged with the
	mouse.  Unlike player dragging, crate dragging is more severely
	constrained since the player must be able to reach the crate, and an
	appropriate path must exist from the crate to the destination cell.
	Crate dragging is built atop the same machinery used by point-and-click
	crate movement (as described above), so it is subject to all of the
	same constraints and benefits (such as minimized pushes and moves).
	The only difference is that, from the user's perspective, dragging
	seems to be a continuous operation, whereas the point-and-click
	mechanism seems entirely discreet.
    Augmented the "quick push crate" mechanism, which is normally invoked with
	the secondary mouse button, so that it can now be invoked with the
	primary mouse button when any of the keyboard modifiers shift, control,
	alternate, or command are held down.  This provides a way for
	single-button mice, such as those on the Macintosh, to trigger this
	movement mechanism, as well.
    Added a copious amount of source code documentation to SokoBoard.m to
	explain the new automated movement mechanisms and various special cases
	or behavior associated with them.
    Eliminated the movement mechanism triggered by clicking on a crate while
	the player was adjacent would push the crate _and_ the mouse pointer
	simultaneously.
    Changed text fields on SokoBoard and New Score windows so that they are
	drawn with simple outline borders rather than bezels.  The outline
	style looks nicer across a wider range of platforms and user interfaces
	such as in Cocoa and YellowBox.  This way, these fields will more
	closely resemble the ones in those other ports.  The history playback
	control box on the SokoBoard window now stretches to fill window width
	if necessary.
    Renamed nib outlet `solvedLabel' to `solvedFld' in SokoBoard to conform to
	other outlet names which employ the "Fld" suffix.
    Renamed SokoBoard's global `openBoards' variable to `OPEN_BOARDS'.
    Eliminated the hard-coded maximum puzzle dimensions from SokoBoard.  These
	dimensions were hard-coded into, not only the puzzle grid, but all of
	the data structures used for path-finding and load-time puzzle
	validation.  All such data structures are now sized dynamically, thus
	allowing puzzles of any size.  Also updated FILE_SYNTAX.txt so that it
	no longer mentions these, now obsolete, constraints.
    Added SokoHelp.rtfd which contains the user documentation which used to
	reside directly within the SokoInfo.nib.  This documentation is now
	loaded into the text section of the SokoInfo.nib from SokoHelp.rtfd at
	run-time.
    Updated SokoHelp.rtfd to reflect all of the changes and new features for
	this version.
    Augmented the "Moving Around" section in the help file to describe the new
	"Dragging Player" movement mechanism.  Also expanded the discussion of
	the other existing player movement mechanisms.
    Greatly expanded the "Pushing Crates" section in the help file to describe
	the four new automate crate movement mechanisms, "Quick Push via
	Keyboard Modifier", "Dragging Player", "Dragging Crate", and
	"Point-and-Click".  Also added a new "selected crate" image to the game
	element legend in the "Objective" section.  The selected crate is
	employed by the point-and-click crate pushing mechanism.
    Significantly expanded the "Playback" section of the help file.  Now
	describes new undo/redo-push mechanism.  Added a graphic legend for the
	various undo/redo buttons.  Expanded the discussion of the playback
	slider.  Now discusses the "Animate" switch, as well as the new Stop
	button and cancellation of playback via Escape.  Added discussion of
	automated intelligent undo/redo based upon comparison of current move
	with most recent move.
    Greatly expanded the "Scoring" section of the help file.  Now contains
	illustrated examples explaining how the goals of minimizing moves
	and minimizing pushes differ.  Also added explanation of how the
	various automated movement mechanisms impact scoring.
    Updated Paul's email address, throughout, since the old one is no longer
	valid.
    Added an alpha channel to all button images which were lacking it in order
	to ensure that they display more attractively on highlighted button
	faces.  (Some of the images already had an alpha channel, though most
	did not.)
    The static DIRTY, SAVE_ORDER, and SAVE_SIZES flags from SokoScore.m are
	now instance variables of the SokoScore class.  Their names are now
	dirty, saveOrder, and saveSizes, respectively.
    SokoMatrix now implements -acceptsFirstMouse.
    Added an unpack_binaries.sh script to complement the existing
	pack_binaries.sh script.
    Fixed a bug in unpack.sh where it failed to set the permissions of the
	extracted files.
    Added a README_ABOUT_RCS document.
    ---- OPENSTEP -------------------------------------------------------------
    Ported to MacOS/X Server 1.0 for Mach (Rhapsody) and Windows (YellowBox).
	Also did all preliminary work for MacOS/X port.  Presumably all that is
	needed to complete MacOS/X support is for someone to create a project
	file with the new ProjectBuilder, and to create a MacOX/X-specific main
	menu nib file.  (I do not currently have access to MacOS/X, so I can
	not perform these tasks.)
    Added platform.make and make.sh from ProjectUnity 2.0.  These resources
	allow the project to build successfully on MacOS/X Server and OpenStep
	(Mach and Windows) without having to maintain multiple PB.project and
	Makefile resources.  Also merged forceload.fix from ProjectUnity into
	Makefile.postamble.
    Since C++ and Objective-C++ were dropped, eliminated special C++ and
	Objective-C++ goop from Makefile.preamble and Makefile.postamble which
	worked around blunders in the Apple/NeXT makefiles.  Since
	Makefile.preamble was empty after this change, eliminated it
	altogether.
    Updated all nibs to latest UI layout guidelines as specified by the MacOS/X
	Server 1.0 documentation.  Adjusted all fonts to respect user settings
	rather than assuming fixed font selection.
    SokoInfo now translates spaces in displayed numbers to dots, thus the
	package number now displays as "10.1" rather than "10 1".
    SokoScore now provides an NSTableView category which overrides
	-acceptsFirstMouse: to return YES unconditionally.  This is more
	user-friendly behavior.
    On Windows, file associations for the .sokomaze and .sokosave extensions
	are programmatically added to the registry if absent or incorrect.
	This allows users to double-click on these files and have SokoSave
	automatically launched as a result.
    Now disables drawing of dotted rectangle around key-cell in SokoMatrix.
    Now ensures that other controls on SokoBoard window don't steal keyboard
	focus away from SokoMatrix.  Previously, other controls would steal
	focus, which prevented keyboard from being used to move player.
    Added tool-tips to controls on SokoBoard window.
    Now sets the miniwindow icon for the SokoInfo panel.
    ---- NEXTSTEP -------------------------------------------------------------
    Eliminated the unneeded Makefile.preamble and Makefile.postamble.
    Upgraded formatting of source and header files which I had not updated in
	the last version.  Added explicit (id) in several places which had not
	previously been updated.
    Renamed the following functions in order to avoid potential symbolic
	collisions in the target environment:
	    basename --> soko_basename
	    ends_with --> soko_ends_with
	    load_nib --> soko_load_nib
	    starts_with --> soko_starts_with
	    strdup --> soko_strdup
    Eliminated unnecessary inclusion of <assert.h> from SokoScore.m.
    Fixed bugs: All MiscTableScroll delegate methods in SokoScore failed to
	return a value even though they were declared as doing so.
    Renamed SokoUtil.c to SokoUtil.m since it employs Objective-C in its
	soko_load_nib() function.
    Removed the unneeded NextStep help files.
    Moved the "Print" menu item to the spot between "Windows" and "Services"
	for consistency with other NextStep applications.
    Added a "miniaturize" button to the Info panel.  Also now sets the
	miniwindow icon for this panel.
    Eliminated all inclusions of <appkit/appkit.h> throughout the project;
	replaced with inclusion of individual header files.
    Nib objects are now referenced by explicit types in class interfaces rather
	than by generic (id).
    Replaced uses of MAXPATHLEN with FILENAME_MAX from <stdio.h> so that
	FILENAME_MAX is now used consistently throughout the project instead of
	having a mixture of the two.
    The static `LAUNCHED_WITH_FILE' variable in SokoApp.m has been removed.
	Its function is now handled by checking if the SokoBoard class has any
	open mazes.
    Implemented menu item validation machinery.  All menu items are now enabled
	and disabled as appropriate.  The core machinery is implemented by
	SokoApp.  SokoBoard implements validation logic for menu items which
	are associated with the board's state.
    README_ABOUT_SOURCE_CODE now explains how to obtain MiscTableScroll, which
	is needed to build the NextStep version of SokoSave.
    Updated control layouts on windows to match those in MacOS/X Server version
	since MacOS/X Server controls tend to require more real-estate.

    Changed Files:
    * FILE_SYNTAX.txt
    - Help
    > LargeArrow*.tiff --> SokoArrow*.tiff
    + make.sh
    * Makefile
    * Makefile.postamble (OpenStep)
    - Makefile.{preamble|postamble} (NextStep)
    * PB.project
    + platform.mak
    * README
    + README_ABOUT_RCS
    * README_ABOUT_SOURCE_CODE
    * README_MACOSXS
    * README_OPENSTEP
    > README_RHAPSODY --> README_MACOSXS
    * RELEASE_NUMBER
    * SCORES
    * SokoApp.{h|m}
    * SokoArrow*.tiff (added alpha channel)
    + SokoArrowLeftLeft.tiff
    + SokoArrowRightRight.tiff
    * SokoBoard.{h|m|nib}
    + SokoCrateSelected.tiff
    + SokoCrateSafeSelected.tiff
    * SokoDefs.h
    * SokoEncode.{h|c}
    * SokoFiles.{h|m}
    + SokoHelp.rtfd
    * SokoInfo.{h|m|nib}
    * SokoMatrix.{h|m}
    - SokoMouse.{h|m}
    * SokoPref.{h|m|nib}
    * SokoSave.nib
    * SokoSave-mactintosh.nib
    * SokoSave-windows.nib
    * SokoSave_main.m
    * SokoScore.{h|m|nib}
    + SokoWindows.{h|c}
    * SokoUtil.{h|m}
    + unpack_binaries.sh
    > *.cc --> *.c
    > *.M --> *.m
    > *.tiff --> Soko*.tiff

*** RELEASE 1.1 ***
v10 1997-12-10 06:40 EST sunshine@sunshineco.com
    ---- GENERAL --------------------------------------------------------------
    Fixed wording in info panel: "brings up panel" --> "brings up a panel".
    Added "Feedback" section to info panel.
    Fixed wording on main menu: "Games" --> "Game".
    Fixed bug: "Save As..." menu item was malformatted as "SaveAs...".
    Fixed bug: +[SokoBoard nextMaze] was neglecting to call -makeKeyWindow:
	after opening the maze on behalf of SokoApp.
    Fixed bug: "New Score" panel allowed resizing in both dimensions even
	though it only makes sense to resize horizontally.
    Fixed bug: When opening a saved game with a deferred game window, the
	NSSlider/Slider didn't get drawn.  SokoBoard was incorrectly and
	unnecessarily calling -sizeToFit on the slider.  For some reason on
	deferred windows this has the side-effect of setting the slider's frame
	size to (0,0).
    Fixed bug: New and Open panels failed to restrict allowed types to
	.sokomaze and .sokosave, respectively.  The problem was that they were
	using the inherited -setRequiredFileType: method which seems to be
	ineffectual in NSOpenPanel/OpenPanel.  They now specify the types
	explicitly via -runModalForDirectory:file:types:.
    Fixed bug: Opening a saved game with no history resulted in a "corrupt
	moves/pushes" error message.  The problem was that an earlier fscanf()
	format string was eating the blank line which represented the empty
	history in the save-file.
    Fixed bug: Opening a saved game with no history called malloc(0).
    Fixed bug: Opening a saved game could report "corrupt recorded values" in
	the following case: 1) solve and save game, 2) undo two or more
	times, 3) make a move which is *not* in the history, 4) save game, 5)
	close game, 6) re-open game.  The problem was that at step 3, the
	history was truncated.  Yet the load function was asserting that the
	"recorded" moves & pushes were less than the history-length; but after
	the truncation, this assertion was no longer valid.
    The preference panel now has a field to allow resetting the Level.
    The Cancel button on the preference panel now reverts the fields to their
	saved values.
    The Okay button on the preference panel now dismisses the panel.
    The preference panel now gets marked dirty when edits are made and prompts
	the user if dirty and the window's close button is pressed.
    Added option to preference panel to allow user to toggle automatic saving
	of game when it's solved.
    Preferences panel now saves its on-screen position.
    Unified the color depth of all the LargeArrow tiffs.  Gave them all
	transparency rather than having opaque light-gray backgrounds so that
	they look correct on all platforms.  (Not all platforms use light-gray
	as the background for the button.)  Also they look better this way
	when disabled.
    Removed an unnecesary #include <assert.h> from SokoEncode.cc.
    The README files are now included in the application wrapper.
    Folded in Paul's new SCORES file.
    ---- OPENSTEP -------------------------------------------------------------
    Ported to OpenStep 4.1 & 4.2 for Mach, OpenStep 4.2 for NT, and Rhapsody
	Developer Release (RDR) for Mach and NT.
    Added a Rhapsody-specific main menu.
    Added a Windows-specific main menu.
    Under Windows, the automatic launching of the "default" maze is no longer
	deferred.  This was incompatible with the Windows UI where an
	application must have at least one window on-screen on account of the
	fact that the main menu is attached to the window rather than stand-
	alone.  The automatic launch is still deferred on the other platforms.
    Under Windows, had to account for failure to load the "default" maze
	since this would leave the application dangling without a window
	on-screen.  Now, if the "default" maze fails to load, then it tries
	loading maze #1.  If that fails, then it presents the user with an
	open panel from which they can choose a new game or a saved game.  If
	the user aborts the open panel, or if the chosen game fails to load,
	then the application terminates.
    Under Windows, PSadjustcursor() had no effect.  This is used by the
	click-crate-to-move feature to move the mouse pointer along with the
	crate.  Apparently PSadjustcursor() is a no-op under Windows.  Ended
	up having to make native Windows calls in order to emulate this
	behavior.  Unfortunately the Objective-C++ compiler can *not* import
	Windows header files without barfing up hundreds of errors, so I had
	to move the mouse-positioning code into its own Objective-C file,
	SokoMouse.m.
    Under Windows, the Scores panel incorrectly contained an application menu.
    Under Windows, the information panel was not displaying the application
	icon.  I fixed this by explicitly using the name "SokoSave" for the
	image rather than "NSApplicationIcon".
    Under Windows, SokoFile's mkdirs() couldn't properly handle Universal
	Naming Convention (UNC) paths (of the form \\machine\sunshine).
	Had to rewrite it to visit the directories bottom-up rather than
	top-down.
    SokoBoard now implements -validateMenuItem: to properly enable and disable
	the Undo, Redo, and Save menu items.
    SokoApp now implements -validateMenuItem: to properly enable and disable
	the Save All menu item.
    Worked around OpenStep 4.1 & 4.2 makefile bugs.  SRCFILES didn't include
	any of the C++ sources.  OFILES didn't include any of the C++ object
	files.
    ---- NEXTSTEP -------------------------------------------------------------
    Fixed bug: SokoBoard was freeing the shared Save Panel.
    Removed the "Insert Entry Here" items from the NextStep Help index.

    Changed Files:
    * LargeArrow{Down|Left|Right|Up}.tiff
    * LargeArrowDown{Left|Right}.tiff
    * LargeArrowUp{Left|Right}.tiff
    * Makefile
    * Makefile.{preamble|postamble}
    * pack.sh
    * PB.project
    * README
    * README_ABOUT_SOURCE_CODE
    + README_{OPENSTEP|RHAPSODY}
    * SCORES
    * SokoApp.{h|M}
    * SokoBoard.{h|M|nib}
    * SokoDefs.h
    * SokoEncode.cc
    * SokoFiles.{h|M}
    * SokoInfo.{h|M|nib}
    * SokoMatrix.{h|M}
    + SokoMouse.{h|m} (yes 'm', not 'M')
    * SokoPref.{h|M|nib}
    + SokoSave.ico
    * SokoSave.nib
    + SokoSave-{macintosh|windows}.nib
    > SokoSave_main.M --> SokoSave_main.m
    * SokoSave_main.m
    * SokoScore.{h|M|nib}

*** RELEASE 1.0 ***
v9 1997-11-13 03:09:40 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    Grabbed virgin makefiles.
    New default save directory: ~/Library/SokoSave
    Fixed bug: Table scroll was not resized when a new entry was added.

    Changed Files:
    * Makefile.{preamble|postamble}
    * SokoBoard.M
    * SokoDefs.h
    * SokoFiles.{h|M}
    * SokoInfo.nib
    * SokoScore.M
    + trim_scores.sh

v8 1997-11-04 01:28:15 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    Suppresses "next" maze when launched with a file.
    Reset save file version to "1".
    Added keyboard interface.
    Shuffled order of images in some tiff files so that they all print with the
	monochrome versions.  Apparently, Previewer.app, or whatever software
	is involved in the pipeline was choosing the first image in the file,
	instead of using the standard rules to choose the best image.

    Changed Files:
    * FILE_SYNTAX.txt
    * SokoApp.M
    * SokoBoard.{h|M|nib}
    * SokoMatrix.M
    * CrateSafe.tiff
    * Player.tiff
    - Lightning.tiff

v7 1997-11-03 00:41:14 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    Made SCORE file parsing and user-input handling more robust.  No longer
	screws up the file if the user enters spaces, tabs, newlines in the
	name and notes fields on the new score panel.
    Fixed springiness and minimum size on NewScore panel.
    Reduced minimum size on Scores window.
    Now saves/restores table scroll defaults.
    Now writes the SCORES file in sorted order.
    Made the Moves and Pushes columns right-aligned.
    Added a small border around the table scroll.
    Implemented printing for info, boards and scores.

    Changed Files:
    * SokoBoard.M
    * SokoInfo.{h|M|nib}
    * SokoSave.nib
    * SokoScore.{M|nib}
    * FILE_SYNTAX.txt

v6 1997-11-02 17:31:24 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    New SCORES file layout.
    Now uses table-scroll.  This also fixes bug with old scores file compaction
	code.  Scores are no longer automatically trimmed.
    Plugged memory leak in -[SokoBoard free].
    Fixed bug: "Save As..." when the history was empty used to crash.

    Changed Files:
    * Makefile
    * PB.project
    * SokoBoard.M
    * SokoEncode.cc
    * SokoFiles.{h|M}
    * SokoScore.{h|M|nib}

v5 1997-11-02 00:11:31 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    Implemented open-file stuff.
    Now catches power-off to save defaults when user logs out while app is
	running.
    Consolidated the code for the diagonal movement.
    Updated copyright notices: *.[chmM]*
    Switching to Objective-C++... *.m --> *.M  *.c --> *.cc
    Now stores compressed maze in save file.
    Now uses collapsed filenames with save files.

    Changed Files:
    * SokoApp.{h|M}
    * SokoBoard.{h|M}
    * SokoFiles.{h|cc}
    * SokoUtil.{h|cc}

v4 1997-10-29 12:51:20 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    Touched up the info nib a little.
    Implemented work-around for the AppKit window positioning bug.

    Changed Files:
    + FILE_SYNTAX.txt
    * Makefile
    * PB.project
    * SokoBoard.{h|m}
    * SokoInfo.{m|nib}
    > SokoUtil.c --> SokoUtil.cc
    * SokoUtil.{h|cc}

v3 1997-10-29 03:15:19 EST zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    More scores.
    Documented right mouse button.
    Added standard NeXT help.
    Displays the version on the info panel.

    Changed Files:
    - English.lproj/SokoSave.nib
    * Save/SCORES
    * SokoInfo.{h|m|nib}
    + SokoMerge.cc

v2 1997-10-28 23:27:49 EST zarnuk@high-speed-software.com
    Changed Files:
    * Makefile
    * PB.project

v1 1994-03-22 zarnuk@high-speed-software.com
    Changed Files:
    * SokoApp.{h|m}
    * SokoBoard.{h|m}
    * SokoEncode.{h|c}
    * SokoFiles.m
    * SokoInfo.{h|m}
    * SokoMatrix.h
    * SokoPref.{h|m}
    * SokoPref.m
    * SokoScore.{h|m}
    * SokoUtil.c

v0 1994-03-12 zarnuk@high-speed-software.com
    ---- NEXTSTEP -------------------------------------------------------------
    Created.  First version; NextStep-only.
