User Tools

Site Tools


4rpl:overview

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
4rpl:overview [2021/01/10 11:31] Karsten754rpl:overview [2022/02/14 06:12] (current) – Attempt to make wrapping notation slightly easier to grok. serdalis
Line 1: Line 1:
  
 <=[[4rpl:start| 4RPL Scripting Language]] <=[[4rpl:start| 4RPL Scripting Language]]
 +
 +:!: 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, similar to an HP calculator or the Forth programming language.  Scripting in CW4 uses a custom language, **4RPL**. It is stack-based, similar to an HP calculator or the Forth programming language. 
  
-4RPL commands either read data from the //stack// or place data on the //stack// Data (arguments) on the stack are in LIFO (**L**ast **I**n, **F**irst **O**ut) order. That means the argument that was placed on the stack last will be the first to be retrieved. Imagine this as a stack of coins. If you put a coin on the top, then the first coin to be taken off will also be the one that was last placed on the stack. +4RPL commands either read data from the //stack// or place data on the //stack// Data (arguments) on the stack are in LIFO (**L**ast **I**n, **F**irst **O**ut) order. That means the argument that was placed on the stack last will be the first to be retrieved. Imagine this as a stack of coins. If you put a coin on the top, then the first coin to be taken off will also be the one that was last placed on top.  
 + 
 +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 
 +</code> 
  
-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 </code> and then these two numbers will be pushed onto the stack when your script executes.+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:4rpl_console|Console]] in the [[cw4:editor_mods|Mission Editor]]. Let's use this to illustrate the next few examples.  An easy way to familiarize yourself with 4RPL is to use the [[cw4:4rpl_console|Console]] in the [[cw4:editor_mods|Mission Editor]]. Let's use this to illustrate the next few examples. 
  
-As an illustration, imagine you want to add two of the numbers you entered above. The instruction to perform addition is **[[4rpl:commands:add|add]]**. Either of these mini scripts will now perform the addition:+As an illustration, imagine you want to add two of the numbers you entered above. The instruction to perform addition is **[[4rpl:commands:add|add]]**. You can also simply use a "+" rather than the **add** command. 
  
 <code 4rpl> <code 4rpl>
-2 4 5 add +2 4 + 
-TraceAllSp +TraceAllSP
 </code> </code>
  
-The code above put 3 numbers on the stack, the `addcommand took the 4 and the (last-in, first out) added them and pushed the result (9) back on the stack. `TraceAllSptakes all commands on the stack, puts a space in between them and prints them to the Console. SO the 2 and the 9 are now printed on the console +The code above puts 2 numbers on the stack, the ''%%add%%'' (or ''%%+%%''command took the 4 and the (last-in, first out) added them and pushed the result (6) back on the stack. [[4rpl:commands:traceAllSp|TraceAllSp]] pops (takes/removes) all elements on the stack, puts a space in between them and prints them to the Console. A "6" is now printed on the console
  
-{{console_output_1.png}}+:!: Note that 4RPL is a //case-insensitive// language, meaning **__any and all capitalization is ignored__**. **TraceAllSP** may as well be written as **TRACEALLSP** or **traceallsp**, there is no difference.
  
-fixme after this +Part of 4RPL is the commands that manipulate map objects, such as creeperterrain and unitsHere is a simple script to put some creeper on a specific cell on a map
----- +
-4RPL programming is a stack-based languagesimilar to programming a HP calculator or Forth language programmingIf this is not something you have done, read on for brief introduction to 4RPL and stack-based programming+
  
-An 4RPL instruction either use arguments (data) that is on a "stack", or place arguments on the "stack". Arguments on the stack are in LIFO (**L**ast **I**n, **F**irst **O**ut) order. That means the argument that was placed on the stack last will be the first to be retrieved. Imagine this as a stack of coins. If you put a coin on the top, then the first coin to be taken off will also be the one that was last placed on the stack. +<code 4rpl>  
 +12 23 100 AddCreeper   
 +</code>
  
-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 </code> and then these two numbers will be pushed onto the stack when your script executes.+Run this **once** in the console and then unpause the game and let the game simulation run a few framesYou 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, see [[cw4:custom_maps#Understanding the 3D Coordinate System]])).
  
-As an illustration, imagine you want to add two of the numbers you entered above. The instruction to perform addition is **[[4rpl:commands:add|add]]**. Either of these mini scripts will now perform the addition: 
  
-<code 4rpl>2 4 5 add</code>+===== Comments ===== 
 +Comments in 4RPL can be either a whole line or a partial line. The comment terminates when a line ends. 
 +Comments are indicated by the "hash" character **#**,
  
-   +<code 4rpl> 
-Either of the scripts above will read the two most recent arguments on the stack (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 "2" from your original entry, and "9" - the sum of the two arguments added by the "add" instruction.  The stack would now look like this: +# This is how we add two of the three numbers 
-<code 4rpl>2 9</code>+# that are on the stack 
 +# Below is code         # Below is a comment 
 +4 5  add              # adds 4 and to get 
 +</code>
  
-<wrap info round > 
-You can find more commands and detailed explanations of them in the [[crpl:crplreference|CRPL Reference]]! 
-</wrap> 
  
-==== Comments ====+===== 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
  
-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.+<code 4rpl> 
 +12 23 100 AddCreeper 
 +AddCreeper(12 23 100) # Does the same thing as the line above.
  
-Comments in xRPL can be either a whole line or a partial lineThe comment terminates when a line ends.+1 (2 3 +) 4  # Demonstrate wrapping affects all stack locations. 
 +2 3 + 1 4    # This line is the same as the one above. 
 +</code>
  
-Comments are indicated by the "hash" character (**#**), 
  
 +===== 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.
  
-<code 4rpl># This is how we add two of the three numbers +<code 4rpl> 
-# that are on the stack +if ( GetGameUpdateCount 900 >= ) 
-# Below is code         #  Below is a comment +   TraceAllSp("More than 30 seconds of game time have passed") 
-2 4 5  add              # adds 4 and 5 to get 9</code>+else 
 +   TraceAllSp("Less than 30 seconds of game time have passed") 
 +endif 
 +</code>
  
-<wrap important>Note:</wrap> Unless explicitly noted otherwise, all instructions are destructive stack operations in that they will remove as many arguments as is required for their execution from the stack and replace those with the output from their execution. In the example above, the original two items on the stack have been replaced by their sum. 
  
-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. 
  
-==== Warp Notation ====+Note: See [[4rpl:Data Types]] for comparison between dissimilar types and type conversion. 
  
-An extra and optional <wrap hi>operator</wrap> ((In mathematics and sometimes in computer programming, an operator is a character that represents an action, as for example x is an arithmetic operator that represents multiplication. In computer programs, one of the most familiar sets of operators, the Boolean operators, is used to work with true/false values.)) change how you can choose to write the syntax.  It doesn't change anything about the stack, or how xRPL works.  It only gives you a syntax alternative that can make things easier to read in some cases. 
  
-This operator is called the  **warp**  operator since it warps things around. In more technical terms,  it allows for prefix notation.   Take the following example: 
  
-<code prpl>3 4 add </code>+===== Variables ===== 
 +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 //variables//. To store a variable //from// the stack, write **->varname**. To write a variable back //to// the stack, write **<-varname**. Variables remember their value and can be written to the stack multiple times. Variable names are //case-insensitive//.
  
-This means to push to the stack, push to the stack, then to call <wrap round box>add</wrap> <wrap round box>Add</wrappops two items from the stack, adds them together, then pushes the result back.  +<code 4rpl> 
 +3 4 + ->result 
 +"3 plus 4 is" <-result TraceAllSP 
 +</code>
  
-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.  It remains unchanged and untouched. 
  
-Introducing the Warp operator.   
  
-<code prpl>3 4 add</code>  +Note: See [[4rpl:Data Types]] for comparison between dissimilar types and type conversion. 
-can become +
-<code prpl>add (3 4)</code>+
  
-The open parenthesis <wrap round box>(</wrap> means to warp the all arguments between it and the closing parenthesis <wrap round box>)</wrap> to **before** the command during compilation.  This is merely a syntax trick to improve readability of some code and has no run-time penalty. It is resolved during compilation, when the  compiler literally //warps// the 3 and 4 from inside the parenthesis to the front of the <wrap round box>add</wrap> operation when the code is compiled.  
  
-Here the warp operator is used to make the code slightly more readable. 
-<code prpl>3 add(4)</code> 
-Here, the <wrap round box>4</wrap>to the front of the <wrap round box>add</wrap>, resulting in <wrap round box>3 4 add</wrap> which is the exact same thing as the first example. 
  
-Take second example:+===== Functions ===== 
 +4RPL supports user-defined functions that can be called from anywhere in the script. Functions are declared at the end of script and are formatted as **:FunctionName**. A call to a function is formatted as **@FunctionName**. Function names are //case-insensitive//.
  
-<code prpl+<code 4rpl
-# CurrentCoords obtains the (X, y) location and places it on the stack +4 2 @Function1 Trace  # prints "11" 
-# GetCreeper uses the (X,Y) coordinates to  look at a cell on a map +@Function2            prints "function two"
-  and returns the amount of creeper on that cell +
-The "IFstatement then evaluates for a value greater than one (In  +
-#  other words, creeper exists in a significant amount) and if true +
-#  displays a message in the trace output.+
  
-CurrentCoords GetCreeper 1 gt if +:function1 
-   "Creeper exists here" Trace +    add    # adds together 2 items on the stack 
-endif+    5 add  # adds an extra 5 to that 
 + 
 +:function2 
 +    "function two" Trace
 </code> </code>
  
-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:commands:call|Function Calls]] and [[4rpl:commands:func|Function Declarations]]
  
-It uses the current coordinates, to get the creeper at that coordinate location, then checks if it is greater than 1.  If so, it writes the string //"Creeper exists here"// to the trace log.  
  
-Because of the way the stack works, you have to push two coordinates to the stack first (<wrap round box>[[crpl:docs:currentcoords|CurrentCoords]]</wrap> does that), then call <wrap round box>[[crpl:docs:GetCreeper|GetCreeper]]</wrap> That takes two items from the stack, uses them as coordinates, then pushes the value of the creeper at that map location back to the stack. The number <wrap round box>1</wrap> is then pushed to the stack, and the <wrap round box>[[crpl:docs:gt|gt]]</wrap> operator  takes two items from the stack and does //"greater than"// comparison between them.  The result is either <wrap round box>0</wrap> (//<wrap round box>[[crpl:docs:false|false]]</wrap>//) or <wrap round box>1</wrap> (//<wrap round box>[[crpl:docs:true|true]]</wrap>//) and that is pushed back to the stack.  Finally, the <wrap round box>[[crpl:docs:if|if]]</wrap> statement pops the result of the <wrap round box>[[crpl:docs:gt|gt]]</wrap> call from the stack and then either allows execution to pass to the <wrap round box>[[crpl:docs:trace|Trace]]</wrap> statement, or jumps to the <wrap round box>[[crpl:docs:endif|endif]]</wrap>.+===== Loops ===== 
 +4RPL supports both "do/loop" and "while/repeat" looping constructs\\ 
 +For an example of a **do** loop see: [[4rpl:commands:do]] \\ 
 +For an example of a **while** loop see: [[4rpl:commands:while]] \\
  
-That's xRPL in a nutshell. +\\
  
-Using **warp notation**we can make this slightly more readable. +---- 
 +===== Working with CPACKs ===== 
 +When a CPACK is importedit 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).  You can look on disk at a location like this:  
 +<WRAP width center twothirds> 
 +<code> 
 +%HOMEPATH%\Documents\My Games\creeperworld4\creeperworld4\editor\map2\cpacks\[CPACKNAME] 92415695-49d6-4e97-852b-64493e76233b\scripts\ 
 +</code>  
 +</WRAP>
  
-<code prpl> +If you load map as a regular player and then enter edit mode, the game will stick the scripts into the _UNKNOWN project directory. If there are already matching scripts present at that locationthey will not be overwritten (importing a CPACK is the only exception to this).  If you export, it will take the scripts on disk.  Basically, in the normal case there is project directory on disk. When you open project, that directory is where scripts are location on disk.  When you compile, those are the ones compiledThey get placed into the exported or finalized CPACK.  
-# 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 "IF" statement then evaluates for a value greater than one (In  +
- other wordscreeper exists in a significant amount) and if true +
-#  displays message in the trace output.+
  
-if ( GetCreeper(CurrentCoords)  gt (1) ) +The case of on-the-fly opening the editor in map you are playing is no different -with one exception: The game doesn'know what the project directory isso it uses "_UNKNOWN" as the directory.  Everything else is the same after that.
-   Trace ("Creeper exists here"+
-endif +
-</code> +
-Notice that spaces before or after warp operator <wrap round box>(</wrap> and <wrap round box>)</wrap> don'matter.  You can put spacesor you can bump the warp operator up right next to something else.+
  
-Note also that this syntax is totally optional and can be intermixed with standard RPL notation as seems appropriate.  For instance, assignments still look better without warping. +If you want to grab the scripts from a map (like an FPS mapand you want to make sure you have the latest scripts, you should either create a project for the map and open it from the project page, or you should clean your _UNKNOWN directory before you open the map on the fly.
-<code prpl> +
-7 ->x +
-->x(7) +
-</code> +
-Both the above statements assign 7 to the variable "x". Choose which format you prefer and you think makes your code most readable - then be consistent:)+
  
-==== Symbol Aliasing ====+Basically, just deleting the _UNKNOWN directory is the easiest way to clean it
  
-Many arithmetic operators  can be substituted with shorthand symbols **(4RPL only)**.  
  
-^ Operator ^ Symbol ^ +----
-| ADD | + |  +
-| SUB | |  +
-| MUL | * |  +
-| DIV | / |  +
-| MOD | % |  +
-| AND | && |  +
-| OR  | %%||%% |  +
-| NOT | ! |  +
-| POW | %%^%% |  +
-| GT  | > |  +
-| GTE | >=|  +
-| LT  | < |  +
-| LTE | %%<=%% |   +
-| EQ  | == |  +
-| NEQ | != |  +
-  +
-==== Code translator ==== +
-[[https://github.com/Arin112}Arin112]] wrote a code translator that can translate in-fix ((Infix notation is the notation commonly used in arithmetical and logical formulae and statements. It is characterized by the placement of operators between operands—"infixed operators"—such as the plus sign in 2 + 2.)) code to the xRPL post-fix notation. +
  
-For those struggling to master xRPL's post-fix format, this may be a useful tool. It can be obtained from [[https://github.com/Arin112/mplLang|github]] and is accompanied by many samples. Of course, it should be noted that the code and translation will only be up-to-date as long as the repository is maintained+===== Code translator ===== 
 +[[https://github.com/Arin112}Arin112]] wrote a code translator that can translate in-fix ((Infix notation is the notation commonly used in arithmetical and logical formulae and statements. It is characterized by the placement of operators between operands—"infixed operators"—such as the plus sign in 2 + 2.)) code to the 4RPL post-fix notation
  
-Here are some sample translationstaken directly from the GitHub repository: +For those struggling to master 4RPL's post-fix formatthis may be a useful tool. It can be obtained from [[https://github.com/Arin112/mplLang|github]] and is accompanied by many samplesOf courseit should be noted that the code and translation will only be up-to-date as long as the repository is maintained
- +
-<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> +
- +
-<WRAP group> +
-<WRAP half column> +
-<code c> +
-z = f(x, y); +
-</code> +
-</WRAP> +
-<WRAP half column> +
-<code 4rpl> +
-z = f(x, y); +
-</code> +
-</WRAP> +
-</WRAP> +
- +
-<WRAP group> +
-<WRAP half column> +
-<code c> +
-[x, y= CurrentCoords(); +
-</code> +
-</WRAP> +
-<WRAP half column> +
-<code 4rpl> +
-CurrentCoords ->y ->x +
-</code> +
-</WRAP> +
-</WRAP> +
- +
-<WRAP group> +
-<WRAP half column> +
-<code c> +
-if(a<b && (c+1 == -c)) [a, b, c= 1, 2.03.14; +
-</code+
-</WRAP> +
-<WRAP half column> +
-<code 4rpl> +
-<-a <-b lt <-c 1 add <-c neg eq and if +
-1 2 3.140000 ->c ->b ->a +
-endif +
-</code> +
-</WRAP> +
-</WRAP> +
- +
-<WRAP group> +
-<WRAP half column> +
-<code c> +
-do (1 .. 42){ +
-a = refRead("num"); +
-refWrite(7*(3.14+i), "num"); +
-+
-</code> +
-</WRAP> +
-<WRAP half column> +
-<code 4rpl> +
-42 1 do +
-"num" <-! ->a +
-7 3.140000 i add mul "num" ->! +
-loop +
-</code> +
-</WRAP> +
-</WRAP>+
  
-===== Tutorials and how-to ===== 
-link to Cornucanis' examine map resources 
-link to rotation tutorial 
4rpl/overview.1610296288.txt.gz · Last modified: 2021/01/10 11:31 by Karsten75