For my Sokoban clone I wrote the simplest level thingymajigg that I could. I've created a binary file that only contains a series of whole numbers. Since the game is grid based the first number is the width of the grid, the second is the total number of tiles in the grid and then it's the actual tiles themselves. And again, the tiles are represented as whole numbers.

I can then read the numbers, number of tiles divided by width gives me the height of the grid. Then just loop through the numbers in the file and create tiles based on that.

1, is a floor tile, 2 is a wall tile, 4 is a target where the player should push the crate, 8 is a crate and 16 is the player starting position. So if I read a 5, that's a 1 + 4 so I know that it's a floor tile with a target on it, 9 = 1 + 8 so that's a floor tile with a crate on it. That was the easiest method I could come up with and it pretty much mirrors the way I handle the logic in the game, because I store all tile information in a single dimensional array and then the player moves I check in the array to see if the tile they want to move to is free etc.

Here is an example of the code I use to read the level.

Type Tile
X
Y
SpriteID
IsWall
Target
Crate
EndType
OpenToRead(1, filename$)
level.Width = ReadInteger(1)
level.Height = ReadInteger(1) / level.Width
For i = 0 To (level.Width * level.Height) - 1
data = ReadByte(1)
t.X = Mod(i, level.Width)
t.Y = i / level.Width
If data = 0
t.IsWall = True
t.SpriteID = CreateSprite(wallImg)
SetSpriteTransparency(t.SpriteID, 0)
SetSpriteVisible(t.SpriteID, False)
ElseIf data && 1 = 1
t.IsWall = False
t.SpriteID = CreateSprite(floorImg)
SetSpriteTransparency(t.SpriteID, 0)
ElseIf data && 2 = 2
t.SpriteID = CreateSprite(wallImg)
SetSpriteTransparency(t.SpriteID, 0)
t.IsWall = True
EndIf
If data && 4 = 4
t.Target = CreateSprite(targetImg)
SetSpriteSize(t.Target, tileWidth#, tileHeight#)
SetSpriteDepth(t.Target, 10)
Inc level.NumberOfTargets
Else
t.Target = 0
EndIf
If data && 8 = 8
t.Crate = CreateSprite(crateImg)
SetSpriteSize(t.Crate, tileWidth#, tileHeight#)
SetSpriteDepth(t.Crate, 9)
Else
t.Crate = 0
EndIf
level.Tiles.Insert(t)
If data && 16 = 16
level.StartX = t.X
level.StartY = t.Y
EndIf
Next i
CloseFile(1)