1 Utility for Games

+- HP Forums (http://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: HP Prime Software Library (/forum-15.html)
+--- Thread: 1 Utility for Games (/thread-516.html)



1 Utility for Games - patrice - Yesterday 12:46 PM

This utility is aimed to games with levels, but can have other usages.
The goal is to save space in source code.
Usually in games with levels, there is a map per level. It is common to describe the levels as a matrix which is not space efficient in source code. Encoding the map in a string and using the RLE simple minded compression can do dramatic savings.

String codes
! can be used for end of code (last char in string)
$ is for a new line
. is the default value (background), usually it is 0 in the matrix
letters are used to describe the diff parts of the map

Exemple with ArielPalazzesi's Sokoban
$ encode a new line in matrix
. encode 0 the background
w encode 1 the Walls
c encode 2 a Cube
d encode 3 a Destination
s encode 4 Sokoban (the pusher)

First is a matrix to string conversion and reverse
Code:
EXPORT m2s(Mt)
BEGIN
LOCAL Row, Col, Sz, Tmp;
Tmp:= ""; Sz:= SIZE(Mt);
FOR Row FROM 1 TO Sz(1) DO
  FOR Col FROM 1 TO Sz(2) DO
    Tmp:= Tmp+ MID(".wcds",Mt(Row,Col)+1,1);
  END;
  Tmp:= Tmp+ "$";
END;
RETURN Tmp;
END;

EXPORT s2m(Rows, Cols, St)
BEGIN
LOCAL Row, Col, Ptr; Tmp;
Row:= 1; Col:= 1;
Tmp:= MAKEMAT(0,Rows,Cols);
FOR Ptr FROM 1 TO DIM(St) DO
  IF MID(St, Ptr, 1) == "$" THEN
    Row:= Row+1; Col:= 1;
  ELSE
    Tmp(Row,Col):= INSTRING(".wcds", MID(St, Ptr, 1))-1;
    Col:= Col+ 1;
  END;
END;
END;

Code:
matriz := [ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,4,0,1,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,0,2,2,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,0,0,2,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,3,3,3,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ];
Convert to
Code:
St:=m2s(matriz);
"...................$...................$...................$........wwww.......$​......wwws.ww......$......w.cc..w......$......w..c..w......$......w.....w......$​......www..ww......$........w...w......$........wdddw......$........wwwww......$​...................$...................$...................$"
and since the matrix is already initialized to the background value, they are not needed at the end of line.
Code:
"$$$........wwww$......wwws.ww$......w.cc..w$......w..c..w$......w.....w$......ww​w..ww$........w...w$........wdddw$........wwwww$$$$"
and decoding is done by
Code:
St:="$$$........wwww$......wwws.ww$......w.cc..w$......w..c..w$......w.....w$......ww​w..ww$........w...w$........wdddw$........wwwww$$$$";
matriz:= s2m(15,20,St);

And with the RLE compression on fly
Code:
NTOS(Cnt)
BEGIN
  LOCAL Tmp;
  Tmp:= MID("0123456789", 1+ Cnt MOD 10, 1);
  IF Cnt > 9 THEN
    Tmp:= NTOS(IP(Cnt/10))+Tmp;
  END;
  RETURN Tmp;
END;

EXPORT RLEEnc (Mt) // RLE encodeur
BEGIN
  LOCAL Row, Col, Cod, Cnt, Tmp, Sz;
  Tmp:= ""; Sz:=SIZE(Mt);
  FOR Row FROM 1 TO Sz(1) DO
    Cnt:= 1; Cod:= Mt(Row,1);
    FOR Col FROM 2 TO Sz(2) DO
      IF Cod == Mt(Row,Col) THEN
        Cnt:= Cnt+1;
      ELSE
        IF Cnt <> 1 THEN Tmp:= Tmp+ NTOS(Cnt); END;
        Tmp:= Tmp+ MID(".wcds",Cod+1,1);
        Cnt:= 1; Cod:= Mt(Row,Col);
      END;
    END;
    IF Cod <> 0 THEN
      IF Cnt <> 1 THEN Tmp:= Tmp+ NTOS(Cnt); END;
      Tmp:= Tmp+ MID(".wcds",Cod+1,1);
    END;
    Tmp:= Tmp+ "$";
  END;
  Tmp(SIZE(Tmp)):= "!";
  RETURN Tmp;
END;

EXPORT RLEDec (Rows, Cols, RLE) // RLE décodeur
BEGIN
  LOCAL Row, Col, Ptr, Cnt, Cod, 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;
      DEFAULT
      Cod:= INSTRING(".wcds", MID(RLE, Ptr, 1));
      FOR Col FROM Col TO Col+MAX(1, Cnt)-1 DO Tmp(Row,Col):=Cod- 1; END; Cnt:= 0;
    END;
  END;
  RETURN Tmp;
END;
gives
Code:
St:=RLEEnc(matriz);
"$$$9b4w$7b3wsb2w$7bwb2c2bw$7bw2bc2bw$7bw5bw$7b3w2b2w$9bw3bw$9bw3dw$9b5w$$$!"
// And back to matrix
matriz:= RLEDec(15,20,St);
Replace ".wcds" with your own set of values in the functions
Nota: numbers are reserved for the RLE compression

RLE compression is simple enough that one can encode a map by hand.