Sokoban game for HP Prime

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: HP Prime Software Library (/forum-15.html)
+--- Thread: Sokoban game for HP Prime (/thread-319.html)



Sokoban game for HP Prime - ArielPalazzesi - 01-04-2014 05:58 AM

Sokoban game for HP Prime

Hello!
I'm still learning a little bit about the commands and possibilities of this excellent machine.

I started working on developing a version of the game Sokoban. Using tiles of 16x16 bits and I'm using the touch screen to control the movements of "pusher".

[Image: Captura+de+pantalla+de+2014-01-03+12%253A18%253A53.png]

I've already finished programming the graphics and movement routines. I need to optimize the compression / decompression of maps and details of the game (score, help, etc).

I made one (the first one!) video of the game:





The video shows how the game works. It is not a particular level, but a sandbox created just to do some testing.

I try finish in a few days.

Regards

PD: Sorry for my bad English language management. My native language is Spanish, and it showsWink
----------------------------
EDIT 14/01/14: Download latest release: ([url=http://www.hpmuseum.org/forum/attachment.php?aid=170[/url])


RE: Sokoban game for HP Prime - patrice - 01-05-2014 04:11 AM

About compression, you can use a simple encoding as commonly used in the game of life
Here is a decoding routine
Code:
RLEMap (Rows, Cols,RLE)
BEGIN
LOCAL Row, Col, Ptr, Cnt, Tmp;
Row:= 1; Col:= 1; Cnt:= 0;
Tmp:= MAKEMAT(0,Rows,Cols);
FOR Ptr FROM 1 TO DIM(RLE) DO
  CASE
  IF INSTRING("0123456789", MID(RLE, Ptr, 1)) <> 0 THEN Cnt:= Cnt*10+EXPR(MID(RLE, Ptr, 1)); END;
  IF MID(RLE, Ptr, 1) == "$" THEN Row:= Row+MAX(1, Cnt); Col:= 1; Cnt:= 0; END;
  IF INSTRING("b.", MID(RLE, Ptr, 1)) <> 0 THEN Col:= Col+MAX(1, Cnt); Cnt:= 0; END;
  IF INSTRING("w", MID(RLE, Ptr, 1)) <> 0 THEN // Wall
    FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO Tmp(Row,Col):=1; END; Cnt:= 0; END;
  IF INSTRING("c", MID(RLE, Ptr, 1)) <> 0 THEN // Cube
    FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO Tmp(Row,Col):=2; END; Cnt:= 0; END;
  IF INSTRING("d", MID(RLE, Ptr, 1)) <> 0 THEN // Destination
    FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO Tmp(Row,Col):=3; END; Cnt:= 0; END;
  IF INSTRING("s", MID(RLE, Ptr, 1)) <> 0 THEN // Sokoban
    FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO Tmp(Row,Col):=4; END; Cnt:= 0; END;
   END;
END;
RETURN Tmp;
END;
and the encoding for the first level
Code:
"$$$5b5w$5bw3bw$5bwc2bw$3b3w2bc2w$3bw2bcbcbw$b3wbwb2wbw3b7w$bw3bwb2wb5w2b2dw$bwbc​6bs6b2dw$b5wb3wbwb2w2b2dw$6bw5b9w$5b7w!"
The coding is :
$ : new line
! : End (optional)
b : Background (your 0)
w : Wall (your1)
c : Cube (your 3)
s : Sokoban (your 4)
and numeric is the repeat factor for next letter

Routine and level untested, but you get the idea

By the way, are you sure there is a Cube missing in level 1 ?


RE: Sokoban game for HP Prime - patrice - 01-05-2014 10:29 AM

Here is a little rewrite of your code for Moves and Pushes in the 4 directions.
Code:
local DX, DY;
...
        IF xmouse<80 AND ymouse>60 AND ymouse<180 THEN DY:=0; DX:=-1; END;
        IF xmouse>240 AND ymouse>60 AND ymouse<180 THEN DY:=0; DX:=1; END;
        IF xmouse>80 AND xmouse<240 AND ymouse<60 THEN DY:=-1; DX:=0; END;
        IF xmouse>80 AND xmouse<240 AND ymouse>180 THEN DY:=1; DX:=0; END;

        CASE
          IF matriz [YYP+1+DY, XXP+1+DX] == 0 OR matriz [YYP+1+DY, XXP+1+DX] == 3 THEN
            IF matriz [YYP+1,XXP+1] == 0 THEN BLIT_P(G5,XXP*16,YYP*16); END;
            IF matriz [YYP+1,XXP+1] == 3 THEN BLIT_P(G3,XXP*16,YYP*16); END;
            YYP := YYP+DY; XXP := XXP+DX;
            BLIT_P(G4,XXP*16,YYP*16);
            MOVI := MOVI + 1;
          END; //-----------------------------------
          IF ((matriz [YYP+1+DY,XXP+1+DX]==2) OR (matriz [YYP+1+DY,XXP+1+DX]==5)) AND ((matriz [YYP+1+2*DY,XXP+1+2*DX]==0) OR (matriz [YYP+1+2*DY,XXP+1+2*DX]==3)) THEN
            IF matriz [YYP+1,XXP+1] == 0 THEN BLIT_P(G5,XXP*16,YYP*16); END;
            IF matriz [YYP+1,XXP+1] == 3 THEN BLIT_P(G3,XXP*16,YYP*16); END;
            YYP := YYP+DY; XXP := XXP+DX;
            BLIT_P(G4,XXP*16,YYP*16);
            BLIT_P(G2,(XXP+DX)*16,(YYP+DY)*16);
            IF (matriz [YYP+1,XXP+1]==2) THEN matriz [YYP+1,XXP+1] := 0; ELSE matriz [YYP+1,XXP+1] := 3; END;
            IF (matriz [YYP+1+DY,XXP+1+DX]==0) THEN matriz [YYP+1+DY,XXP+1+DX] := 2; ELSE matriz [YYP+1+DY,XXP+1+DX] := 5; END;
            MOVI := MOVI + 1;
            PUSH := PUSH + 1;
          END; //-----------------------------------
        END;
Since Moves and Pushes are the same in each directions, this code is doing the trick without duplicating the code. It save about 20K in source code.


RE: Sokoban game for HP Prime - patrice - 03-10-2014 12:15 AM

Hi Ariel,
Here are my changes:
Levels are compressed with RLE: saves 40K for 40 levels
removed duplicated code for moves: save about 20K
added keyboard moves


RE: Sokoban game for HP Prime - patrice - 03-10-2014 01:24 PM

I have 1 more change to allow Esc to abort the game.

Code:
          IF TYPE(Ky) == 0 THEN
            IF Ky == 2 THEN DY:=-1; DX:=0; END;
            IF Ky == 7 THEN DY:=0; DX:=-1; END;
            IF Ky == 8 THEN DY:=0; DX:=1; END;
            IF Ky ==12 THEN DY:=1; DX:=0; END;
            IF Ky ==4 THEN abortgame(); END;
          END;



RE: Sokoban game for HP Prime - patrice - 03-14-2014 06:56 PM

Hi Ariel,
After the last review of your code, I have an advice for you.
When programming big pieces of code it is usually easier to put only one functionality in a subroutine, and only the top level routines put together every thing.
Example in loadsubnivel(), it is called only once by the top level routine. Making it only loading the level and nothing else make it easier to remember and to change. drawscreen() have some side effects that complicate changes.
Code:
    IF GAMEOVER == 0 THEN
      loadsubnivel();
      drawscreen();
      RECT_P(G0,20,223,300,238,#000000,#FFFFFF);
      TEXTOUT_P("LEVEL: "+NIVEL+"-"+SUBNIVEL+"  MOVES:           PUSHES:        ",25,224);
      FINAL := 0; MOVI  := 0;PUSH  := 0;
a code like that with a loadsubnivel() only loading the level is considered easier to understand and to change.


RE: Sokoban game for HP Prime - patrice - 05-30-2014 04:28 PM

Update for Rev 6030
This version is only taking advantage of new features of rev 6030
the pragma ensure that the program will compile.
your number format setting will not mess the display.
the .prime file is the source code in text