This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
4rpl:overview [2021/01/11 16:12] – Karsten75 | 4rpl:overview [2025/02/14 14:57] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
< | < | ||
+ | |||
+ | :!: To edit files you will need an editor. Read how to get started with [[creating and editing 4rpl scripts]]. | ||
====== Scripting ====== | ====== Scripting ====== | ||
Line 6: | Line 8: | ||
Scripting in CW4 uses a custom language, **4RPL**. It is stack-based, | Scripting in CW4 uses a custom language, **4RPL**. It is stack-based, | ||
- | 4RPL commands either read data from the //stack// or place data on the // | + | 4RPL commands either read data from the //stack// or place data on the // |
+ | |||
+ | You can place arguments on the stack by typing them, or executing an instruction that will push arguments on to the stack. | ||
+ | |||
+ | <code 4rpl> | ||
+ | 2 4 | ||
+ | </ | ||
- | You can place arguments on the stack by typing them, or executing an instruction that will push arguments on to the stack. For instance, you can type <code 4rpl>2 4 </ | + | and then these two numbers will be pushed onto the stack when your script executes. |
An easy way to familiarize yourself with 4RPL is to use the [[cw4: | An easy way to familiarize yourself with 4RPL is to use the [[cw4: | ||
- | As an illustration, | + | As an illustration, |
<code 4rpl> | <code 4rpl> | ||
- | 2 4 5 add | + | 2 4 + |
- | TraceAllSp | + | TraceAllSP |
</ | </ | ||
- | The code above put 3 numbers on the stack, the `add` command took the 4 and the 5 (last-in, first out) added them and pushed the result (9) back on the stack. [[4rpl: | + | The code above puts 2 numbers on the stack, the '' |
- | {{console_output_1.png}} | + | :!: Note that 4RPL is a // |
Part of 4RPL is the commands that manipulate map objects, such as creeper, terrain and units. Here is a simple script to put some creeper on a specific cell on a map. | Part of 4RPL is the commands that manipulate map objects, such as creeper, terrain and units. Here is a simple script to put some creeper on a specific cell on a map. | ||
Line 29: | Line 37: | ||
</ | </ | ||
- | Run this **once** in the console and then press the pause key to let the game simulation run a few frames. You will see a stack of 100 deep creeper at map coordinate x=12 and z=23((For more information on the game coordinate system and why we use `x` and `z` coordinates, | + | Run this **once** in the console and then unpause |
- | ===== Warp Notation ===== | ||
- | About now is a good time to introduce **warp notation**, a method to improve the readability of 4RPL script. | + | ===== Comments ===== |
- | + | Comments | |
- | An extra and optional <wrap hi> | + | Comments are indicated by the " |
- | + | ||
- | This operator is called | + | |
<code 4rpl> | <code 4rpl> | ||
- | AddCreeper (12 23 100) | + | # This is how we add two of the three numbers |
+ | # that are on the stack | ||
+ | # Below is code # Below is a comment | ||
+ | 2 4 5 add # adds 4 and 5 to get 9 | ||
</ | </ | ||
- | Now one can more clearly see which arguments are intended for the AddCreeper command. | ||
- | ===== Flow Control | + | ===== Warp Notation |
+ | Warp notation is an optional notation that allows the use of parentheses to change the order that things are written. The use of parentheses is called warp notation since it warps, or moves, things around. Parentheses can be added anywhere in 4RPL and will move the command that proceeded the opening parenthesis to the location of the closing parenthesis. This can be useful for making some expressions look more like functions in some other languages | ||
- | sometimes one wants to do something a number of times, that is called a **loop** and an important part of programming. | ||
- | |||
- | Here is a small sample that puts a diagonal line of creeper on a map. | ||
<code 4rpl> | <code 4rpl> | ||
- | GetMapSize ->sizeZ -> | + | 12 23 100 AddCreeper |
- | do(<-sizeX 0) # iterate over every cell in the x-direction | + | AddCreeper(12 23 100) # Does the same thing as the line above. |
- | # starting at zero (first cell) | + | |
- | AddCreeper(I I 50) # if so, plop down some creeper | + | 1 (2 3 +) 4 # |
- | loop | + | 2 3 + 1 4 |
</ | </ | ||
+ | ===== Conditionals ===== | ||
+ | **If** statements in 4RPL consist of an **if**, optional **else** and a closing **endif** instruction. The **if** instruction pops the item from the top of the stack and evaluates it as a boolean (true or false, not 0 or 0). If the item is false, then execution jumps to the **else** or **endif** instruction in the script. | ||
- | fixme after this | + | <code 4rpl> |
- | ---- | + | if ( GetGameUpdateCount 900 >= ) |
- | 4RPL programming is a stack-based language, similar to programming a HP calculator or Forth language programming. If this is not something you have done, read on for a brief introduction to 4RPL and stack-based programming. | + | TraceAllSp(" |
+ | else | ||
+ | | ||
+ | endif | ||
+ | </ | ||
- | An 4RPL instruction either use arguments (data) that is on a " | ||
- | You can place arguments on the stack by typing them, or executing an instruction that will push arguments on to the stack. For instance, you can type <code 4rpl>2 4 </ | ||
- | As an illustration, | + | Note: See [[4rpl:Data Types]] for comparison between dissimilar types and type conversion. |
- | <code 4rpl>2 4 5 add</ | ||
- | | ||
- | Either of the scripts above will read the two most recent arguments on the stack (4 and 5), add them and push the sum on to the stack. After the instruction has completed, there will be two numbers on the stack. The " | ||
- | <code 4rpl>2 9</ | ||
- | <wrap info round > | + | ===== Variables ===== |
- | You can find more commands | + | The stack is not the only place to store information in 4RPL, it is possible to take items from the stack and store them in // |
- | </wrap> | + | |
- | ==== Comments ==== | + | <code 4rpl> |
+ | 3 4 + -> | ||
+ | "3 plus 4 is" <-result TraceAllSP | ||
+ | </ | ||
- | Adding comments makes code easier to understand, and sometimes helps the programmer or other readers to grasp complex pieces of logic. Also, after some time interval, it refreshes one's memory about exactly what a certain piece of code was intended to do. | ||
- | Comments in xRPL can be either a whole line or a partial line. The comment terminates when a line ends. | ||
- | Comments are indicated by the " | + | Note: See [[4rpl:Data Types]] for comparison between dissimilar types and type conversion. |
- | <code 4rpl># This is how we add two of the three numbers | ||
- | # that are on the stack | ||
- | # Below is code # | ||
- | 2 4 5 add # adds 4 and 5 to get 9</ | ||
- | <wrap important> | + | ===== Functions ===== |
+ | 4RPL supports user-defined functions | ||
- | Likewise, note that the most recent item pushed on to the stack will also be the first item to be removed. This is referred to as LIFO (**L**ast **I**n, **F**irst **O**ut) processing. | + | <code 4rpl> |
+ | 4 2 @Function1 Trace # prints " | ||
+ | @Function2 | ||
- | ==== Warp Notation ==== | + | : |
+ | add # adds together 2 items on the stack | ||
+ | 5 add # adds an extra 5 to that | ||
- | An extra and optional <wrap hi> | + | :function2 |
- | + | " | |
- | This operator is called the **warp** | + | |
- | + | ||
- | <code prpl>3 4 add </ | + | |
- | + | ||
- | This means to push 3 to the stack, push 4 to the stack, then to call <wrap round box> | + | |
- | + | ||
- | This means two items on the stack before the operation, and one item on the stack afterwards. | + | |
- | This is all xRPL (or RPL, or Forth...) standard stuff and the primary principle of the language. | + | |
- | + | ||
- | Introducing the Warp operator. | + | |
- | + | ||
- | <code prpl>3 4 add</ | + | |
- | can become | + | |
- | <code prpl>add (3 4)</ | + | |
- | + | ||
- | The open parenthesis <wrap round box> | + | |
- | + | ||
- | Here the warp operator is used to make the code slightly more readable. | + | |
- | <code prpl>3 add(4)</ | + | |
- | Here, the <wrap round box> | + | |
- | + | ||
- | Take a second example: | + | |
- | + | ||
- | <code prpl> | + | |
- | # CurrentCoords obtains the (X, y) location and places it on the stack | + | |
- | # GetCreeper uses the (X,Y) coordinates to look at a cell on a map | + | |
- | # and returns the amount of creeper on that cell | + | |
- | # The " | + | |
- | # other words, creeper exists in a significant amount) and if true | + | |
- | # displays a message in the trace output. | + | |
- | + | ||
- | CurrentCoords GetCreeper 1 gt if | + | |
- | " | + | |
- | endif | + | |
</ | </ | ||
- | The comments in the sample above explains what we're trying to achieve with this code snippet. | + | Read more about functions on the pages for [[4rpl: |
- | It uses the current coordinates, | ||
- | Because of the way the stack works, you have to push two coordinates to the stack first (<wrap round box> | + | ===== Loops ===== |
+ | 4RPL supports both "do/loop" and "while/repeat" | ||
+ | For an example | ||
+ | For an example | ||
- | That's xRPL in a nutshell. | + | \\ |
- | Using **warp notation**, we can make this slightly more readable. | + | ---- |
+ | ===== Working with CPACKs ===== | ||
+ | When a CPACK is imported, it does not overwrite any scripts that might be on disk. So if there are scripts on disk those will get jammed back into the CPACK whenever a compile is done (and a compile is done during finalization). | ||
+ | <WRAP width center twothirds> | ||
+ | < | ||
+ | %HOMEPATH%\Documents\My Games\creeperworld4\creeperworld4\editor\map2\cpacks\[CPACKNAME] 92415695-49d6-4e97-852b-64493e76233b\scripts\ | ||
+ | </ | ||
+ | </ | ||
- | <code prpl> | + | If you load map as a regular player |
- | # CurrentCoords obtains the (X, y) location | + | |
- | # GetCreeper uses the (X,Y) coordinates | + | |
- | # and returns | + | |
- | # The " | + | |
- | # other words, creeper exists | + | |
- | # displays | + | |
- | if ( GetCreeper(CurrentCoords) | + | The case of on-the-fly opening the editor in a map you are playing is no different -with one exception: The game doesn' |
- | Trace (" | + | |
- | endif | + | |
- | </ | + | |
- | Notice that spaces before or after a warp operator <wrap round box> | + | |
- | Note also that this syntax is totally optional and can be intermixed with standard RPL notation as seems appropriate. | + | If you want to grab the scripts from a map (like an FPS map) and you want to make sure you have the latest scripts, |
- | <code prpl> | + | |
- | 7 ->x | + | |
- | ->x(7) | + | |
- | </ | + | |
- | Both the above statements assign 7 to the variable " | + | |
- | ==== Symbol Aliasing ==== | + | Basically, just deleting the _UNKNOWN directory is the easiest way to clean it |
- | Many arithmetic operators | ||
- | ^ Operator ^ Symbol ^ | + | ---- |
- | | ADD | + | | + | |
- | | SUB | - | | + | |
- | | MUL | * | | + | |
- | | DIV | / | | + | |
- | | MOD | % | | + | |
- | | AND | && | | + | |
- | | OR | %%||%% | | + | |
- | | NOT | ! | | + | |
- | | POW | %%^%% | | + | |
- | | GT | > | | + | |
- | | GTE | >=| | + | |
- | | LT | < | | + | |
- | | LTE | %%<=%% | | + | |
- | | EQ | == | | + | |
- | | NEQ | != | | + | |
- | + | ||
- | ==== Code translator ==== | + | |
- | [[https:// | + | |
- | For those struggling to master xRPL's post-fix format, this may be a useful tool. It can be obtained from [[https:// | + | ===== Code translator ===== |
+ | [[https:// | ||
- | Here are some sample translations, taken directly | + | For those struggling to master 4RPL's post-fix format, this may be a useful tool. It can be obtained |
- | + | ||
- | <WRAP group> | + | |
- | <WRAP half column> | + | |
- | **mplLang code** | + | |
- | <code c> | + | |
- | x = 2 + 2 * 2; | + | |
- | </code> | + | |
- | </WRAP> | + | |
- | <WRAP half column> | + | |
- | **xRPL translated code** | + | |
- | <code 4rpl> | + | |
- | 2 2 2 mul add ->x | + | |
- | </code> | + | |
- | </WRAP> | + | |
- | </ | + | |
- | + | ||
- | <WRAP group> | + | |
- | <WRAP half column> | + | |
- | <code c> | + | |
- | z = f(x, y); | + | |
- | </ | + | |
- | </ | + | |
- | <WRAP half column> | + | |
- | <code 4rpl> | + | |
- | z = f(x, y); | + | |
- | </ | + | |
- | </ | + | |
- | </ | + | |
- | + | ||
- | <WRAP group> | + | |
- | <WRAP half column> | + | |
- | <code c> | + | |
- | [x, y] = CurrentCoords(); | + | |
- | </ | + | |
- | </ | + | |
- | <WRAP half column> | + | |
- | <code 4rpl> | + | |
- | CurrentCoords ->y ->x | + | |
- | </ | + | |
- | </ | + | |
- | </ | + | |
- | + | ||
- | <WRAP group> | + | |
- | <WRAP half column> | + | |
- | <code c> | + | |
- | if(a<b && (c+1 == -c)) [a, b, c] = 1, 2.0, 3.14; | + | |
- | </code> | + | |
- | </ | + | |
- | <WRAP half column> | + | |
- | <code 4rpl> | + | |
- | <-a <-b lt <-c 1 add <-c neg eq and if | + | |
- | 1 2 3.140000 | + | |
- | endif | + | |
- | </ | + | |
- | </ | + | |
- | </ | + | |
- | + | ||
- | <WRAP group> | + | |
- | <WRAP half column> | + | |
- | <code c> | + | |
- | do (1 .. 42){ | + | |
- | a = refRead(" | + | |
- | refWrite(7*(3.14+i), | + | |
- | } | + | |
- | </ | + | |
- | </ | + | |
- | <WRAP half column> | + | |
- | <code 4rpl> | + | |
- | 42 1 do | + | |
- | " | + | |
- | 7 3.140000 i add mul " | + | |
- | loop | + | |
- | </ | + | |
- | </ | + | |
- | </ | + | |
- | ===== Tutorials and how-to ===== | ||
- | link to Cornucanis' | ||
- | link to rotation tutorial |