/*---------------------------------------------------------- Sokoban game in AREXX! --------------------- by Harry EMAIL: harry@jooky.cz NOTE: see documentation at end of this file to find out more ------------------------------------------------------------ */ CALL Init DO WHILE Level ~> MaxLevel CALL Load(Level) CALL Play IF ToDo = 0 THEN Level = Level + 1 ELSE BREAK END /*-*/ CLOSE(win) /* Just to be nice */ EXIT /***************/ Pixel: /* Write character on the specified place */ ARG PixX,PixY,PixC Str = Str || '[' || PixY+1 || ';' || PixX+1 || 'H' || PixC RETURN Place: /* Get the char placed on PlaX, PlaY */ ARG PlaX,PlaY RETURN SUBSTR(P.PlaY,PlaX,1) Putit: /* Put the char PutC on PutX, PutY */ ARG PutX,PutY,PutC P.PutY = OVERLAY(PutC,P.PutY,PutX) RETURN Play: /************ This is the inner body of the game x,y are coordinates of the player, dx,dy is contemplated move m is object found on players place str is buffer for output */ DO FOREVER Str = '' a = ReadCH(win) IF a = '1B'x THEN BREAK IF UPPER(a) = 'N' THEN DO /* Pressed key for Next level */ IF Level < MaxLevel THEN ToDo = 0 END IF UPPER(a) = 'P' THEN DO /* Pressed key for Previous level */ IF Level > 1 THEN DO Level = Level - 2 ToDo = 0 RETURN END END IF a = '9B'x THEN DO in = ReadCH(win) xx = x yy = y dx = (in='43'x)-(in='44'x) dy = (in='42'x)-(in='41'x) x = x + dx y = y + dy m = Place(x,y) SELECT WHEN m = whi THEN NOP WHEN m = tar THEN NOP WHEN m = box THEN DO /* Pushing a box */ px = x + dx py = y + dy p1 = Place(px,py) /* Contents of place beyond the box */ IF p1 = whi THEN DO /* Can I push a box? */ CALL Pixel(px,py,Box) CALL Pixel(x,y,Whi) CALL Putit(px,py,Box) CALL Putit(x,y,Whi) END ELSE IF p1 = Tar THEN DO /* Pushing a box on target? */ CALL Pixel(px,py,Ful) CALL Pixel(x,y,Whi) CALL Putit(px,py,Ful) CALL Putit(x,y,Whi) ToDo = ToDo - 1 /* We finished another box */ END ELSE DO x = xx y = yy END END WHEN m = ful THEN DO /* Pushing a box */ px = x + dx py = y + dy p1 = Place(px,py) /* Contents of place beyond the box */ IF p1 = whi THEN DO /* Can I push a box? */ CALL Pixel(px,py,Box) CALL Pixel(x,y,Tar) CALL Putit(px,py,Box) CALL Putit(x,y,Tar) ToDo = ToDo + 1 /* We released one box */ END ELSE IF p1 = Tar THEN DO /* Pushing a box on another target? */ CALL Pixel(px,py,Ful) CALL Pixel(x,y,Tar) CALL Putit(px,py,Ful) CALL Putit(x,y,Tar) END ELSE DO x = xx y = yy END END OTHERWISE DO x = xx y = yy END END END Str = Str || '[' || y+1 || ';' || x+1 || 'H' /* Player */ WRITECH(win,Str) IF ToDo = 0 THEN BREAK END RETURN Load: /* Load specified level */ ARG LevNum L = LevNum X = XPos.L /* Getting measures */ Y = YPos.L D = NLin.L ToDo = BoxN.L IF outopen = 1 THEN CLOSE(win) /* Close window of old size */ wdx = 8 + FonDX * (LENGTH(Line.L.1) + 2) /* Width - 8 is winborder width */ wdy = 8 + FonDY * (D + 3) /* Height- 8 is winborder width */ wx = (ScrDX - wdx) % 2 /* Centered X */ wy = (ScrDY - wdy) % 2 /* Centered Y */ wt = 'Level :' L IF ~OPEN(win,'RAW:'||wx||'/'||wy||'/'||wdx||'/'||wdy||'/'||wt||'/NOSIZE') THEN EXIT outopen = 1 WriteLN(win,'[>2m') /* This line controls used colors */ /* Some alternative color sets are written here WriteLN(win,'[>1m') WriteLN(win,'[>2m') WriteLN(win,'[>3m') WriteLN(win,'[>4m') WriteLN(win,'[>5m') WriteLN(win,'[>6m') WriteLN(win,'[>7m') */ WriteLN(win,'') DO i = 1 TO D P.i = Line.L.i WriteLN(win,' ' || P.i) END WRITECH(win,'['||y+1||';'||x+1||'H') /* Place the player */ RETURN Init: /** Miscelaneous settings **/ ScrDX = 720 /* Supposed screen sizes (for centering) */ ScrDY = 400 FonDX = 8 /* Sizes of used font */ FonDY = 8 Box = 'O' /* Character representing box */ Whi = ' ' /* Free place */ Tar = '+' /* Where to place the box */ Ful = '0' /* Target with box on it */ Level = 0 /* Starting level number */ /** Level parameters **/ XPos.0 = 16 /* Position X of player */ XPos.1 = 2 XPos.2 = 5 XPos.3 = 11 XPos.4 = 2 YPos.0 = 8 /* Position Y of player */ YPos.1 = 3 YPos.2 = 3 YPos.3 = 7 YPos.4 = 3 NLin.0 = 9 /* Number of lines of level */ NLin.1 = 5 NLin.2 = 7 NLin.3 = 11 NLin.4 = 8 BoxN.0 = 0 /* How much targets to fill */ BoxN.1 = 3 BoxN.2 = 6 BoxN.3 = 4 BoxN.4 = 0 Line.0.1 = '.--------------------.' Line.0.2 = '|ARexx SOKOBAN |' Line.0.3 = '| |' Line.0.4 = '| N - next level |' Line.0.5 = '| P - previous level |' Line.0.6 = '| ESC end game |' Line.0.7 = '| |' Line.0.8 = '| Press any key |' Line.0.9 = "`--------------------'" Line.1.1 = '/##########\' Line.1.2 = '# +#' Line.1.3 = '# OOO +#' Line.1.4 = '# +#' Line.1.5 = '\##########/' Line.2.1 = '.#######.' Line.2.2 = '## + ##' Line.2.3 = '# +O O+ #' Line.2.4 = '# O#O #' Line.2.5 = '# +O O+ #' Line.2.6 = '## + ##' Line.2.7 = ' ####### ' Line.3.1 = '/############' Line.3.2 = '#H ++++ #' Line.3.3 = '# ## # #' Line.3.4 = '# ######O##' Line.3.5 = '## ( ) # ' Line.3.6 = ' # ##### ### ' Line.3.7 = ' # # # ' Line.3.8 = ' # #### O # ' Line.3.9 = ' # O O# # ' Line.3.10 = ' ####### # ' Line.3.11 = ' ##### ' Line.4.1 = '.--------------------.' Line.4.2 = '|Congratulations! |' Line.4.3 = '| |' Line.4.4 = '|You finished all |' Line.4.5 = '|levels. |' Line.4.6 = '| |' Line.4.7 = '|Press a key to quit.|' Line.4.8 = "`--------------------'" MaxLevel = 4 RETURN /* General information: ------------------- Configuration can be made via setting of some variables at the start of 'Init:' procedure. Used colors can be changed on line 171. Rules of level building: ----------------------- Characters defining box, target and target with box are defined on the beginning of the function Init:. Every other character is treated as a wall. Number of targets to be filled is written in field BoxN.xxx. If you set BoxN to zero, the level will be finished after first pressing of a key (but ESC or P take their action). The map itself should be made so that player cannot get out of map since no extra check takes place. Level width will be taken from the first line, so do not neglect to write all spaces for the level to be rectangular. Implementation: -------------- The map changes are chained in string buffer Str written presently at the end of iteration. */