01-25-2014, 06: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
Convert to
and since the matrix is already initialized to the background value, they are not needed at the end of line.
and decoding is done by
And with the RLE compression on fly
gives
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.
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] ];
Code:
St:=m2s(matriz);
"...................$...................$...................$........wwww.......$......wwws.ww......$......w.cc..w......$......w..c..w......$......w.....w......$......www..ww......$........w...w......$........wdddw......$........wwwww......$...................$...................$...................$"
Code:
"$$$........wwww$......wwws.ww$......w.cc..w$......w..c..w$......w.....w$......www..ww$........w...w$........wdddw$........wwwww$$$$"
Code:
St:="$$$........wwww$......wwws.ww$......w.cc..w$......w..c..w$......w.....w$......www..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;
Code:
St:=RLEEnc(matriz);
"$$$9b4w$7b3wsb2w$7bwb2c2bw$7bw2bc2bw$7bw5bw$7b3w2b2w$9bw3bw$9bw3dw$9b5w$$$!"
// And back to matrix
matriz:= RLEDec(15,20,St);
Nota: numbers are reserved for the RLE compression
RLE compression is simple enough that one can encode a map by hand.