1
0
Fork 0

Added Sokoban

This commit is contained in:
acn 2019-10-24 15:10:47 +02:00
parent 681542b41c
commit 66426f5a03
11 changed files with 1568 additions and 0 deletions

View File

@ -24,6 +24,7 @@ See this repository: https://git.imzadi.de/acn/backgammon-vt100
* [Quatris](Quatris/)
* [Worm](Worm/)
* [Cpmtris](cpmtris/)
* [Sokoban](Sokoban/)
## More Games on the Interwebs

BIN
Sokoban/HitechC/z80v309.lbr Normal file

Binary file not shown.

54
Sokoban/README.md Normal file
View File

@ -0,0 +1,54 @@
# Sokoban
CP/M port of a Unix curses clone of sokoban
I found it as part of the ZCN repository: https://github.com/jamesots/zcn
The C source has been modified for VT100 compatibility, and some unused variables have been removed :)
``sokoban.com`` is the compiled binary.
To run it, the files ``sokoban.com`` and ``soklevls.dat`` are needed
The help file, ``sokoban.hlp``, is not used in this version.
You find the contents below.
See the ``readme.*`` files for more information.
## Commands
| Key | Action | Key | Action | Key | Action |
| --- | ------------------- | --- | -------------- | --- | ------------------- |
| h | move/push left | H | run/push left | ^H | run left to object |
| l | move/push right | L | run/push right | ^L | run right to object |
| j | move/push down | J | run/push down | ^J | run down to object |
| k | move/push up | K | run/push up | ^K | run up to object |
| u | undo last move/push | U | undo all | | |
| c | temporary save | ^U | reset to temporary save | | |
| ^R | Refresh screen | ? | this help | | |
| q | quit | s | save the game | | |
## The game
Characters on screen are:
| @@ | player | ++ | player on saving position |
| .. | saving position for packet | $$ | packets |
| ** | saved packet | ## | wall |
Your goal is to move all packets to the saving position by pushing them.
As you could see you can make a temporary save. This is useful if you think
that all the moves/pushes you have made are correct, but you don't know how
to go on. In this case you can temporary save (using the c command). If you
then get stucked you need not undo all (using U), you can reset to you
temporary save.
If you have restored a saved game, a temporary save is automatically made
at the start.
## Compiling
HiTech C has been used to compile it, it is placed in the directory ``HitechC``.
To compile Sokoban, I used the command ``c -O sokoban.c`` in CP/M.

19
Sokoban/readme.1st Normal file
View File

@ -0,0 +1,19 @@
This is a CP/M port of a Unix curses clone of sokoban, along with an
executable patched to run in emulated 80x24 on ZCN.
To run it on ZCN, you need to copy both sokoban.com and soklevls.dat.
To run on any other CP/M, you'll probably need to hack the clear() and
move() routines in sokzcn.c and recompile it (with Hitech C); see
sokzcn.c for more.
The various other README files aren't too relevant any more, but
they're the READMEs supplied by the author(s) of the version I ported.
FYI, and all that. :-)
I combined all the level files into one 'soklevls.dat' file. The format
is that of the old screen.?? files, but with a ^L separating each level.
This should make it easy to add your own levels; in VDE you can insert a
^L by doing ^P ^L. The hard bit is designing the levels. :-)
-Rus.

34
Sokoban/readme.lnx Normal file
View File

@ -0,0 +1,34 @@
This packages was originally a port of sokoban to minix. but with a
few hacks it works fine with linux too.
I have done some hacking in source-code to
obtain the following:
1. It is now possible to use the arrow-keys
to move the player, you can also use the
numerical-keypad.
2. The objects now contains of two diffrent
characters so you can make packages thats
looks like '[]', earlier you just had one
character that where repeated twice.
3. The getch function in curses dont behave well
in combination with tcsh (6.01) so i 'borrowed'
from tt (the Tetris clone) the method to use
read instead.
The Executable is compiled with gcc2.1 and shared libs, but it should
be no problems to re-compile it with gcc 1.40
The compiled version looks for screenfiles in /usr/games/sokob, it also
puts its highscore file there.
Dont forget to make a highscore file first, sokoban want work if you don't.
Bengt Andersson.
Student at KTH (The Royal Tecnical High School) Sweden.
email: da1-ban@nada.kth.se

39
Sokoban/readme.org Normal file
View File

@ -0,0 +1,39 @@
This is SOKOBAN.
I saw this game first on a PC running MSDOS. I found the idea of the game so
clever, that I made up my mind to make it run with an ascii terminal using
curses so that we can play it on our MicroVAX/ULTRIX.
Along with this package there are alot of screen files describing the various
play levels. So what you need to do to install it on your own machine is:
- Edit the header file sokoban.h to alter the given defines
You have to note the following restrictions
- The screen files must be readable for everyone who should be able to play
his game
- The score file should have read/write permission only for the owner
of the executable program. Because of that sokoban must run with setuid.
You can now compile it (just type 'make').
If compilation is succesful you must initialize the score file (just type
'sokoban -c')
There is no manual page. All you have to know when you first play the game is
the command '?'. This gives you one screenful of information.
After you have solved all the given screens (this will take a while) you will
find the game boring (sure you will). I hope there will be a lot of players who
will think out some new screens.
To test your own screens copy them to the screen directory (with a new level
number <nn>) and type sokoban -<nn>.
PLEASE DO SO AND POST NEW SCREENS TO THE NET.
OTHERWISE IT GETS BORING !!!!!!!!!!!!!!!!!!!!
Comments are welcome.
>From Canada or the US reply to ...!pyramid!tub!astbe!ber
(otherwise it would be expensive)
from elsewhere reply to ber@astbe

27
Sokoban/readme.v2 Normal file
View File

@ -0,0 +1,27 @@
This is my second version of SOKOBAN.
The first thing I have to say is that I don't have the sources for SOKOBAN
under MS-DOS. I believe that this program is copyrighted. I took only the
idea and the screens of the PC-version.
I think that porting my version of SOKOBAN to the PC will not be very difficult
if you use the PC-Curses version which was on the net some months ago.
I had a short mail talk with Norman Ramsey (...!allegra!princeton!nr) who wants
to do the porting. He said that he will post his version if the work is done.
Some people asked me whether it is possible to make a better looking screen.
I added some extra definitions to the header file sokoban.h so that it is
possible to alter the the characters that are used for the representation of
the objects on the screen. You can also define wheter the object is displayed
in standout mode (invers) or not.
There is no helpfile anymore (sokoban.help in the first version). I
included the help file in showscreen.c and made a better help facility.
The score files from both versions are compatible so that you can go on with
the game.
At last I added some new screens. I hope you enjoy them.
If you have already designed some new screens mail them to me. My netadress is
given in README.

761
Sokoban/soklevls.dat Normal file
View File

@ -0,0 +1,761 @@
#####
# #
#$ #
### $##
# $ $ #
### # ## # ######
# # ## ##### ..#
# $ $ ..#
##### ### #@## ..#
# #########
#######
############
#.. # ###
#.. # $ $ #
#.. #$#### #
#.. @ ## #
#.. # # $ ##
###### ##$ $ #
# $ $ $ $ #
# # #
############
########
# @#
# $#$ ##
# $ $#
##$ $ #
######### $ # ###
#.... ## $ $ #
##... $ $ #
#.... ##########
########
########
# ....#
############ ....#
# # $ $ ....#
# $$$#$ $ # ....#
# $ $ # ....#
# $$ #$ $ $########
# $ # #
## #########
# # ##
# $ ##
# $$#$$ @#
# # ##
###########
#####
# #####
# #$## #
# $ #
######### ### #
#.... ## $ $###
#.... $ $$ ##
#.... ##$ $ @#
######### $ ##
# $ $ #
### ## #
# #
######
###### ###
#.. # ##@##
#.. ### #
#.. $$ #
#.. # # $ #
#..### # $ #
#### $ #$ #
# $# $ #
# $ $ #
# ## #
#########
#####
####### ##
## # @## $$ #
# $ #
# $ ### #
### #####$###
# $ ### ..#
# $ $ $ ...#
# ###...#
# $$ # #...#
# ### #####
####
####
# ###########
# $ $ $ #
# $# $ # $ #
# $ $ # #
### $# # #### #
#@#$ $ $ ## #
# $ #$# # #
# $ $ $ $ #
##### #########
# #
# #
#......#
#......#
#......#
########
#######
# ...#
##### ...#
# . .#
# ## ...#
## ## ...#
### ########
# $$$ ##
##### $ $ #####
## #$ $ # #
#@ $ $ $ $ #
###### $$ $ #####
# #
########
### #############
##@#### # #
# $$ $$ $ $ ...#
# $$$# $ #...#
# $ # $$ $$ #...#
### # $ #...#
# # $ $ $ #...#
# ###### ###...#
## # # $ $ #...#
# ## # $$ $ $##..#
# ..# # $ #.#
# ..# # $$$ $$$ #.#
##### # # #.#
# ######### #.#
# #.#
###############
####
#### # #
### @###$ #
## $ #
## $ $$## ##
# #$## #
# # $ $$ # ###
# $ # # $ #####
#### # $$ # #
#### ## $ #
#. ### ########
#.. ..# ####
#...#.#
#.....#
#######
################
# #
# # ###### #
# # $ $ $ $# #
# # $@$ ## ##
# # $ $ $###...#
# # $ $ ##...#
# ###$$$ $ ##...#
# # ## ##...#
##### ## ##...#
##### ###
# #
#######
#########
## ## #####
### # # ###
# $ #$ # # ... #
# # $#@$## # #.#. #
# # #$ # . . #
# $ $ # # #.#. #
# ## ##$ $ . . #
# $ # # #$#.#. #
## $ $ $ $... #
#$ ###### ## #
# # ##########
####
#######
####### #
# # $@$ #
#$$ # #########
# ###......## #
# $......## # #
# ###...... #
## #### ### #$##
# #$ # $ # #
# $ $$$ # $## #
# $ $ ###$$ # #
##### $ # #
### ### # #
# # #
######## #
####
########
# # #
# $ #
### #$ ####
# $ ##$ #
# # @ $ # $#
# # $ ####
## ####$## #
# $#.....# # #
# $..**. $# ###
## #.....# #
# ### #######
# $$ # #
# # #
###### #
#####
#####
# ##
# # ####
# $ #### #
# $$ $ $#
###@ #$ ##
# ## $ $ ##
# $ ## ## .#
# #$##$ #.#
### $..##.#
# #.*...#
# $$ #.....#
# #########
# #
####
##########
#.. # #
#.. #
#.. # ####
####### # ##
# #
# # ## # #
#### ## #### ##
# $ ##### # #
# # $ $ # $ #
# @$ $ # ##
#### ## #######
# #
######
###########
# . # #
# #. @ #
##### ##..# ####
## # ..### ###
# $ #... $ # $ #
# .. ## ## ## #
####$##$# $ # # #
## # #$ $$ # #
# $ # # # $## #
# #
# ########### #
#### ####
######
# @####
##### $ #
# ## ####
# $ # ## #
# $ # ##### #
## $ $ # #
## $ $ ### # #
## # $ # # #
## # #$# # #
## ### # # ######
# $ #### # #....#
# $ $ ..#.#
####$ $# $ ....#
# # ## ....#
###################
##########
##### ####
# # $ #@ #
# #######$#### ###
# # ## # #$ ..#
# # $ # # #.#
# # $ # #$ ..#
# # ### ## #.#
# ### # # #$ ..#
# # # #### #.#
# #$ $ $ #$ ..#
# $ # $ $ # #.#
#### $### #$ ..#
# $$ ###....#
# ## ######
########
#########
# #
# ####
## #### # #
## #@## #
# $$$ $ $$#
# # ## $ #
# # ## $ ####
#### $$$ $# #
# ## ....#
# # # #.. .#
# # # ##...#
##### $ #...#
## #####
#####
###### ####
# ####### #####
# $# # $ # #
# $ $ $ # $ $ #
##$ $ # @# $ #
# $ ########### ##
# # #.......# $#
# ## # ......# #
# # $........$ #
# # $ #.... ..# #
# $ $####$#### $#
# $ ### $ $ ##
# $ $ $ $ #
## ###### $ ##### #
# # #
###################
#######
# # ####
##### $#$ # ##
#.. # # # #
#.. # $#$ # $####
#. # #$ # #
#.. $# # $ #
#..@# #$ #$ # #
#.. # $# $# #
#.. # #$$#$ # ##
#.. # $# # $#$ #
#.. # # # # #
##. #### ##### #
#### #### #####
###############
#.......... .####
#..........$$.# #
###########$ # ##
# $ $ $ #
## #### # $ # #
# # ## # ##
# $# # ## ### ##
# $ #$### ### ##
### $ # # ### ##
### $ ## # # ##
# $ # $ $ $ #
# $ $#$$$ # #
# # $ #####
# @## # # #
##############
####
# ##############
# # ..#......#
# # # ##### ...#
##$# ........#
# ##$###### ####
# $ # ######@ #
##$ # $ ###### #
# $ #$$$## #
# # #$#$###
# #### #$$$$$ #
# # $ # #
# # ## ###
# ######$###### $ #
# # # #
########## #####
#######
# # #####
## # #...###
# $# #... #
# $ #$$ ... #
# $# #... .#
# # $########
##$ $ $ #
## # $$ # #
###### ##$$@#
# ##
########
#################
#... # # ##
##..... $## # #$ #
#......# $ # #
#......# # # # #
######### $ $ $ #
# #$##$ ##$##
## $ # $ #
# ## ### # ##$ #
# $ $$ $ $ #
# $ $##$ ######
####### @ ##
######
#####
##### #
## $ $ ####
##### $ $ $ ##.#
# $$ ##..#
# ###### ###.. #
## # # #... #
# $ # #... #
#@ #$ ## ####...#
#### $ $$ ##..#
## $ $ $...#
# $$ $ # .#
# $ $ ####
###### #
#####
#####
# ##
# $ #########
## # # ######
## # $#$#@ # #
# # $ # $ #
# ### ######### ##
# ## ..*..... # ##
## ## *.*..*.* # ##
# $########## ##$ #
# $ $ $ $ #
# # # # # #
###################
###########
# # #
##### # $ $ #
# ##### $## # ##
# $ ## # ## $ #
# $ @$$ # ##$$$ #
## ### # ## #
## # ### #####$#
## # $ #....#
# ### ## $ #....##
# $ $ # #..$. #
# ## $ # ##.... #
##### ######...##
##### #####
####
# #########
## ## # #
# $# $@$ ####
#$ $ # $ $# ##
## $## #$ $ #
# # # # $$$ #
# $ $ $## ####
# $ $ #$# # #
## ### ###$ #
# #.... #
####......####
#....####
#...##
#...#
#####
####
##### #
## $#
## $ ## ###
#@$ $ # $ #
#### ## $#
#....#$ $ #
#....# $#
#.... $$ ##
#... # $ #
######$ $ #
# ###
#$ ###
# #
####
############
## ## #
## $ $ #
#### ## $$ #
# $ # #
# $$$ # ####
# # # $ ##
# # # $ #
# $# $# #
# ..# ####
####.. $ #@#
#.....# $# #
##....# $ #
###..## #
############
#########
#.... ##
#.#.# $ ##
##....# # @##
# ....# # ##
# #$ ##$ #
## ### $ #
#$ $ $ $# #
# # $ $ ## #
# ### ## #
# ## ## ##
# $ # $ #
###$ $ ###
# #####
####
############ ######
# # # ###....#
# $$# @ .....#
# # ### # ....#
## ## ### # ....#
# $ $ # # ####
# $ $## # #
#### # #### # ## #
# # #$ ## # #
# $ $ # ## # ##
# # $ $ # # #
# $ ## ## # #####
# $$ $$ #
## ## ### $ #
# # # #
###### ######
#####
##### ###### #
# #### $ $ $ #
# $ ## ## ## ##
# $ $ $ $ #
### $ ## ## ##
# ##### #####$$ #
##$##### @## #
# $ ###$### $ ##
# $ # ### ###
# $$ $ # $$ #
# # ## #
#######.. .###
#.........#
#.........#
###########
###########
#...... #########
#...... # ## #
#..### $ $ #
#... $ $ # ## #
#...#$##### # #
### # #$ #$ #
# $$ $ $ $## #
# $ #$#$ ##$ #
### ## # ## #
# $ $ ## ######
# $ $ #
## # # #
#####@#####
###
####
####### @#
# $ #
# $## $#
##$#...# #
# $... #
# #. .# ##
# # #$ #
#$ $ #
# #######
####
######
#############....#
## ## ##....#
# $$## $ @##....#
# $$ $# ....#
# $ ## $$ # # ...#
# $ ## $ # ....#
## ##### ### ##.###
## $ $ ## . #
# $### # ##### ###
# $ # #
# $ #$ $ $### #
# $$$# $ # ####
# # $$ #
###### ###
#####
############
# ##
# # #$$ $ #
#$ #$# ## @#
## ## # $ # ##
# $ #$ # #
# # $ # #
## $ $ ## #
# # ## $ #
# ## $$# #
######$$ # #
#....# ########
#.#... ##
#.... #
#.... #
#########
#####
## ##
## #
## $$ #
## $$ $ #
# $ $ #
#### # $$ #####
# ######## ## #
#. $$$@#
#.# ####### ## ##
#.# #######. #$ $##
#........... # #
############## $ #
## ##
####
########
#### ######
# ## $ $ @#
# ## ##$#$ $ $##
### ......# $$ ##
# ......# # #
# # ......#$ $ #
# #$...... $$# $ #
# ### ###$ $ ##
### $ $ $ $ #
# $ $ $ $ #
###### ######
#####
#######
##### # ####
# # $ #
#### #$$ ## ## #
## # # ## ###
# ### $#$ $ $ #
#... # ## # #
#...# @ # ### ##
#...# ### $ $ #
######## ## # #
#########
#####
# #
# # #######
# $@######
# $ ##$ ### #
# #### $ $ #
# ##### # #$ ####
## #### ##$ #
# $# $ # ## ## #
# # #...# #
###### ### ... #
#### # #...# #
# ### # #
# #
#########
##### ####
#...# # ####
#...### $ #
#....## $ $###
##....## $ #
###... ## $ $ #
# ## # $ #
# ## # ### ####
# $ # #$ $ #
# $ @ $ $ #
# # $ $$ $ ###
# ###### ###
# ## ####
###
##########
# ####
# ###### # ##
# # $ $ $ $ #
# #$ #
###$ $$# ###
# ## # $##
##$# $ @#
# $ $ ###
# # $ #
# ## # #
## ##### #
# #
#.......###
#.......#
#########
####
######### ##
## $ $ #####
# ## ## ##...#
# #$$ $ $$#$##...#
# # @ # ...#
# $# ###$$ ...#
# $ $$ $ ##....#
###$ #######
# #######
####
#########
#*.*#*.*#
#.*.*.*.#
#*.*.*.*#
#.*.*.*.#
#*.*.*.*#
### ###
# #
###### ######
# #
# $ $ $ $ $ #
## $ $ $ $ ##
#$ $ $ $ $#
# $@$ #
# ##### #
#### ####
####
# ##
# ##
# $$ ##
###$ $ ##
#### $ #
### # ##### #
# # #....$ #
# # $ ....# #
# $ # #.*..# #
### #### ### #
#### @$ ##$##
### $ #
# ## #
#########
############
##.. # #
##..* $ $ #
##..*.# # # $##
#..*.# # # $ #
####...# # # #
# ## # #
# @$ $ ### # ##
# $ $ # # #
###$$ # # # # #
# $ # # #####
# $# ##### #
#$ # # # #
# ### ## #
# # # ##
#### ######

594
Sokoban/sokoban.c Normal file
View File

@ -0,0 +1,594 @@
/* A fairly hacked-up version of sokoban, for CP/M.
* ported 95/7/28 by Russell Marks
*
* It compiles ok (with the usual warnings :-)) under Hitech C.
* All the source files were basically cat'ted together to make compliation
* less awkward.
*
* You'll need to patch the 'clear' and 'move' routines with your
* machine/terminal's clear screen and cursor move codes. (They're currently
* set for ZCN.) For very simple terminals, you may even be able to patch
* the binary directly and not bother recompiling.
*
* This version is for VT100 compatible terminals, patched by
* Anna Christina Nass <acn@acn.wtf>
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define refresh()
#define printw printf
void clear()
{
printf("%c[2J%c[H",27,27);
}
void move(int y,int x)
{
printf("%c[%d;%dH",27,y+1,x+1);
}
short readscreen();
/**/
/* OBJECT: this typedef is used for internal and external representation */
/* of objects */
/**/
typedef struct {
char obj_intern; /* internal representation of the object */
char obj_display1; /* first display char for the object */
char obj_display2; /* second display char for the object */
short invers; /* if set to 1 the object will be shown invers */
} OBJECT;
/**/
/* You can now alter the definitions below.
/* Attention: Do not alter `obj_intern'. This would cause an error */
/* when reading the screenfiles */
/**/
static OBJECT
player = { '@', '*', '*', 0 },
playerstore = { '+', '*', '*', 1 },
store = { '.', '.', '.', 0 },
packet = { '$', '[', ']', 0 },
save = { '*', '<', '>', 1 },
ground = { ' ', ' ', ' ', 0 },
wall = { '#', '#', '#', 1 };
/*************************************************************************
********************** DO NOT CHANGE BELOW THIS LINE *********************
*************************************************************************/
#define MAXROW 20
#define MAXCOL 40
typedef struct {
short x, y;
} POS;
#define E_FOPENSCREEN 1
#define E_PLAYPOS1 2
#define E_ILLCHAR 3
#define E_PLAYPOS2 4
#define E_TOMUCHROWS 5
#define E_TOMUCHCOLS 6
#define E_ENDGAME 7
#define E_NOUSER 9
#define E_FOPENSAVE 10
#define E_WRITESAVE 11
#define E_STATSAVE 12
#define E_READSAVE 13
#define E_ALTERSAVE 14
#define E_SAVED 15
#define E_TOMUCHSE 16
#define E_FOPENSCORE 17
#define E_READSCORE 18
#define E_WRITESCORE 19
#define E_USAGE 20
#define E_ILLPASSWORD 21
#define E_LEVELTOOHIGH 22
#define E_NOSUPER 23
#define E_NOSAVEFILE 24
/* defining the types of move */
#define MOVE 1
#define PUSH 2
#define SAVE 3
#define UNSAVE 4
#define STOREMOVE 5
#define STOREPUSH 6
/* defines for control characters */
#define CNTL_L '\014'
#define CNTL_K '\013'
#define CNTL_H '\010'
#define CNTL_J '\012'
#define CNTL_R '\022'
#define CNTL_U '\025'
static POS tpos1, /* testpos1: 1 pos. over/under/left/right */
tpos2, /* testpos2: 2 pos. " */
lastppos, /* the last player position (for undo) */
last_p1, last_p2; /* last test positions (for undo) */
static char lppc, ltp1c, ltp2c; /* the char for the above pos. (for undo) */
static char action, lastaction;
/** For the temporary save **/
static char tmp_map[MAXROW+1][MAXCOL+1];
static short tmp_pushes, tmp_moves, tmp_savepack;
static POS tmp_ppos;
short scoring = 1;
short level, packets, savepack, moves, pushes, rows, cols;
short scorelevel, scoremoves, scorepushes;
char map[MAXROW+1][MAXCOL+1];
POS ppos;
char username[]="Player", *prgname;
short play() {
short c;
short ret;
short undolock = 1; /* locked for undo */
showscreen();
tmpsave();
ret = 0;
while( ret == 0) {
c=getch();
switch(c) { case '8': c = 'k'; break;
case '2': c = 'j'; break;
case '4': c = 'h'; break;
case '6': c = 'l'; break;
case '5': c = 'u'; break;
case 'E'&0x3f: c='k'; break;
case 'S'&0x3f: c='h'; break;
case 'D'&0x3f: c='l'; break;
case 'X'&0x3f: c='j'; break;
default: break; };
switch(c) {
case 'q': /* quit the game */
ret = E_ENDGAME;
break;
case CNTL_R: /* refresh the screen */
clear();
showscreen();
break;
case 'c': /* temporary save */
case 's':
tmpsave();
break;
case CNTL_U: /* reset to temporary save */
case 'r':
tmpreset();
undolock = 1;
showscreen();
break;
case 'U': /* undo this level */
moves = pushes = 0;
if( (ret = readscreen()) == 0) {
showscreen();
undolock = 1;
}
break;
case 'u': /* undo last move */
if( ! undolock) {
undomove();
undolock = 1;
}
break;
case 'k': /* up */
case 'K': /* run up */
case CNTL_K: /* run up, stop before object */
case 'j': /* down */
case 'J': /* run down */
case CNTL_J: /* run down, stop before object */
case 'l': /* right */
case 'L': /* run right */
case CNTL_L: /* run right, stop before object */
case 'h': /* left */
case 'H': /* run left */
case CNTL_H: /* run left, stop before object */
do {
if( (action = testmove( c)) != 0) {
lastaction = action;
lastppos.x = ppos.x; lastppos.y = ppos.y;
lppc = map[ppos.x][ppos.y];
last_p1.x = tpos1.x; last_p1.y = tpos1.y;
ltp1c = map[tpos1.x][tpos1.y];
last_p2.x = tpos2.x; last_p2.y = tpos2.y;
ltp2c = map[tpos2.x][tpos2.y];
domove( lastaction);
undolock = 0;
}
} while( (action != 0) && (! islower( c))
&& (packets != savepack));
break;
default: helpmessage(); break;
}
if( (ret == 0) && (packets == savepack)) {
scorelevel = level;
scoremoves = moves;
scorepushes = pushes;
break;
}
}
return( ret);
}
testmove( action)
register short action;
{
register short ret;
register char tc;
register short stop_at_object;
if( (stop_at_object = iscntrl( action))) action = action + 'A' - 1;
action = (isupper( action)) ? tolower( action) : action;
if( (action == 'k') || (action == 'j')) {
tpos1.x = (action == 'k') ? ppos.x-1 : ppos.x+1;
tpos2.x = (action == 'k') ? ppos.x-2 : ppos.x+2;
tpos1.y = tpos2.y = ppos.y;
}
else {
tpos1.y = (action == 'h') ? ppos.y-1 : ppos.y+1;
tpos2.y = (action == 'h') ? ppos.y-2 : ppos.y+2;
tpos1.x = tpos2.x = ppos.x;
}
tc = map[tpos1.x][tpos1.y];
if( (tc == packet.obj_intern) || (tc == save.obj_intern)) {
if( ! stop_at_object) {
if( map[tpos2.x][tpos2.y] == ground.obj_intern)
ret = (tc == save.obj_intern) ? UNSAVE : PUSH;
else if( map[tpos2.x][tpos2.y] == store.obj_intern)
ret = (tc == save.obj_intern) ? STOREPUSH : SAVE;
else ret = 0;
}
else ret = 0;
}
else if( tc == ground.obj_intern)
ret = MOVE;
else if( tc == store.obj_intern)
ret = STOREMOVE;
else ret = 0;
return( ret);
}
domove( moveaction)
register short moveaction;
{
map[ppos.x][ppos.y] = (map[ppos.x][ppos.y] == player.obj_intern)
? ground.obj_intern
: store.obj_intern;
switch( moveaction) {
case MOVE: map[tpos1.x][tpos1.y] = player.obj_intern; break;
case STOREMOVE: map[tpos1.x][tpos1.y] = playerstore.obj_intern; break;
case PUSH: map[tpos2.x][tpos2.y] = map[tpos1.x][tpos1.y];
map[tpos1.x][tpos1.y] = player.obj_intern;
pushes++; break;
case UNSAVE: map[tpos2.x][tpos2.y] = packet.obj_intern;
map[tpos1.x][tpos1.y] = playerstore.obj_intern;
pushes++; savepack--; break;
case SAVE: map[tpos2.x][tpos2.y] = save.obj_intern;
map[tpos1.x][tpos1.y] = player.obj_intern;
savepack++; pushes++; break;
case STOREPUSH: map[tpos2.x][tpos2.y] = save.obj_intern;
map[tpos1.x][tpos1.y] = playerstore.obj_intern;
pushes++; break;
}
moves++;
dispmoves(); disppushes(); dispsave();
mapchar( map[ppos.x][ppos.y], ppos.x, ppos.y);
mapchar( map[tpos1.x][tpos1.y], tpos1.x, tpos1.y);
mapchar( map[tpos2.x][tpos2.y], tpos2.x, tpos2.y);
move( MAXROW+1, 0);
refresh();
ppos.x = tpos1.x; ppos.y = tpos1.y;
}
undomove() {
map[lastppos.x][lastppos.y] = lppc;
map[last_p1.x][last_p1.y] = ltp1c;
map[last_p2.x][last_p2.y] = ltp2c;
ppos.x = lastppos.x; ppos.y = lastppos.y;
switch( lastaction) {
case MOVE: moves--; break;
case STOREMOVE: moves--; break;
case PUSH: moves--; pushes--; break;
case UNSAVE: moves--; pushes--; savepack++; break;
case SAVE: moves--; pushes--; savepack--; break;
case STOREPUSH: moves--; pushes--; break;
}
dispmoves(); disppushes(); dispsave();
mapchar( map[ppos.x][ppos.y], ppos.x, ppos.y);
mapchar( map[last_p1.x][last_p1.y], last_p1.x, last_p1.y);
mapchar( map[last_p2.x][last_p2.y], last_p2.x, last_p2.y);
move( MAXROW+1, 0);
refresh();
}
tmpsave() {
register short i, j;
for( i = 0; i < rows; i++) for( j = 0; j < cols; j++)
tmp_map[i][j] = map[i][j];
tmp_pushes = pushes;
tmp_moves = moves;
tmp_savepack = savepack;
tmp_ppos.x = ppos.x; tmp_ppos.y = ppos.y;
}
tmpreset() {
register short i, j;
for( i = 0; i < rows; i++) for( j = 0; j < cols; j++)
map[i][j] = tmp_map[i][j];
pushes = tmp_pushes;
moves = tmp_moves;
savepack = tmp_savepack;
ppos.x = tmp_ppos.x; ppos.y = tmp_ppos.y;
}
short readscreen() {
FILE *screen;
short j, c, f, ret = 0;
if( (screen = fopen( "soklevls.dat", "r")) == NULL)
ret = E_FOPENSCREEN;
else {
if(level>1) {
for(f=1;f<level;f++) {
while((c=getc(screen))!=12 && c!=EOF) ;
getc(screen); /* get the \n after */
}
}
packets = savepack = rows = j = cols = 0;
ppos.x = -1; ppos.y = -1;
while( (ret == 0) && ((c = getc( screen)) != 12) && c!=EOF) {
if( c == '\n') {
map[rows++][j] = '\0';
if( rows > MAXROW)
ret = E_TOMUCHROWS;
else {
if( j > cols) cols = j;
j = 0;
}
}
else if( (c == player.obj_intern) || (c == playerstore.obj_intern)) {
if( ppos.x != -1)
ret = E_PLAYPOS1;
else {
ppos.x = rows; ppos.y = j;
map[rows][j++] = c;
if( j > MAXCOL) ret = E_TOMUCHCOLS;
}
}
else if( (c == save.obj_intern) || (c == packet.obj_intern) ||
(c == wall.obj_intern) || (c == store.obj_intern) ||
(c == ground.obj_intern)) {
if( c == save.obj_intern) { savepack++; packets++; }
if( c == packet.obj_intern) packets++;
map[rows][j++] = c;
if( j > MAXCOL) ret = E_TOMUCHCOLS;
}
else ret = E_ILLCHAR;
}
fclose( screen);
if( (ret == 0) && (ppos.x == -1)) ret = E_PLAYPOS2;
}
return( ret);
}
showscreen() {
register short i, j;
clear();
for( i = 0; i < rows; i++)
for( j = 0; map[i][j] != '\0'; j++)
mapchar( map[i][j], i, j);
move( MAXROW, 0);
printw( "Level: Packets: Saved: Moves: Pushes:");
displevel();
disppackets();
dispsave();
dispmoves();
disppushes();
move( MAXROW+2,0);
refresh();
}
mapchar( c, i, j)
register char c;
register short i, j;
{
OBJECT *obj, *get_obj_adr();
register short offset_row = 0; /*(MAXROW - rows) / 2;*/
register short offset_col = MAXCOL - cols;
obj = get_obj_adr( c);
/* if( obj->invers) standout();*/
move( i + offset_row, 2*j + offset_col);
printw( "%c%c", obj ->obj_display1, obj ->obj_display2);
/* if( obj->invers) standend();*/
}
OBJECT *get_obj_adr( c)
register char c;
{
register OBJECT *ret;
if( c == player.obj_intern) ret = &player;
else if( c == playerstore.obj_intern) ret = &playerstore;
else if( c == store.obj_intern) ret = &store;
else if( c == save.obj_intern) ret = &save;
else if( c == packet.obj_intern) ret = &packet;
else if( c == wall.obj_intern) ret = &wall;
else if( c == ground.obj_intern) ret = &ground;
else ret = &ground;
return( ret);
}
displevel() {
move( MAXROW, 7); printw( "%3d", level);
}
disppackets() {
move( MAXROW, 21); printw( "%3d", packets);
}
dispsave() {
move( MAXROW, 33); printw( "%3d", savepack);
}
dispmoves() {
move( MAXROW, 45); printw( "%5d", moves);
}
disppushes() {
move( MAXROW, 59); printw( "%5d", pushes);
}
static short optrestore = 0,
optlevel = 1;
helpmessage() {
#if 0
move( MAXROW+2, 0);
printw( "Press ? for help.");
refresh();
sleep( 1);
move( MAXROW+2, 0); deleteln();
refresh();
#endif
}
showhelp() {
}
main( argc, argv)
short argc;
char *argv[];
{
short ret;
scorelevel = 0;
moves = pushes = packets = savepack = 0;
if( (prgname = strrchr( argv[0], '/')) == NULL)
prgname = argv[0];
else prgname++;
{
if( (ret = checkcmdline( argc, argv)) == 0) {
level=optlevel;
}
}
ret = gameloop();
errmess( ret);
}
checkcmdline( argc, argv)
short argc;
char *argv[];
{
short ret = 0;
if(argc==2) {
if( (optlevel = atoi(argv[1])) == 0)
ret = E_USAGE;
}
return( ret);
}
gameloop() {
short ret = 0;
/* initscr(); cbreak(); noecho();*/
if( ! optrestore) ret = readscreen();
while( ret == 0) {
if( (ret = play()) == 0) {
level++;
moves = pushes = packets = savepack = 0;
ret = readscreen();
}
}
clear(); refresh();
/* nocbreak(); echo(); endwin();*/
return( ret);
}
char *message[] = {
"illegal error number",
"cannot open screen file",
"more than one player position in screen file",
"illegal char in screen file",
"no player position in screenfile",
"too much rows in screen file",
"too much columns in screenfile",
"quit the game",
NULL, /* errmessage deleted */
"cannot get your username",
"cannot open savefile",
"error writing to savefile",
"cannot stat savefile",
"error reading savefile",
"cannot restore, your savefile has been altered",
"game saved",
"too much users in score table",
"cannot open score file",
"error reading scorefile",
"error writing scorefile",
"illegal command line syntax",
"illegal password",
"level number too big in command line",
"only superuser is allowed to make a new score table",
"cannot find file to restore"
};
errmess( ret)
register short ret;
{
if( ret != E_ENDGAME) {
fprintf( stderr, "%s: ", prgname);
switch( ret) {
case E_FOPENSCREEN: case E_PLAYPOS1: case E_ILLCHAR:
case E_PLAYPOS2: case E_TOMUCHROWS: case E_TOMUCHCOLS:
case E_ENDGAME: case E_NOUSER:
case E_FOPENSAVE: case E_WRITESAVE: case E_STATSAVE:
case E_READSAVE: case E_ALTERSAVE: case E_SAVED:
case E_TOMUCHSE: case E_FOPENSCORE: case E_READSCORE:
case E_WRITESCORE: case E_USAGE: case E_ILLPASSWORD:
case E_LEVELTOOHIGH: case E_NOSUPER: case E_NOSAVEFILE:
fprintf( stderr, "%s\n", message[ret]);
break;
default: fprintf( stderr, "%s\n", message[0]);
break;
}
if( ret == E_USAGE) usage();
}
}
usage() {
fprintf( stderr, "Usage: %s [start_level]", prgname);
}

BIN
Sokoban/sokoban.com Normal file

Binary file not shown.

39
Sokoban/sokoban.hlp Normal file
View File

@ -0,0 +1,39 @@
S O K O B A N
The problem is to push packets to saving positions by moving around
and pushing only one packet at a time if possible.
Available Commands are:
h: move/push left H: run/push left ^H: run left to object
l: move/push right L: run/push right ^L: run right to object
j: move/push down J: run/push down ^J: run down to object
k: move/push up K: run/push up ^K: run up to object
u: undo last move/push U: undo all
c: temporary save ^U: reset to temporary save
^R: Refresh screen
q: quit s: save the game ?: this help screen
+= (DO NOT CHANGE OR DELETE THIS LINE)
Characters on screen are:
@@ player ++ player on saving position
.. saving position for packet $$ packets
** saved packet ## wall
As you could see you can make a temporary save. This is useful if you think
that all the moves/pushes you have made are correct, but you don't know how
to go on. In this case you can temporary save (using the c command). If you
then get stucked you need not undo all (using U), you can reset to you
temporary save.
If you have restored a saved game, a temporary save is automatically made
at the start.
== (DO NOT CHANGE THIS LINE)