C2G

Revision as of 19:05, 7 May 2021 by G-lander (talk | contribs) (→‎Advanced scripting: Rename highspeed to speed since it's very weird to reference wrong variable names due to lax variable name rules)

C2G files are a file extension used by Chip's Challenge 2. Despite the C2G extension, C2G files are plain text and can be edited with any text editor.

While individual levels are stored in C2M files, C2G files arrange these levels in levelsets. C2G files can also be used to specify music tracks, text between levels, and several forms of advanced scripting.

The official set does not use any advanced C2G features, nor did Chuck Sommerville provide any documentation; there are several features that have not yet been discovered by the community.

Basic usage

Set name

The first line of the C2G file must absolutely specify the set's name. Such lines must begin with the "game" directive, followed by the set's name in quotes. For example:

game "Levelset Name"

In the above example, the levelset will be known "Levelset Name" in Chip's Challenge 2's "Load Level Set" window.

Levels

Most of the C2G file consists of loading individual C2M files. This is done using the "map" directive, followed by the file name/path in quotes. For example:

map "ShortLevel.c2m"

In the example above, the game engine will load the level stored in the file ShortLevel.c2m in the same directory as the C2G file.

It is also possible to specify custom directories for C2M files.

map "1-20\VeryLongLevel.c2m"

In the example above, the game will load the level stored in the file VeryLongLevel.c2m in the 1-20 subfolder of the folder where the C2G file is stored.

map "..\crazy-levels\OrdinaryLevel.c2m"

In the example above, the game will go back one directory, enter the crazy-levels folder and load the level stored in the file OrdinaryLevel.c2m

Music

If music is to be played during a specific level, it must be specified in the C2G file; otherwise there will be silence. Only files in MP3 format are supported.

Music is using the "music" directive; followed by the file name/path in quotes, and then, on the same line, the level file. Advanced paths can be specified, like with level files.

After the track is finished, the game will fall silent; this can be avoided by using the + symbol before the path (but inside the quotes). For example:

music "+..\music\DeletingLife.mp3" map "21-40\IntenseDodging.c2m"

In the example above, the game will load the level in the file IntenseDodging.c2m in the 21-40 subfolder. It will also go back one directory, enter the music folder, and play the track DeletingLife.mp3. After playback has finished, it will start playing again.

Comments

A semicolon (;) can be placed at the end of any line in a C2G file. Any text after the semicolon will be ignored by the engine. This can allow the designer to write notes in the C2G file. For example:

music "+..\music\DeletingLife.mp3" map "21-40\IntenseDodging.c2m" ;   Intense music for an intense level

In the example above, the text "Intense music for an intense level" will be ignored by the game; the level and music specified will be loaded normally.

Text

C2G files make it possible to put text, between levels, as well as at the beginning and end of the set. This is done using the "script" directive, followed by up to 10 lines of text. All text must be between quotes, and lines may not be longer than 20 characters (excluding the quotes). It is possible to put blank lines by simply putting a space inside the quotes. For example:

script
"The following level"
"uses some really"
"clever tricks and" ;   some are also evil
"is guaranteed"
"to be enjoyable"
" "
"Have fun!"
map "AwesomeLevel.c2m"

In the example above, the text will be displayed in-game like this:

THE FOLLOWING LEVEL
USES SOME REALLY
CLEVER TRICKS AND
IS GUARANTEED
TO BE ENJOYABLE
 
HAVE FUN!

The text "some are also evil" is a comment and will not be displayed. After the text is displayed, the game will then load the level in the file AwesomeLevel.c2m

Advanced scripting

In addition to the features described above, C2G files can support some additional keywords that provide extra features. Note that any information beyond this point may be incomplete or inaccurate.

Syntax

The syntax of the .c2m file appears to be a mix of Reverse Polish Notation expressions and simple statements. For example, to set the global "flags" variable to (reg1 + 42) * 3, you would write:

 reg1 42 + 3 * flags =

Other statements, such as "map" or "music" take a parameter after the keyword:

 map "somemap.c2m"

In addition, variables can be formatted into strings in script sections by placing the variable after a string with a printf-style format specifier:

 "flags = %ld" flags

Score

The following line, when inserted in a "script"

"%ld" score

will print the player's current total score for the set.

Permanently change directory

By default, C2G files will look for files to be loaded in the same directory as the C2G file itself. This can be changed by the

chdir

directive. This will apply for any future files to be loaded (although custom paths can still be specified, like described above).

Keeping items across levels

C2G files can make it possible to allow the player to keep items and keys across levels.

In order to do this, the C2G script needs this line at the beginning of the file (after the set name):

ktools flags | flags =

This allows the player to keep tools (and keys) into the next level, instead of the key and tool inventories being reset like normal. With this flag set, the player can set up his inventories in one level and keep them into the next.

Alternatively, the set designer can use the C2G script to preset the player's inventories explicitly. This can be done with the following code, placed before calling the level's "map":

<#> keys =    ; to preset the key inventory
<#> tools =   ; to preset the tools inventory

For each inventory, "<#>" is a 4-byte number in which each byte represents a different inventory slot. Its value can be calculated as follows:

  (tool 1 code OR red key count)
+ (tool 2 code OR blue key count) * 256
+ (tool 3 code OR yellow key count) * 65,536
+ (tool 4 code OR green key count) * 16,777,216

Or if you know hexadecimal, just write it out as a hex integer in little-endian order, then convert to decimal - CC2 does not read hex literals.

Here are the number codes for items:

For example, a key inventory with 1 yellow key and 2 red keys can be set with

65538 keys =

and a tool inventory with flippers in slot 1 and a yellow teleport in slot 2 can be set with

2564 tools =

Note that tool codes > 16 will be reduced to a value <= 16, and key counts > 9 will be reduced to 9. These limits do not apply when either inventory is carried over from the previous level.

Timed levelset

C2G files make it possible to set a time limit for the entire levelset, rather than individual levels. In order to do this, the following code must be added to the beginning of the file, after the "game" directive:

ktime flags | flags =

Before the first level, this code will also be required:

<#> tleft =

Replace "<#>" with the desired time limit for the set. This will ignore any time limits set for individual levels. Time limits will be carried over from one level to the next, and restarting the level does not reset the time limit. Time bonuses and time penalties can still be used. After the time limit reaches 0, or if a level is skipped, all future levels will be untimed.

Exit choices

If a level has several exits, C2G scripting can be used to send the player to different levels depending on what exit is entered.

In order to do this, each level must be given a label starting with a pound (#) character. For example:

#bonuslevel
script
"Congratulations!"
"You have reached"
"the secret level!"
map "BonusLevel.c2m"

In the example above, the level BonusLevel.c2m as well as the preceding text are given the label "bonuslevel".

Exits are numbered in reading order, starting at 1; there does not appear to be any limit. In order to use the feature, after calling the "map" of the level containing the exits, a line similar to this will be required:

 <#> exit == do goto #label

Replace <#> with the exit number, and #label with the label name (including the #). For example:

map "ChooseYourFuture.c2m"
1 exit == do goto #end
2 exit == do goto #secret

#secret
map "SuperSecretFinalLevel.c2m"

#end
script
"This is the end."

In the example above, the game will load the level stored in the file ChooseYourFuture.c2m; if the player exits using the first exit in reading order, the game will then display the THIS IS THE END. message. If the player exits using the second exit, however, the game will load the level in the file SuperSecretFinalLevel.c2m instead, and the THIS IS THE END message will be displayed after the level has been solved.

If there are several players in the level, the exit used by the last player to finish the level will be the one used by the C2G script. If an invalid label is called, or no label is assigned for the exit that was used, the game will continue to work through the C2G file as it would normally.

Gender choices

C2G scripting can be used to send the player to different levels depending on whether they finished the level as Chip or Melinda. This will require setting up labels, similar to exit checkpoints.

After calling the appropriate level's "map", the following lines will be required:

male gender == do goto <#label>
female gender == do goto <#label>

Replace <#label> with the appropriate labels. The "male" line is for Chip, and the "female" line for Melinda; the order of the two lines can be changed.

If there are several players in the level, the gender of the last one to finish the level will be the one used by the C2G script. If an invalid label is called, or no line is specified for a specific gender, the game will continue to work through the C2G file as it would normally.

Goto

Goto can also be used in absence of a gender or exit check. For example:

map "NormalProgression.c2m"
#loop
map "DejaVu.c2m"
map "StuckInALoop.c2m"
goto #loop

In the example above, completing StuckInALoop.c2m will always take you back by one level to DejaVu.c2m.

Fake level numbers

C2G scripting can be used to assign specific numbers to levels. To do this, the following line must be added before calling the level's "map":

<#> level =

Replace <#> with the desired level number. This makes it possible to skip (nonexistent) levels and go backwards (for example, going from level 2 to 5 to 248 to 125). Any number can be specified, including four digit numbers (although this will be displayed in-game as 999) and 0. It is also possible to have several levels with the same number.

It is not required to specify numbers for all levels; if the line is absent, or an invalid value (such as a string of number) is given, the game will simply add 1 to the previous level's number. For example:

game "Jumping Around"
2 level =
map "Wheres1.c2m"
0 level =
map "Backwards.c2m"
8 level =
map "Jumping.c2m"
map "Normal.c2m"

In the example above, Normal.c2m will be level 9.

Speed

C2G scripting can be used to modify the speed at which the game is played. To do this, the following line must be added before calling the map:

 1 speed =

The number determines the speed, where 1 is normal speed; the upper limit is unknown. This flag will apply for all future levels; in order to restore normal speed, the flag must be called again before a later level.

Blocking flags

C2G scripting can be used to prevent bonus flags from being picked up. This will apply to the entire set, rather than individual levels.

The following line must be added at the beginning of the file (after the set's name):

 no_bonus flags | flags =

With this flag set, bonus flags become acting floor to Chip, Melinda, their mirrors and rovers. It has no impact on other monsters and blocks that would not normally pick up the flags.

Editor

The following line

edit

will open the game's built-in editor.

Automatic replays

The following lines

1 level =
50 speed = continue replay | silent | flags =

added to the beginning of the file (after the set name) will cause the game to automatically replay the recorded solutions for all levels in the set, in extremely high speed. This can be used to quickly verify that all levels are solvable and have recorded replays.

Comments box

Certain C2G scripts, notably ktools and speed can be placed inside a specific level file's comments field, and will apply to the level itself. To do this, the comments field must contain the following line:

[COM]

followed, on subsequent lines, by the C2G parameters.

Reference

The following is a list of all keywords and tokens recognized by the c2g parser. The function of some keywords in here is unknown, and some formerly did something but are now just gibberish to the engine (NO_L_DOORS for example). Note that keywords are case-insensitive.

Token Type Syntax Description
MUSIC directive
music "<filename>"
Specifies a music file to play for the next script element.
GOTO directive
goto #<label>
Move script execution to the specified #label
DO directive
<conditional> do ...
If the preceding condition is true, do the following command. Example:
2 exit == do goto #secret
==
<=
>=
!=
<
>
binary operator
<expressions...> <operator>
Pop two values from the preceding expressions and compare them with the specified operator, then push the result. The operators have the same meanings as in C.
= assignment
<expression> <variable> =
Assign the specified value from the preceding expression to <variable>.
LEVEL variable
level
Contains the current level number. The first level is 1.
GENDER variable
gender
Contains the player's current gender (male or female).
EXIT variable
exit
Contains the most recently used exit (see above).
ENTER variable
enter
Use is currently unknown.
SCORE variable
score
Contains the current score for the levelset.
BONUS unknown Appears to be unused.
MENU variable
menu
Use is currently unknown.
CHIPS unknown Appears to be unused.
START unknown Appears to be unused.
MALE constant
male
Value: 0x16
"male" constant for gender variable.
FEMALE constant
female
Value: 0x56
"female" constant for gender variable.
MAP directive
map "<filename>"
Specifies the map file to use for the next level.
SCRIPT directive
script
Begins "script" mode for displaying text (see above).
" string
"..."
"... %<format> ..." <value>
Strings begin and end with a double-quote ("). There does not appear to be any capability for escaping characters. However, formatting can be applied with printf-style format strings (see above).
# label
#<name>
Labels can be jumped to with the "goto" directive. There appears to be some interaction with the end directive, but this is untested.
0..9 integer
1234
Integer literal. Can only be specified in decimal (digits 0-9).
;
//
comment
; comment text
// comment text
Comments are ignored until the end of the current line.
END directive
end
There appears to be some interaction with labels, but this is untested.
RESULT variable
result
Use is currently unknown. Possibly contains the result of arithmetic expressions?
REG1
REG2
REG3
REG4
variable
reg1
reg2
reg3
reg4
Use is currently unknown. Possibly used as scratch registers for more complex expression evaluation?
FLAGS variable
flags
Specifies flags (bitwise OR'ed) for the current gameplay. See sections above for details.
EDIT directive
edit
Start the built-in level editor.
CHAIN directive
chain "<filename>"
Use is currently unknown.
LINE variable
line
Use is currently unknown.
CHDIR directive
chdir "<path>"
Change the game's current working directory to <path>.
SCREEN unknown Appears to be unused.
*
/
+
-
&&
&
||
|
%
^
binary operator
<expressions...> <operator>
Pop two values from the preceding expressions and evaluate them with the specified operator, then push the result. The operators have the same meanings as in C.
REPLAY constant
replay
Value: 0x2
When set in flags, automatically replay recorded solutions.
CONTINUE constant
continue
Value: 0x1
When set in flags, automatically continue to the next level.
SILENT constant
silent
Value: 0x4
When set in flags, ?
KTIME constant
ktime
Value: 0x20
When set in flags, keep the time limit across levels.
KTOOLS constant
ktools
Value: 0x10
When set in flags, keep collected tools (items and keys) across levels.
TLEFT variable
tleft
Contains the global time limit when ktime is set in flags.
TOOLS variable
tools
Contains the current tools inventory (see above).
KEYS variable
keys
Contains the current keys inventory (see above).
ART directive
art "..."
Use is currently unknown.
WAV directive
wav "..."
Use is currently unknown.
RAND pseudo-variable
rand
When read, generates a pseudo-random integer.
SPEED variable
speed
Contains the current gameplay speed. 1 = 100% (normal speed).
NO_BONUS constant
no_bonus
Value: 0x40
When set in flags, disables bonus flag pickup (see above for details).
NO_L_DOORS unknown Appears to be unused.
MAIN directive
main
Use is currently unknown. Appears to jump to "playcc2.c2g" from the current levelset or script.
GAME directive
game "<name>"
Sets the name of the current levelset to <name>
DLC directive
dlc "..."
Use is currently unknown.