From f7adc8384e164b82ec6a099431afaff7eb1d5183 Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Tue, 12 May 2009 13:18:50 +0700 Subject: [PATCH] Initial commit on github to give this project a somewhat more 'permanent' home Signed-off-by: Gwenhael Le Moine --- INSTALL | 54 ++++ emstar-levels/emstar-lvl.1 | 9 + emstar-levels/emstar-lvl.10 | 9 + emstar-levels/emstar-lvl.11 | 9 + emstar-levels/emstar-lvl.12 | 9 + emstar-levels/emstar-lvl.13 | 9 + emstar-levels/emstar-lvl.14 | 9 + emstar-levels/emstar-lvl.15 | 9 + emstar-levels/emstar-lvl.16 | 9 + emstar-levels/emstar-lvl.17 | 9 + emstar-levels/emstar-lvl.18 | 9 + emstar-levels/emstar-lvl.19 | 9 + emstar-levels/emstar-lvl.2 | 9 + emstar-levels/emstar-lvl.20 | 9 + emstar-levels/emstar-lvl.21 | 9 + emstar-levels/emstar-lvl.22 | 9 + emstar-levels/emstar-lvl.23 | 9 + emstar-levels/emstar-lvl.24 | 9 + emstar-levels/emstar-lvl.25 | 9 + emstar-levels/emstar-lvl.3 | 9 + emstar-levels/emstar-lvl.4 | 9 + emstar-levels/emstar-lvl.5 | 9 + emstar-levels/emstar-lvl.6 | 9 + emstar-levels/emstar-lvl.7 | 9 + emstar-levels/emstar-lvl.8 | 9 + emstar-levels/emstar-lvl.9 | 9 + emstar.el | 556 ++++++++++++++++++++++++++++++++++++ 27 files changed, 835 insertions(+) create mode 100644 INSTALL create mode 100644 emstar-levels/emstar-lvl.1 create mode 100644 emstar-levels/emstar-lvl.10 create mode 100644 emstar-levels/emstar-lvl.11 create mode 100644 emstar-levels/emstar-lvl.12 create mode 100644 emstar-levels/emstar-lvl.13 create mode 100644 emstar-levels/emstar-lvl.14 create mode 100644 emstar-levels/emstar-lvl.15 create mode 100644 emstar-levels/emstar-lvl.16 create mode 100644 emstar-levels/emstar-lvl.17 create mode 100644 emstar-levels/emstar-lvl.18 create mode 100644 emstar-levels/emstar-lvl.19 create mode 100644 emstar-levels/emstar-lvl.2 create mode 100644 emstar-levels/emstar-lvl.20 create mode 100644 emstar-levels/emstar-lvl.21 create mode 100644 emstar-levels/emstar-lvl.22 create mode 100644 emstar-levels/emstar-lvl.23 create mode 100644 emstar-levels/emstar-lvl.24 create mode 100644 emstar-levels/emstar-lvl.25 create mode 100644 emstar-levels/emstar-lvl.3 create mode 100644 emstar-levels/emstar-lvl.4 create mode 100644 emstar-levels/emstar-lvl.5 create mode 100644 emstar-levels/emstar-lvl.6 create mode 100644 emstar-levels/emstar-lvl.7 create mode 100644 emstar-levels/emstar-lvl.8 create mode 100644 emstar-levels/emstar-lvl.9 create mode 100644 emstar.el diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..1e6065b --- /dev/null +++ b/INSTALL @@ -0,0 +1,54 @@ +====================================================================== + INSTALLATION NOTES FOR EMACS EMSTAR + 2008, Gwenhael Le Moine +====================================================================== + +Copy `emstar.el' anywhere you like, best in a directory, which is in +the default load-path of your emacs. + +Copy the directory `emstar-levels' and it's content anywhere you +like, the default configuration of Emacs Emstar expects it in +/usr/local/share/ + +Add the following lines to your .emacs file: + +(autoload 'emstar "emstar.el" + "Start a new game of Emstar." t) +(autoload 'emstar-mode "emstar.el" + "Play Emstar in current buffer." t) + +If you put `emstar.el' in a place which is not in your load-path you +have to write the full path like "/path/to/emstar.el" instead of +"emstar.el". + +If you put the emstar-levels in a other directory than +/usr/local/share you must configure `emstar-levels-dir' in your +.emacs to point to the proper place: + +(setq emstar-levels-dir "/path/to/emstar-levels") + +This can also be set using emacs customize feature. + + +Player files +============ + +By default Emacs Emstar saves player-files to /tmp. These files hold +the best results for each player and the last level each player finished. + +If you want your player files to be put in another place set the value +of `emstar-playerfiles-dir' appropriate, either in your .emacs file +with: + +(setq emstar-playerfiles-dir "/path/to/emstar-playerfiles") + +or using the emacs customize feature. + +IMPORTANT NOTE: The directory holding the playerfiles must be +writeable for all players of Emacs Emstar. So it should be a +dedicated directory with access permissions set to 1777 on *nix +systems. + +You can turn of writing of playerfiles by setting +`emstar-playerfiles-dir' to nil, but this will disable some features, +such as best players listing. diff --git a/emstar-levels/emstar-lvl.1 b/emstar-levels/emstar-lvl.1 new file mode 100644 index 0000000..73f5850 --- /dev/null +++ b/emstar-levels/emstar-lvl.1 @@ -0,0 +1,9 @@ +################ +#@## *#H# +# * ### +# ##* # +# ## * ## +## * * * # +# * *## * # +# ##* *# +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.10 b/emstar-levels/emstar-lvl.10 new file mode 100644 index 0000000..9bff5ed --- /dev/null +++ b/emstar-levels/emstar-lvl.10 @@ -0,0 +1,9 @@ + ########### +#### * # +# H ###* *# *# +# * #* #* # +# # * # *# +#*#* # *# #@# + #* ### ### +# # # # + ######### # # \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.11 b/emstar-levels/emstar-lvl.11 new file mode 100644 index 0000000..983a909 --- /dev/null +++ b/emstar-levels/emstar-lvl.11 @@ -0,0 +1,9 @@ +################ +# # @# +# #** ** ## +## * ## *# +#* #*#** ### +## ## ## # +#* *# * H *# +##*### # ## + ## ########### \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.12 b/emstar-levels/emstar-lvl.12 new file mode 100644 index 0000000..2e1473d --- /dev/null +++ b/emstar-levels/emstar-lvl.12 @@ -0,0 +1,9 @@ +## ## #### +#@#####* ### *## +# ** * # +# ## ##* #*# # +# # * ###* ## # +# ## ## #H# # +# * # +# * # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.13 b/emstar-levels/emstar-lvl.13 new file mode 100644 index 0000000..021a901 --- /dev/null +++ b/emstar-levels/emstar-lvl.13 @@ -0,0 +1,9 @@ + ############## +# @# * ## +# # #* *## # +# * # # +# * #*# +# # * # +## * * #*# +#H # * # # # + ############## \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.14 b/emstar-levels/emstar-lvl.14 new file mode 100644 index 0000000..28b1a04 --- /dev/null +++ b/emstar-levels/emstar-lvl.14 @@ -0,0 +1,9 @@ +################ +#*#* *#*# +# *#@ ## # +# H * # +# *# # +# * # +# *# # # +#*#* *#*# +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.15 b/emstar-levels/emstar-lvl.15 new file mode 100644 index 0000000..4a4c4b1 --- /dev/null +++ b/emstar-levels/emstar-lvl.15 @@ -0,0 +1,9 @@ + ###### ####### +# *# * # +# # * # # * # +# @# #** #* # + # # # * H# # +#* # #* # + # * # +#* *# + ############## \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.16 b/emstar-levels/emstar-lvl.16 new file mode 100644 index 0000000..759fbf4 --- /dev/null +++ b/emstar-levels/emstar-lvl.16 @@ -0,0 +1,9 @@ +################ +## H#* * *# +#* @*#* ## +## ### * ## +## *#*# # +#** *#* # +## * ####* # +##*# # # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.17 b/emstar-levels/emstar-lvl.17 new file mode 100644 index 0000000..784f654 --- /dev/null +++ b/emstar-levels/emstar-lvl.17 @@ -0,0 +1,9 @@ +################ +# *# #@ # +# # *#**#* # # +# #*##*# * # +# *# *# # +# *#* *# # +# # # ##*# # # +# * #* H # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.18 b/emstar-levels/emstar-lvl.18 new file mode 100644 index 0000000..42390c4 --- /dev/null +++ b/emstar-levels/emstar-lvl.18 @@ -0,0 +1,9 @@ +################ +# * * H# # +# #*#* #* # +# #*# #* # +# * # *#* # +# #*# # *# # +# *#* # * # # +#*#@ # # # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.19 b/emstar-levels/emstar-lvl.19 new file mode 100644 index 0000000..9ec7902 --- /dev/null +++ b/emstar-levels/emstar-lvl.19 @@ -0,0 +1,9 @@ +################ +#* ## ##*# +# # # #* # +# *# *## * # +# # #* # +# # *# # +# ## *# ##* #H# +# *# #* ##@# +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.2 b/emstar-levels/emstar-lvl.2 new file mode 100644 index 0000000..665e341 --- /dev/null +++ b/emstar-levels/emstar-lvl.2 @@ -0,0 +1,9 @@ + # # # # # ## +# * @# + #* #* * +# # * * # # + # * # +# #H# * # + # # # #**# +# # + # # # \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.20 b/emstar-levels/emstar-lvl.20 new file mode 100644 index 0000000..4711784 --- /dev/null +++ b/emstar-levels/emstar-lvl.20 @@ -0,0 +1,9 @@ +################ +# *#* # +##* *# ##* ## +# # # * # # # +# H # ## # @*# +# # # * # # # +## *## #* *## +# *#* # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.21 b/emstar-levels/emstar-lvl.21 new file mode 100644 index 0000000..6d9551a --- /dev/null +++ b/emstar-levels/emstar-lvl.21 @@ -0,0 +1,9 @@ +################ +# ### * ## +# # # ## +# ##* * # +# * * * ## +# # ###* # +# * * @ H * **# +################ + \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.22 b/emstar-levels/emstar-lvl.22 new file mode 100644 index 0000000..c01c347 --- /dev/null +++ b/emstar-levels/emstar-lvl.22 @@ -0,0 +1,9 @@ +################ +#*# #*# #* # # +# # # +#* # #* * # +## #* * ### +# * # ###* # +# #@#H * # +################ + \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.23 b/emstar-levels/emstar-lvl.23 new file mode 100644 index 0000000..2b67b6b --- /dev/null +++ b/emstar-levels/emstar-lvl.23 @@ -0,0 +1,9 @@ + ############## +# # #*# #* # # +# * # # +## # * #* # +# #* # ** * # +##* # ## * # +# #@#H * # + ############## + \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.24 b/emstar-levels/emstar-lvl.24 new file mode 100644 index 0000000..cfa2dab --- /dev/null +++ b/emstar-levels/emstar-lvl.24 @@ -0,0 +1,9 @@ +################ +# # ## +# ##* * ##*## +# #* *# ### +# ** *# ## # +# #* * # ## # +# ## @#H###**# +################ + \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.25 b/emstar-levels/emstar-lvl.25 new file mode 100644 index 0000000..4469474 --- /dev/null +++ b/emstar-levels/emstar-lvl.25 @@ -0,0 +1,9 @@ +################ +# # # +# * ##* * # +# #* * ## # +# * ## #* # +# #* *# * # +# ##* #@ H # +################ + \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.3 b/emstar-levels/emstar-lvl.3 new file mode 100644 index 0000000..3687c77 --- /dev/null +++ b/emstar-levels/emstar-lvl.3 @@ -0,0 +1,9 @@ +################ +# *#@# +# ## ##H# +# #* * # +# * *## *# +# #* * *# *## +# ##* #* * *### +#* ##* # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.4 b/emstar-levels/emstar-lvl.4 new file mode 100644 index 0000000..ab03d9a --- /dev/null +++ b/emstar-levels/emstar-lvl.4 @@ -0,0 +1,9 @@ +################ +# #H# +# # # +##*#* *#*#*#*#*# +# # #* *# # # ## +##*#*#* *#*#*#*# +# # # +# # #@ # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.5 b/emstar-levels/emstar-lvl.5 new file mode 100644 index 0000000..9512e91 --- /dev/null +++ b/emstar-levels/emstar-lvl.5 @@ -0,0 +1,9 @@ + ############## +#@ # # # # +# #* # * * # # +## # # # +#* #*# ## +## # * # # +#*# # # # #H# +# # *# #*# + ############## \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.6 b/emstar-levels/emstar-lvl.6 new file mode 100644 index 0000000..648ad6e --- /dev/null +++ b/emstar-levels/emstar-lvl.6 @@ -0,0 +1,9 @@ + ############ + # * #* *# + # * # ## + # * # +#@ * # +## * # ## +# * # # +#H # * ##* # +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.7 b/emstar-levels/emstar-lvl.7 new file mode 100644 index 0000000..9fff69c --- /dev/null +++ b/emstar-levels/emstar-lvl.7 @@ -0,0 +1,9 @@ +################ +# # + ## ### #* ##*# + #* #* # # # # + # # ### ## + ## # #*# #*# +# # +# @#* H #*# +################ \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.8 b/emstar-levels/emstar-lvl.8 new file mode 100644 index 0000000..a634c02 --- /dev/null +++ b/emstar-levels/emstar-lvl.8 @@ -0,0 +1,9 @@ +############### +# *## ## +# #* ## * # +# *## # #* # +## ## #*# # +## # *#* # +#*H*# * #@# # +## # + ############### \ No newline at end of file diff --git a/emstar-levels/emstar-lvl.9 b/emstar-levels/emstar-lvl.9 new file mode 100644 index 0000000..cd69fb8 --- /dev/null +++ b/emstar-levels/emstar-lvl.9 @@ -0,0 +1,9 @@ + # ########### + #*#* # @# +#* *# * # + # # *## *# # +# #* #*H* *# +# *## # +#*#* # +# # +############ \ No newline at end of file diff --git a/emstar.el b/emstar.el new file mode 100644 index 0000000..a923ee3 --- /dev/null +++ b/emstar.el @@ -0,0 +1,556 @@ +;;; emstar.el --- Emstar Game + +;; Copyright (C) 2008 Gwenhael Le Moine + +;; Author: Gwenhael Le Moine +;; Keywords: games + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; Play Emstar in emacs. +;; Heavily based on emacs-sokoban + +;;; Code: + +(require 'cl) + +(defconst emstar-version "0.1" + "Version string for this version of GNU-Emacs Emstar.") + +(defconst emstar-left '(-1 . 0)) +(defconst emstar-right '( 1 . 0)) +(defconst emstar-down '( 0 . 1)) +(defconst emstar-up '( 0 . -1)) +(defconst emstar-eater "eater") +(defconst emstar-stopper "stopper") + +(defgroup emstar nil + "Emstar game for GNU Emacs." + :prefix "emstar-" + :group 'games) + +(defcustom emstar-playerfiles-dir "/tmp/" + "*The directory holding the emstar playerfiles. +Emstar saves the information from `emstar-player-stats' to a +playerfile in this directory. If you don't want to use +playerfiles, set value to NIL." + :group 'emstar + :type 'string) + +(defvar emstar-player-stats nil + "Alist with player specific information as saved in the playerfiles. +This holds the best results for each finished level and the +players current level.") + +(defconst emstar-playerfile-prefix "emstar-pl-" + "The prefix used for emstar playerfiles.") + +(defvar emstar-best-players-list nil + "A list with the best result for each level +generated from all available playerfiles, if `emstar-playerfiles-dir' +is none nil.") + +(defcustom emstar-levels-dir "/usr/local/share/emstar/emstar-levels" + "*Directory holding the emstar level files" + :group 'emstar + :type 'string) + +(defcustom emstar-levels-basename "emstar-lvl." + "*Basename of the emstar level files" + :group 'emstar + :type 'string) + +(defcustom emstar-start-level 1 + "*Defines the level-numver to start with. +This might be overwritten by the last level played, +as saved in the playerfile." + :group 'emstar + :type 'integer) + +(defcustom emstar-undo-penalty 3 + "*Defines the number of moves one undo costs." + :group 'emstar + :type 'integer) + +(defcustom emstar-eater-char ?@ + "*Defines the character used to diplay the eater." + :group 'emstar + :type 'character) + +(defcustom emstar-gift-char ?* + "*Defines the character used to diplay the gifts." + :group 'emstar + :type 'character) + +(defcustom emstar-stopper-char ?H + "*Defines the character used to diplay the stopper." + :group 'emstar + :type 'character) + +(defcustom emstar-wall-char ?# + "*Defines the character used to diplay the walls." + :group 'emstar + :type 'character) + +(defface emstar-eater-face + '((t (:foreground "green" + :weight bold))) + "*Face used display the eater in emstar game." + :group 'emstar) + +(defface emstar-stopper-face + '((t (:foreground "red" + :weight bold))) + "*Face used display the stopper in emstar game." + :group 'emstar) + +(defface emstar-gift-face + '((t (:foreground "yellow" + :weight bold))) + "*Face used display gifts in emstar game." + :group 'emstar) + +(defface emstar-wall-face + '((t (:foreground "blue"))) + "*Face used display walls in emstar game." + :group 'emstar) + +(defvar emstar-eater-face 'emstar-eater-face) +(defvar emstar-stopper-face 'emstar-stopper-face) +(defvar emstar-gift-face 'emstar-gift-face) +(defvar emstar-wall-face 'emstar-wall-face) + +(defconst emstar-font-lock-keywords + `((,(regexp-quote (char-to-string emstar-eater-char)) + . emstar-eater-face) + (,(regexp-quote (char-to-string emstar-stopper-char)) + . emstar-stopper-face) + (,(regexp-quote (char-to-string emstar-gift-char)) + . emstar-gift-face) + (,(regexp-quote (char-to-string emstar-wall-char)) + . emstar-wall-face)) + "Stuff to highlight in emstar.") + +(defvar emstar-mode-map nil + "Keymap for emstar.") +(defvar emstar-selected 'emstar-eater + "Currently selected piece.") +(setq emstar-mode-map (make-sparse-keymap)) +(define-key emstar-mode-map [up] 'emstar-move-up) +(define-key emstar-mode-map [down] 'emstar-move-down) +(define-key emstar-mode-map [left] 'emstar-move-left) +(define-key emstar-mode-map [right] 'emstar-move-right) +(define-key emstar-mode-map "u" 'emstar-undo) +(define-key emstar-mode-map "b" 'emstar-display-best-players-list) +(define-key emstar-mode-map ">" 'emstar-goto-next-level) +(define-key emstar-mode-map "n" 'emstar-goto-next-level) +(define-key emstar-mode-map "<" 'emstar-goto-prev-level) +(define-key emstar-mode-map "p" 'emstar-goto-prev-level) +(define-key emstar-mode-map " " 'emstar-switch-selected) +(define-key emstar-mode-map "r" 'emstar-reload-level) + +(defvar emstar-collected-gifts 0 + "Number of gifts collected. Buffer-local in emstar-mode.") +(defvar emstar-total-gifts 0 + "Total number of gifts. Buffer-local in emstar-mode.") +(defvar emstar-level nil + "Number of current level. Buffer-local in emstar games.") +(defvar emstar-moves nil + "Number of moves made by player. Buffer-local in emstar-mode.") +(defvar emstar-pos nil + "Current position of player. Buffer-local in emstar-mode.") +(defvar emstar-last-pos nil + "Backup of last player position. Buffer-local in emstar-mode.") +(defvar emstar-game-info nil + "String with infos to the current game. Buffer-local in emstar-mode.") +(defvar emstar-level-best-string nil + "String holding the best result for the current level as displayed.") + +(defun emstar-forward-line (arg) + "Like forward-line but preserve the current column. +The implementation is rather simple, as we can make certain +assumptions about the structure of a valid emstar level buffer." + (let ((goal-column (current-column))) + (forward-line arg) + (move-to-column goal-column))) + +(defun emstar-paint (char) + "Insert char at point, overwriting the old char. +Extreme simple, but sufficient for our needs." + (let ((inhibit-read-only t)) + (delete-char 1) + (insert (char-to-string char)) + (forward-char -1)) + t) + +(defun emstar-count-gifts () + (setq emstar-total-gifts 0) + (goto-char (point-min)) + (while (search-forward (char-to-string emstar-gift-char) nil t) + (setq emstar-total-gifts (1+ emstar-total-gifts)))) + +(defun emstar-refresh-collected-gifts () + (setq emstar-collected-gifts 0) + (goto-char (point-min)) + (while (search-forward (char-to-string emstar-gift-char) nil t) + (setq emstar-collected-gifts (1+ emstar-collected-gifts))) + (setq emstar-collected-gifts (- emstar-total-gifts emstar-collected-gifts ))) + +(defun emstar-update-score (level moves) + "Save number of moves for level to `emstar-player-stats'." + (let* ((level-name (concat emstar-levels-basename + (number-to-string level))) + (entry (assoc level-name emstar-player-stats))) + (if entry + (or (< (cdr entry) moves) (setcdr entry moves)) + (push (cons level-name moves) emstar-player-stats)))) + +(defun emstar-get-level-best (level &optional list) + "Get best result for level from `emstar-player-stats'." + (if level + (let* ((level-name (concat emstar-levels-basename + (number-to-string level))) + (entry (assoc level-name + (or list emstar-player-stats)))) + (if entry + (cdr entry))))) + +(defun emstar-update-current-level (level) + "Save current level to `emstar-player-stats'." + (let ((entry (assoc :level emstar-player-stats))) + (if entry + (setcdr entry level) + (push (cons :level level) emstar-player-stats)))) + +(defun emstar-save-playerfile () + "Save `emstar-player-stats' to playerfile." + (if emstar-playerfiles-dir + (let ((filename (concat emstar-playerfiles-dir "/" + emstar-playerfile-prefix + (user-login-name)))) + (with-temp-file filename + (prin1 emstar-player-stats (current-buffer))) + (set-file-modes filename #o644)))) + +(defun emstar-load-playerfile () + "Load `emstar-player-stats' from playerfile." + (if emstar-playerfiles-dir + (let ((filename (concat emstar-playerfiles-dir "/" + emstar-playerfile-prefix + (user-login-name)))) + (if (file-readable-p filename) + (with-temp-buffer + (insert-file-contents filename nil) + (setq emstar-player-stats + (read (current-buffer)))))))) + +(defun emstar-gen-best-players-list () + (if emstar-playerfiles-dir + (let ((files (directory-files emstar-playerfiles-dir + t (concat "^" emstar-playerfile-prefix) + t))) + (dolist (filename files) + (if (file-readable-p filename) + (with-temp-buffer + (insert-file-contents filename nil) + (let ((stats (read (current-buffer))) + (player (substring (file-name-nondirectory filename) + (1- (length emstar-levels-basename))))) + (dolist (entry stats) + (let* ((level-name (car entry)) + (best-entry (assoc level-name + emstar-best-players-list))) + (if (and (stringp level-name) + (compare-strings level-name + 0 (length emstar-levels-basename) + emstar-levels-basename + 0 nil)) + (cond ((and best-entry + (> (cadr best-entry) (cdr entry))) + (setcdr best-entry + (cons (cdr entry) player))) + ((or (not best-entry) + (= (cadr best-entry) (cdr entry))) + (push (cons level-name + (cons (cdr entry) player)) + emstar-best-players-list))))))))))))) + + +(defun emstar-display-best-players-list () + (interactive) + (if emstar-best-players-list + (progn + (switch-to-buffer (get-buffer-create "*Emstar Best Players*")) + (erase-buffer) + (dolist (entry emstar-best-players-list) + (let ((level-name (car entry))) + (if (and (stringp level-name) + (compare-strings level-name + 0 (length emstar-levels-basename) + emstar-levels-basename + 0 nil)) + (insert (format "%4s: %5d - %s\n" + (substring level-name + (length emstar-levels-basename)) + (cadr entry) + (cddr entry)))))) + (sort-columns nil (point-min) (point-max))) + (error "No best players list available"))) + +(defun emstar-load-next-level (&optional arg) + "Load next level, with negative arg load previous level. +If requested level doesn't exist, load `emstar-start-level'." + (when (bound-and-true-p emstar-level) + (setq emstar-level (if (and arg (< arg 0)) + (1- emstar-level) + (1+ emstar-level))) + (or (emstar-load-level emstar-level) + (progn + (setq emstar-level emstar-start-level) + (emstar-load-level emstar-level))) + (emstar-init-level) + t)) + +(defun emstar-level-finished () + (message + (format "You finished Level %d in %d moves. Congratulations!" + (or (bound-and-true-p emstar-level) 0) + emstar-moves)) + (when (bound-and-true-p emstar-level) + (emstar-update-score emstar-level emstar-moves)) + (when (emstar-load-next-level) + (emstar-update-current-level emstar-level) + (emstar-save-playerfile))) + +(defun emstar-find-current-pos () + (goto-char (point-min)) + (search-forward (char-to-string (if (equal emstar-selected emstar-eater) + emstar-eater-char + emstar-stopper-char))) + (forward-char -1) + (setq emstar-pos (point))) + +(defun emstar-move-here () + "Move player to point. +Move player char to point, repaint pits and evaluate game status." + (interactive) + (setq emstar-pos (point)) + (emstar-paint (if (equal emstar-selected emstar-eater) + emstar-eater-char + emstar-stopper-char)) + (goto-char emstar-last-pos) + (emstar-paint 32) + (setq emstar-moves (1+ emstar-moves)) + (emstar-update-mode-line)) + +(defun emstar-move-eater (direction) + (goto-char emstar-pos) + (setq emstar-last-pos (point)) + (while (progn + (setq emstar-pos (point)) + (forward-char (car direction)) + (emstar-forward-line (cdr direction)) + (if (= (char-after) emstar-gift-char) + (progn + (setq emstar-collected-gifts (1+ emstar-collected-gifts)) + (emstar-paint 32))) + (= (char-after) 32))) + (goto-char emstar-pos) + (if (or + (= (char-after) 32) + (= (char-after) emstar-gift-char)) + (emstar-move-here)) + (if (= emstar-total-gifts emstar-collected-gifts) + (emstar-level-finished))) + +(defun emstar-move-stopper (direction) + (goto-char emstar-pos) + (setq emstar-last-pos (point)) + (while (progn + (setq emstar-pos (point)) + (forward-char (car direction)) + (emstar-forward-line (cdr direction)) + (= (char-after) 32))) + (goto-char emstar-pos) + (if (= (char-after) 32) + (emstar-move-here))) + + +(defun emstar-move-up () + "Move the player up if possible." + (interactive) + (if (equal emstar-selected emstar-eater) + (emstar-move-eater emstar-up) + (emstar-move-stopper emstar-up))) + +(defun emstar-move-down () + "Move the player down if possible." + (interactive) + (if (equal emstar-selected emstar-eater) + (emstar-move-eater emstar-down) + (emstar-move-stopper emstar-down))) + +(defun emstar-move-left () + "Move the player left if possible." + (interactive) + (if (equal emstar-selected emstar-eater) + (emstar-move-eater emstar-left) + (emstar-move-stopper emstar-left))) + +(defun emstar-move-right () + "Move the player right if possible." + (interactive) + (if (equal emstar-selected emstar-eater) + (emstar-move-eater emstar-right) + (emstar-move-stopper emstar-right))) + +(defun emstar-goto-next-level () + "Jump to next level." + (interactive) + (emstar-load-next-level)) + +(defun emstar-goto-prev-level () + "Jump to previous level." + (interactive) + (emstar-load-next-level -1)) + +(defun emstar-reload-level () + "Jump to previous level." + (interactive) + (emstar-load-level emstar-level) + (emstar-init-level)) + +(defun emstar-switch-selected () + "Switch the item moved." + (interactive) + (setq emstar-selected (if (equal emstar-selected emstar-eater) + emstar-stopper + emstar-eater)) + (if (equal emstar-selected emstar-eater) + (progn + (set-face-inverse-video-p emstar-eater-face t) + (set-face-inverse-video-p emstar-stopper-face nil)) + (progn + (set-face-inverse-video-p emstar-eater-face nil) + (set-face-inverse-video-p emstar-stopper-face t))) + (emstar-find-current-pos)) + +(defun emstar-update-mode-line () + (setq emstar-game-info (format "Level:%d -- %d/%d -- Moves:%d" + (or (bound-and-true-p emstar-level) + 0) + emstar-collected-gifts + emstar-total-gifts + emstar-moves + (or emstar-level-best-string "")))) + +(defun emstar-undo () + (interactive) + (let ((inhibit-read-only t)) + (undo)) + (emstar-find-current-pos) + (setq emstar-moves (+ emstar-moves emstar-undo-penalty)) + (emstar-refresh-collected-gifts) + (emstar-update-mode-line)) + +(defun emstar-load-level (num) + "Load emstar level num." + (let ((inhibit-read-only t) + (level-file + (concat emstar-levels-dir "/" + emstar-levels-basename (number-to-string num)))) + (when (file-exists-p level-file) + (insert-file-contents level-file nil nil nil t) + t))) + +(defun emstar-init-level () + "Initialize level elements." + (setq emstar-selected emstar-eater) + (set-face-inverse-video-p emstar-eater-face t) + (set-face-inverse-video-p emstar-stopper-face nil) + (setq emstar-moves 0) + (setq emstar-collected-gifts 0) + (setq emstar-total-gifts 0) + (setq emstar-level-best-string + (let ((best (emstar-get-level-best emstar-level)) + (world-best (if emstar-best-players-list + (emstar-get-level-best + emstar-level + emstar-best-players-list)))) + (if (or best world-best) + (format " [Best:%s%s]" + (if best (number-to-string best) "") + (if (and world-best + (or (not best) + (< (car world-best) best))) + (format " (%s:%d)" + (cdr world-best) (car world-best)) + ""))))) + (emstar-count-gifts) + (emstar-update-mode-line) + (emstar-find-current-pos) + (buffer-disable-undo (current-buffer)) + (buffer-enable-undo) +) +;;;###autoload +(defun emstar-mode () + "Major mode to play emstar. + +Commands: +\\{emstar-mode-map}" + (interactive) + (kill-all-local-variables) + (toggle-read-only 1) + (use-local-map emstar-mode-map) + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults '(emstar-font-lock-keywords + t nil nil beginning-of-line)) + (setq cursor-type nil) + (make-local-variable 'emstar-level) + (make-local-variable 'emstar-pos) + (make-local-variable 'emstar-last-pos) + (make-local-variable 'emstar-moves) + (make-local-variable 'emstar-collected-gifts) + (make-local-variable 'emstar-total-gifts) + (make-local-variable 'emstar-game-info) + (setq major-mode 'emstar-mode) + (setq mode-name "Emstar") + (setq header-line-format + (list "Emstar v" 'emstar-version + " -- " 'emstar-game-info " ~ " 'emstar-selected)) + (emstar-init-level) + (run-hooks 'emstar-mode-hook)) + +;;;###autoload +(defun emstar () + "Play emstar." + (interactive) + (switch-to-buffer (generate-new-buffer "*Emstar*")) + (emstar-load-playerfile) + (setq emstar-best-players-list nil) + (emstar-gen-best-players-list) + (let ((level (or (cdr (assoc :level emstar-player-stats)) + emstar-start-level))) + (emstar-load-level level) + (emstar-mode) + (setq emstar-level level)) + (emstar-init-level) + (emstar-update-mode-line)) + +(provide 'emstar) +;;; emstar.el ends here