The following warnings occurred:
Warning [2] count(): Parameter must be an array or an object that implements Countable - Line: 795 - File: showthread.php PHP 7.4.33 (FreeBSD)
File Line Function
/showthread.php 795 errorHandler->error





Post Reply 
1 Utility for Games
01-25-2014, 06:46 PM (This post was last modified: 01-26-2014 02:13 AM by patrice.)
Post: #1
1 Utility for Games
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.

Patrice
“Everything should be made as simple as possible, but no simpler.” Albert Einstein
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
1 Utility for Games - patrice - 01-25-2014 06:46 PM
RE: 1 Utility for Games - patrice - 01-27-2014, 07:50 AM
RE: 1 Utility for Games - Han - 03-11-2014, 03:18 PM
RE: 1 Utility for Games - patrice - 03-11-2014, 06:42 PM
RE: 1 Utility for Games - Han - 03-11-2014, 07:43 PM
RE: 1 Utility for Games - ArielPalazzesi - 01-27-2014, 11:25 PM
RE: 1 Utility for Games - patrice - 03-11-2014, 01:04 PM
RE: 1 Utility for Games - patrice - 03-11-2014, 08:42 PM



User(s) browsing this thread: 1 Guest(s)