Project Milestone:


HomeProject ProposalProject Report


Reading level files

The .P2C files are the most basic way that the game encodes levels, more details and visual enhancements can be added in the Hammer editor but these enhancements are not necessary for creating interesting puzzles.
The encoding of the level and it’s structure is crucially important. Images have inherent structural properties, pixels that appear next to each other are often related in value to form coherent images. Similarly the level encoding has to be done in a sensible manner, in order to faithfully represent the structure of the level.

Meta data :

This section contains information like puzzle name, player ID, game version, level size etc.
Out of all this information, level size is an important factor as it can be an important variable for level design.

                        
                            "AppID"		"644"
                            "Version"		"14"
                            "FileID"		"0x0000000000000000"
                            "Timestamp_Created"		"0x000000005F864E8C"
                            "Timestamp_Modified"		"0x000000005F865C98"
                            "CompileTime"		"15.000000"
                            "Coop"		"0"
                            "Title"		"simplest possible puzzle"
                            "Description"		"nothing to see here"
                            "PreviewDirty"		"1"
                            "ChamberSize"		"8 6 4"
                            "Voxels"
                        
                    

Voxel:

This section describes 4 basic properties of the voxels.

                        
                            "Voxels"
                            {
                                "Solid"
                                {
                                    "Z0"
                                    {
                                        "Y6"		"f000000000"
                                        "Y5"		"f000000000"
                                        "Y4"		"f000000000"
                                        "Y3"		"f001100000"
                                        "Y2"		"f001100000"
                                        "Y1"		"f001110000"
                                        "Y0"		"f000000000"
                                    }
                                    ...
                                "Portal0"
                                {
                                    "Z0"
                                    {
                                        "Y6"		"f111110000"
                                        "Y5"		"f111110000"
                                        "Y4"		"f111111111"
                                        "Y3"		"f111111111"
                                        "Y2"		"f000011111"
                                        "Y1"		"f000011111"
                                        "Y0"		"f000111111"
                                    }
                                    ...
                                "Portal1"
                                {
                                    "Z0"
                                    {
                                        "Y6"		"f111110000"
                                        "Y5"		"f111110000"
                                        "Y4"		"f111111111"
                                        "Y3"		"f110111111"
                                        "Y2"		"f000111111"
                                        "Y1"		"f000111111"
                                        "Y0"		"f000111111"
                                    }
                                    ...
                                "Portal2"
                                {
                                    "Z0"
                                    {
                                        "Y6"		"f111110000"
                                        "Y5"		"f111110000"
                                        "Y4"		"f111111111"
                                        "Y3"		"f111111111"
                                        "Y2"		"f000111111"
                                        "Y1"		"f000111111"
                                        "Y0"		"f000111111"
                                    }

                        
                    

Solid describes if the player can walk through this voxel or not.
Portal(0,1,2) describes if a portal can be made on a surface of this voxel.

“Items”:

Describes all the items placed around the level along with the appropriate properties. For a fully featured level generator all of these properties might be necessary but currently for very simple levels we can get away with only considering Index, type, VoxelPos and Angles.

                            
                                "Item"
                                {
                                    "Index"		"0"
                                    "Type"		"ITEM_ENTRY_DOOR"
                                    "Deletable"		"0"
                                    "VoxelPos"		"1 0 0"
                                    "LocalPos"		"0 0 0"
                                    "Angles"		"-90 -90 0"
                                    "ITEM_PROPERTY_DOOR_IS_COOP"		"0"
                                    "Facing"		"0 0 0"
                                    "ConnectionVisiblity"		"0"
                                    "DoorInstanceID"		"2.000000"
                                    "Enabled"		"1"
                                }
                            
                        

“Connections”:

Describes all the connections between different items of the game, so if pressing a button triggers a door then that is stored as a connection.

                        
                            "Connection"
                            {
                                "Sender"		"0"
                                "Receiver"		"1"
                                "Type"		"CONNECTION_BARRIER_ANCHOR_TO_EXTENT"
                            }                    
                        
                    

Structuring the data

If we are just encoding the voxel information that looks as simple as storing a 4 bit greyscale 3D model. To add item information to this each voxel contains a list of different items that are present in it.
The connections between Items is slightly more tricky to represent.

Simple Connection vector

Just provide a separate feature vector containing all the connections.

Add a fourth connection dimension

In this method the level is represented several times:
Once with just the physical geometry and then subsequently ones with each item connection pairing.
Both these approaches could be attempted to see if one works better than the other. The hope with the 4 dimensional approach is that the connection of different items can be linked with their position in space more directly.


Preliminary Datasets

In the previous section we have talked about encoding “simple levels”. This is an attempt to reduce the number of variables that we are working with and to first prove to ourselves that the concept works. This step will be beneficial in helping us determine what direction we want to take with our approach. However, this intermediate step has also been made necessary because of an obstacle that we have encountered. The large dataset of community generated level files that we hoped to be able to use to train this algorithm is in a file format that is not easily readable.
To overcome this problem we will have to create our own set of level data. Our current plan is to hand craft simple levels and then train our algorithm on rotated and reflected versions of these levels. This is a common technique that is used to increase data size where the orientation or the chirality of the end product is irrelevant, this means that for each level we make by hand we get 8 training examples (Levels can’t be reflected over the XY plane nor can they be rotated around x or y axes because gravity is often crucial to the working of the level.)

Handcrafted levels

To increase the size of this dataset we plan to ask the game community and the developers if they can provide us with some P2C files to help train this model. If we can provide a good proof of concept the response may be quite healthy, with this we will be able to significantly increase the latent space ' of our level design potentially leading to more complex and engaging levels.