User Tools

Site Tools


prpl:prpltutorial

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
prpl:prpltutorial [2017/11/17 15:15] – added flow control kajacxprpl:prpltutorial [2023/10/18 15:53] (current) – adding notepad disclaimer Bob
Line 5: Line 5:
 This is a full "A-Z" tutorial on how to write PRPL scripts. PRPL scripts can be attached to PRPL cores in the editor, and they are used to create custom units. This tutorial assumes no prior knowledge in programming or making scripts or even maps for any of the Knuckle Cracker games. This is a full "A-Z" tutorial on how to write PRPL scripts. PRPL scripts can be attached to PRPL cores in the editor, and they are used to create custom units. This tutorial assumes no prior knowledge in programming or making scripts or even maps for any of the Knuckle Cracker games.
  
-I will try to show pictures where illustration could be welcomed, but will also just exaplin with text at other places to not clutter the tutorial too much. Aslo I'll leave a link to the [[https://knucklecracker.com/wiki/doku.php?id=prpl:prplreference|PRPL reference]] here since I'm sure someone will find that usefull.+I will try to show pictures where illustration could be welcomed, but will also just explain with text at other places to not clutter the tutorial too much. Also I'll leave a link to the [[https://knucklecracker.com/wiki/doku.php?id=prpl:prplreference|PRPL reference]] here since I'm sure someone will find that useful. 
 + 
 +After each section there is a little homework, that will hopefully help you try something on your own and get the grip on things. I recommend you actually do the homework yourself and not just read the solution, since doing the work yourself will give you more EXP :)
  
 Navigation: Navigation:
   * [[.:prpltutorial#making_your_first_script|Making your first script]]   * [[.:prpltutorial#making_your_first_script|Making your first script]]
   * [[.:prpltutorial#the_fundamentals|How does PRPL work - the fundamentals]]   * [[.:prpltutorial#the_fundamentals|How does PRPL work - the fundamentals]]
-  * [[.:prpltutorial#first_unit|First usefull unit - a floodgate]]+  * [[.:prpltutorial#first_unit|First useful unit - a floodgate]]
   * [[.:prpltutorial#variables|Variables]]   * [[.:prpltutorial#variables|Variables]]
   * [[.:prpltutorial#flow_control|Flow control]]   * [[.:prpltutorial#flow_control|Flow control]]
 +  * [[.:prpltutorial#functions|Functions]]
 +  * [[.:prpltutorial#lists|Lists]]
  
-<html><span id="making_your_first_script"></span></html> 
 ==== Making your first script ==== ==== Making your first script ====
  
Line 49: Line 52:
 === Setting up the text editor === === Setting up the text editor ===
  
-This step is entirely optional, but can make it much easier to write scripts. Essentially, Notepad++ is a common text editor for writing in unusual languages, and there's an easy way to get it to recognise PRPL.+This step is entirely optional, but can make it much easier to write scripts. Essentially, Notepad++ is a common text editor for writing in unusual languages, and there's an easy way to get it to recognize PRPL.
  
 You may have seen a different text editor when editing the script, and almost definitely you didn't see the "Hello world!" text colored blue like that. That is called syntax highlighting and is very useful to quickly determine the type of command by color. You may have seen a different text editor when editing the script, and almost definitely you didn't see the "Hello world!" text colored blue like that. That is called syntax highlighting and is very useful to quickly determine the type of command by color.
  
-To set it up like this, first download the Notepad++ editor from [[https://notepad-plus-plus.org/download/v7.5.1.html|their website]] and install it. After that, make sure that Notepad++ is the default editor for .prpl files. Just create an empty file named "abc.prpl" anywhere and right-click it -> Properties -> General -> Opens with ... -> Change -> Select Notepad++ -> OK. After that, your prpl scripts should open in Notepad++ when you click "Edit" in the map editor.+To set it up like this, first download the Notepad++ editor from [[https://notepad-plus-plus.org/download/v7.5.1.html|their website]] and install it.<note>Make sure you download only from the official Notepad++ website to avoid malware. https://notepad-plus-plus.org/</note> After that, make sure that Notepad++ is the default editor for .prpl files. Just create an empty file named "abc.prpl" anywhere and right-click it -> Properties -> General -> Opens with ... -> Change -> Select Notepad++ -> OK. After that, your prpl scripts should open in Notepad++ when you click "Edit" in the map editor.
  
 Next, let's set up the syntax highlighter, because we like pretty colors. Go [[https://knucklecracker.com/forums/index.php?topic=21453.0|here]] and download the prpl-syntax.xml attachment file anywhere. Next, open your Notepad++ and go to Language -> Define your language -> Import -> (select the downloaded prpl-syntax.xml file) -> Open -> (close the language window). It should then change the highlighting of the file. If not, try restarting Notepad++ or selecting the language manually from the Language menu. Next, let's set up the syntax highlighter, because we like pretty colors. Go [[https://knucklecracker.com/forums/index.php?topic=21453.0|here]] and download the prpl-syntax.xml attachment file anywhere. Next, open your Notepad++ and go to Language -> Define your language -> Import -> (select the downloaded prpl-syntax.xml file) -> Open -> (close the language window). It should then change the highlighting of the file. If not, try restarting Notepad++ or selecting the language manually from the Language menu.
 +
 +=== Homework ===
 +
 +Change the script to write 2 messages instead of one: "Hello world!" and "It's a good day to learn PRPL today.", then save the file, recompile it and see the difference in the debug window.
 +
 +Solution:
 +<hidden>
 +<code prpl>
 +once
 +    "Hello world!" Trace
 +    "It's a good day to learn PRPL today." Trace
 +endonce
 +</code>
 +</hidden>
  
 <html><span id="the_fundamentals"></span></html> <html><span id="the_fundamentals"></span></html>
Line 102: Line 119:
  
  
-8 6 sub 5 mul #prints 10+8 6 sub 5 mul Trace #prints 10
  
     8        sub    5    mul   Trace     8        sub    5    mul   Trace
Line 112: Line 129:
 8 9 5 min max Trace #prints 8 8 9 5 min max Trace #prints 8
  
-    8           min   max   Trace+    8           min   max   Trace
 | |   | |   | |   |5|   | |   | |   | | | |   | |   | |   |5|   | |   | |   | |
 | |   | |   |9|   |9|   |5|   | |   | | | |   | |   |9|   |9|   |5|   | |   | |
Line 121: Line 138:
 === The command notation === === The command notation ===
  
-Since there is a lot of commands, an easy way to quickly covney what valued does the command take from the stack and what values does it put back is to use a special notaion. It looks something like this: [ input1 input2 input3 - output1 output2 output3 ]. the individual inputs and outputs are replaced with the data type of the particualr input/output.+Since there is a lot of commands, an easy way to quickly coveney what values does the command take from the stack and what values does it put back is to use a special notation. It looks something like this: [ input1 input2 input3 - output1 output2 output3 ]. the individual inputs and outputs are replaced with the data type of the particular input/output.
  
-For example, the "add" command has notation [ number number - number ] since it takes 2 numbers from the stack and puts one number on the stack in return (the addition of the 2 nubmers consumed). Trace has notation [ anything - ] since it accepts one value of any time and doesn't put anything on the stack.+For example, the "add" command has notation [ number number - number ] since it takes 2 numbers from the stack and puts one number on the stack in return (the addition of the 2 numbers consumed). Trace has notation [ anything - ] since it accepts one value of any time and doesn't put anything on the stack. 
 + 
 +=== Homework === 
 + 
 +Write a program that will sum numbers from 1 to 5. Do it in a way so that there are no more than 2 numbers on the stack at a time. 
 + 
 +Solution: 
 +<hidden> 
 +<code prpl> 
 +once 
 +    1 2 add 3 add 4 add 5 add Trace 
 +endonce 
 +</code> 
 +</hidden>
  
-<html><span id="first_unit"></span></html> 
 ==== First usefull unit - a floodgate ==== ==== First usefull unit - a floodgate ====
  
Line 166: Line 195:
  
 You can barely see the land being created and destroyed because of the image, but hey, at least it's something. You can barely see the land being created and destroyed because of the image, but hey, at least it's something.
 +
 +=== Homework ===
 +
 +Change the program to make a horizontal wall instead of vertical. Use ''swap [ anything anything - anything anything ]'' to swap the 2 top values on stack.
 +
 +Solution:
 +<hidden>
 +<code prpl>
 +CurrentCoords swap 2 sub swap 1 SetLand
 +CurrentCoords swap 1 sub swap 1 SetLand
 +CurrentCoords 1 SetLand
 +CurrentCoords swap 1 add swap 1 SetLand
 +CurrentCoords swap 2 add swap 1 SetLand
 +
 +90 Delay #Sleep for 3 second
 +
 +#destroy the land the land
 +CurrentCoords swap 2 sub swap 0 SetLand
 +CurrentCoords swap 1 sub swap 0 SetLand
 +CurrentCoords 0 SetLand
 +CurrentCoords swap 1 add swap 0 SetLand
 +CurrentCoords swap 2 add swap 0 SetLand
 +
 +90 Delay #Sleep for 3 second
 +
 +#                              #sets land at (x-2, y) to 1
 +CurrentCoords  swap      sub    swap        SetLand
 +| |          | |  | |   |2|      |     | 1 |   | | 
 +| |          |y|  |x|   |x|   |x-2|  | y |   | y |   | |
 +| |          |x|  |y|   |y|   | y |  |x-2|   |x-2|   | |
 +===          ===  ===   ===   =====  =====   =====   ===
 +</code>
 +</hidden>
  
 <html><span id="variables"></span></html> <html><span id="variables"></span></html>
 ==== Variables ==== ==== Variables ====
  
-So far we have seen how to store values on the stack and do operations with them. However, somethimes we need to save a value aside and use it later, and leaving it on the stack is not always possible, since in the meantime we want to use other commands that also manipulate with the stack. In such a case, we use variables.+So far we have seen how to store values on the stack and do operations with them. However, sometimes we need to save a value aside and use it later, and leaving it on the stack is not always possible, since in the meantime we want to use other commands that also manipulate with the stack. In such a case, we use variables.
  
 Variables are used for storing values. Unlike the stack, they work like a table of name-value pairs. Use ->variableName to save a value from the stack into a variable named "variableName" and similarly, use <-variableName to read the value stored in that variable and put in on top of the stack. Variables are used for storing values. Unlike the stack, they work like a table of name-value pairs. Use ->variableName to save a value from the stack into a variable named "variableName" and similarly, use <-variableName to read the value stored in that variable and put in on top of the stack.
Line 183: Line 245:
 </code> </code>
  
-Visual representaion of what's going on:+Visual representation of what's going on:
  
 {{:prpl:example_2_1.png|}} {{:prpl:example_2_1.png|}}
  
-Again, each variable can have only one value at a time, I just drew them multiple times to indicate the changed as the commands are being executed. Varaibles don't have to be only numbers, you can story any of the 4 types of value in a variable. Note that you cannot put space into the variable name, so separate the words in the name likeThisInstead.+Again, each variable can have only one value at a time, I just drew them multiple times to indicate the changed as the commands are being executed. Variables don't have to be only numbers, you can story any of the 4 types of value in a variable. Note that you cannot put space into the variable name, so separate the words in the name likeThisInstead.
  
-Unlike the stack that is reset between executions when the script finishes, the variables are persisent enought to stay set across multiple executions (frames). However, all local varibles are reset upon compilation. The variables are called local, because they are local to the instance of a script in a core. That means if the same script is attached multiple times to possibly multiple core, it has separate varaibles every time, with possibly different values.+Unlike the stack that is reset between executions when the script finishes, the variables are persistent enough to stay set across multiple executions (frames). However, all local variables are reset upon compilation. The variables are called local, because they are local to the instance of a script in a core. That means if the same script is attached multiple times to possibly multiple core, it has separate variables every time, with possibly different values.
  
 === Other variable operation === === Other variable operation ===
  
-So far, we have seen how to read from and write to varaibles. Moreover, we can check if the variable exitsts at all: -?variableName puts 1 on the stack if the variable exists, 0 otherwise, or we can delete the variable by writing --variable. To sumarize:+So far, we have seen how to read from and write to variables. Moreover, we can check if the variable exists at all: -?variableName puts 1 on the stack if the variable exists, 0 otherwise, or we can delete the variable by writing --variable. To summarize:
  
 <code prpl> <code prpl>
Line 202: Line 264:
 </code> </code>
  
-All 4 operation also have a reference variant, where they take the name of the variable as an argument from the stack, instead of being writen in the command itself. Just put ! instead of the variable name:+All 4 operation also have a reference variant, where they take the name of the variable as an argument from the stack, instead of being written in the command itself. Just put ! instead of the variable name:
  
 <code prpl> <code prpl>
Line 215: Line 277:
 === Global variables === === Global variables ===
  
-Instead of local variables for each script instance, there is also a single table of global varaibles. They are shared between all scripts, so when one script changes a global varaible, another script will be able to read the change. Global variables are stored completely separately from local variables, so they don't affect each other in any way. Just add * to the end of the command to change it to work with global varaibles:+Instead of local variables for each script instance, there is also a single table of global variables. They are shared between all scripts, so when one script changes a global variable, another script will be able to read the change. Global variables are stored completely separately from local variables, so they don't affect each other in any way. Just add * to the end of the command to change it to work with global variables:
  
 <code prpl> <code prpl>
Line 228: Line 290:
 </code> </code>
  
-Unlike local varaibles, global varaibles persist (are not deleted) even after a compilation.+Unlike local variables, global variables persist (are not deleted) even after a compilation. 
 + 
 +=== Homework === 
 + 
 +Write a variable that will count the number of times the script has been executed. Use the ''once - endonce'' block to initialize it at the start. 
 + 
 +Solution: 
 +<hidden> 
 +<code prpl> 
 +once 
 +    0 ->timesExecuted 
 +endonce 
 +<-timesExecuted 1 add ->timesExecuted 
 +"Times executed: " <-timesExecuted Trace2 # Trace2: write the top 2 values from stack 
 +</code> 
 +</hidden>
  
-<html><span id="flow_control"></span></html> 
 ==== Flow control commands ==== ==== Flow control commands ====
  
 So far we have seen commands being executed one by one as we wrote them. But sometimes you need to execute a piece of code only when a certain condition is met, or you need to execute the same code sever times. For that, there are flow control commands that, well, allow you to control the flow of the command execution. So far we have seen commands being executed one by one as we wrote them. But sometimes you need to execute a piece of code only when a certain condition is met, or you need to execute the same code sever times. For that, there are flow control commands that, well, allow you to control the flow of the command execution.
  
-We have already the ''once'' command, that together with ''endonce'' form a code block that will be executed only the first time the code passes through the ''once'' command, and the block will be skiped on all future executions. This is reset by compiling your script. Most scripts usually have a ''once'' block at the start where they initialize varaibles, set images, etc. Quick example:+We have already the ''once'' command, that together with ''endonce'' form a code block that will be executed only the first time the code passes through the ''once'' command, and the block will be skipped on all future executions. This is reset by compiling your script. Most scripts usually have a ''once'' block at the start where they initialize variables, set images, etc. Quick example:
  
-<core prpl>+<code prpl>
 once once
     0 ->invocationCount     0 ->invocationCount
Line 246: Line 322:
 === if - else - endif === === if - else - endif ===
  
-Next on the list is ''if''. Together with ''endif'' it again creates a block that will be executed only if ''true'' (anything other than 0) is on top of the stack. Since the ''if'' needs to read the value, it will be removed from the stack regardless of wether or not it was ''true''or ''false''. Example:+Next on the list is ''if''. Together with ''endif'' it again creates a block that will be executed only if ''true'' (anything other than 0) is on top of the stack. Since the ''if'' needs to read the value, it will be removed from the stack regardless of whether or not it was ''true''or ''false''. Example:
  
 <code prpl> <code prpl>
Line 260: Line 336:
 <code prpl> <code prpl>
 <-energy 50 gte if <-energy 50 gte if
-    "We have enought energy, horaay!" Trace+    "We have enough energy, hooray!" Trace
 else else
-    "Not enought energy :(" Trace+    "Not enough energy :(" Trace
 endif endif
 </code> </code>
  
-''gte'' (greater than or equal) will check if the first argument is greater than or equal to the second argument. This will write different message depending on if ''energy'' is at least 50. List of all comparision commands:+''gte'' (greater than or equal) will check if the first argument is greater than or equal to the second argument. This will write different message depending on if ''energy'' is at least 50. List of all comparison commands:
   * ''eq [ anything anything - bool ]'' (equals) checks if the 2 values are the same   * ''eq [ anything anything - bool ]'' (equals) checks if the 2 values are the same
   * ''neq [ anything anything - bool ]'' (not equals) checks if the 2 values are different   * ''neq [ anything anything - bool ]'' (not equals) checks if the 2 values are different
Line 286: Line 362:
 </code> </code>
  
-Note: we will get to how to accept energy from mines or how to fire acctual shots later, but we need to get through the fundamentals first. List of all logical operators:+Note: we will get to how to accept energy from mines or how to fire actual shots later, but we need to get through the fundamentals first. List of all logical operators:
  
   * ''and [ bool bool - bool ]'' Tests if both arguments are true   * ''and [ bool bool - bool ]'' Tests if both arguments are true
   * ''or  [ bool bool - bool ]'' Tests if at least one argument is true   * ''or  [ bool bool - bool ]'' Tests if at least one argument is true
-  * ''xor [ bool bool - bool ]'' Tests if exatly one argument is true+  * ''xor [ bool bool - bool ]'' Tests if exactly one argument is true
   * ''not [ bool - bool ]'' Negates the value   * ''not [ bool - bool ]'' Negates the value
  
Line 303: Line 379:
 while <-counter 10 lte repeat while <-counter 10 lte repeat
     <-counter Trace     <-counter Trace
-    <-coutner 1 add ->counter+    <-counter 1 add ->counter
 endwhile endwhile
 </code> </code>
  
-First we initialize the variable counter to 1. Next we use the ''while - repeat - endwhile'' combo: between ''while'' and ''repeat'' is a condition that wil ldetermine wether or not the loop keeps repeating, and between ''repeat'' and ''endwhile'' goes the actual code of the loop. The logic goes like this:+First we initialize the variable counter to 1. Next we use the ''while - repeat - endwhile'' combo: between ''while'' and ''repeat'' is a condition that will determine whether or not the loop keeps repeating, and between ''repeat'' and ''endwhile'' goes the actual code of the loop. The logic goes like this:
  
   - Execute commands between ''while'' and ''repeat''   - Execute commands between ''while'' and ''repeat''
Line 319: Line 395:
 === do - loop === === do - loop ===
  
-Since counting from one number to another is such a common usage of loops, there are 2 entirely different commands just for that: looping by counting a number from a value to another value. Just specify the upper and lower bound (in that order: first uppen, then lower) and you are good to go:+Since counting from one number to another is such a common usage of loops, there are 2 entirely different commands just for that: looping by counting a number from a value to another value. Just specify the upper and lower bound (in that order: first upper, then lower) and you are good to go:
  
 <code prpl> <code prpl>
Line 327: Line 403:
 </code> </code>
  
-The ''I'' command will read the internal counter of the loop, so this will do exactly the same as the prevous loop: count from 1 to 10. So why is there 11? It's because the internal counter has to be **sctrictly less** than the upper bound for the body of the loop to execute. So if we want to count to ten, we need to put 11 there instead.+The ''I'' command will read the internal counter of the loop, so this will do exactly the same as the previous loop: count from 1 to 10. So why is there 11? It's because the internal counter has to be **strictly less** than the upper bound for the body of the loop to execute. So if we want to count to ten, we need to put 11 there instead.
  
 === Nesting loops into one another === === Nesting loops into one another ===
  
-You can also put multiple loops into one another, both do-loop and while-repeat-enwhile can be nested. In such case, 'I' will read the counter of the innermost do-loop loop, 'J' of the second inner-most, and 'K' of the thrid inner-most. A simple example of a multiplication table:+You can also put multiple loops into one another, both do-loop and while-repeat-endwhile can be nested. In such case, 'I' will read the counter of the innermost do-loop loop, 'J' of the second inner-most, and 'K' of the third inner-most. A simple example of a multiplication table:
  
 <code prpl> <code prpl>
Line 341: Line 417:
 </code> </code>
  
-''concat'' is a new commands that takes 2 string from the stack, puts them togeter and returns them as one string. Since we have 5 values on stack in total (J, " times ", I, " is " and J I mul), we need to contac 4 times to join them all together. After that, we cas simply Trace to see the result.+''concat'' is a new commands that takes 2 string from the stack, puts them together and returns them as one string. Since we have 5 values on stack in total (J, " times ", I, " is " and J I mul), we need to contact 4 times to join them all together. After that, we cas simply Trace to see the result. 
 + 
 +=== Homework === 
 + 
 +Add a variable ''direction'' to the floodgate script with 2 possible values: "vertical" and "horizontal". Then change the script to properly work, depending on how this variable is set. Also rework it to use the ''do - loop'' loop. Tip: the lower bound can be negative and remember that the loop will only execute if the inner counter is strictly less than the upper bound. 
 + 
 +Solution: 
 +<hidden> 
 +<code prpl> 
 +once 
 +    #easily change directions by commenting / uncommenting 
 +    "vertical" ->direction 
 +    #"horizonal" ->direction 
 +endonce 
 + 
 +<-direction "vertical" eq if 
 + 
 +    3 -2 do  
 +        CurrentCoords I add 1 SetLand #add land 
 +    loop 
 +    90 Delay #Sleep for 3 second 
 + 
 +    3 -2 do  
 +        CurrentCoords I add 0 SetLand #remove land 
 +    loop 
 +    90 Delay #Sleep for 3 second 
 + 
 +endif 
 + 
 +<-direction "horizontal" eq if 
 + 
 +    3 -2 do  
 +        CurrentCoords swap I add swap 1 SetLand #add land 
 +    loop 
 +    90 Delay #Sleep for 3 second 
 + 
 +    3 -2 do  
 +        CurrentCoords swap I add swap 0 SetLand #remove land 
 +    loop 
 +    90 Delay #Sleep for 3 second 
 + 
 +endif 
 +</code> 
 +</hidden> 
 + 
 +<html><span id="functions"></span></html> 
 +==== Functions ==== 
 + 
 +Apart from build-in commands like ''add'' or ''SetLand'', you can define your own functions that you can later use elsewhere. When calling a function, the program will execute all the commands in the function, and then return to where the function was called from. Example: 
 + 
 +<code prpl> 
 +5 @getMagicNumber add @addMagic Trace #prints 89 (5+42+42) 
 + 
 +:getMagicNumber # [ - int ] 
 +    42 
 + 
 +:addMagic # [ int - int ] 
 +    @getMagicNumber add 
 +</code> 
 + 
 +Use '':funcName'' to define a function, and ''@funcName'' to call one. The body of the function is from it's definition to the definition of the next function, or to the end of the file in case it is the last function. The code before the first function definition is the main code of the script that will be executed every frame. You can return from the function early by using the ''return'' command. 
 + 
 +You can call functions withing other functions, and you can call the same function on multiple places (that's the point, really). However functions are local to a script, so you can't call a function from another script, even if that script is attached to the same core. 
 + 
 +Functions can read and write to the same local variables as the rest of the script, meaning that if you write into a variable in one functions, you can see the value in any other function in the same script. 
 + 
 +=== Homework === 
 + 
 +Make a function that will take 2 numbers and return the bigger one multiplied by their difference. 
 + 
 +Solution: 
 +<hidden> 
 +<code prpl> 
 +:myFunction # [ number number - number ] 
 +    ->b ->a 
 +     
 +    <-a <-b max ->bigger 
 +    <-a <-b sub abs ->difference 
 +     
 +    <-bigger <-difference mul #leave the result on stack 
 +</code> 
 +</hidden> 
 + 
 +<html><span id="lists"></span></html> 
 +==== Lists ==== 
 + 
 +List is a data type that can contain other values. You can add, read, replace and remove values from a list. The 4 basic commands to get started with lists are: 
 + 
 +  * ''CreateList [ - list ]'' Creates a new empty list 
 +  * ''AppendToList [ list anything - ]'' Adds a value to the end of the list 
 +  * ''GetListCount [ list - int ] '' Gets the number of values in the list 
 +  * ''GetListElement [ list int - anything ]'' Reads the value at the specified index from the list 
 + 
 +See [[prpl:prplreference#lists|the PRPL reference]] for more list commands. Example of creating a list and then reading values from it: 
 + 
 +<code prpl> 
 +#create list 
 +CreateList ->list 
 +<-list "a" AppendToList 
 +<-list "b" AppendToList 
 +<-list "c" AppendToList 
 + 
 +#read it's values 
 +<-list GetListCount 0 do 
 +    <-list I GetListElement Trace 
 +    # <-list[I] Trace - a shortcut way of writing the same thing as above 
 +loop 
 +</code> 
 + 
 +This will print "a", "b" and then "c". The ''<-list[I]'' syntax will do the same thing as ''<-list I GetListElement'' it's just easier to write. Some functions like GetAllUnitsInRange return a list, so it's useful to then iterate over the list values to inspect what units did the command find. 
 + 
 +Unlike the 3 other data types, lists are mutable. It means that if you have the same list in 2 variables and you change one, the other one will be changed as well - it is the same list, after all. Think about it like this: let's say that Alice and Bob have the same favourite playground. If you add a seesaw to Alice's favourite playground, Bob's favourite playground will also have that seesaw. A PRPL parallel: 
 + 
 +<code prpl> 
 +CreateList ->playground1 #model a playground as a list of attractions 
 +<-playground1 "swings" AppendToList 
 +<-playground1 "carousel" AppendToList 
 +<-playground1 "slide" AppendToList 
 + 
 +# set this playground as both Alice's and Bob's favourite 
 +<-playground1 ->alicesFavPlayground 
 +<-playground1 ->bobsFavPlayground 
 + 
 +# add a seesaw to Alice's favourite playground 
 +<-alicesFavPlayground "seesaw" AppendToList 
 + 
 +# the seesaw will be in Bob's favourite playground as well 
 +<-bobsFavPlayground Trace 
 +</code> 
 + 
 +I try to explain this in more detail in the [[prpl:copy_vs_deep_copy|Copy vs DeepCopy vs dup]] page, but just remember that if the same list is shared in multiple variables/on multiple place on stack, you can modify it on one place and the changes will be visible when reading the list via a different variable as well. However if you just get a list from a function like GetAllUnitsInRange and read it's content, you don't have to care about any of this. 
 + 
 +=== Homework === 
 + 
 +Create a list with some numbers and then find out how many of them are bigger than 10. 
 + 
 +Solution: 
 +<hidden> 
 +<code prpl> 
 +CreateList ->list 
 +<-list 4 AppendToList 
 +<-list 12 AppendToList 
 +<-list 7 AppendToList 
 +<-list 4 AppendToList 
 +<-list 10 AppendToList 
 +<-list 20 AppendToList 
 +<-list -6 AppendToList 
 +<-list 13 AppendToList 
 + 
 +0 ->count 
 +<-list GetListCount 0 do 
 +    <-list[I] 10 gt if 
 +        <-count 1 add ->count 
 +    endif 
 +loop 
 +<-count Trace 
 +</code> 
 +</hidden> 
 + 
prpl/prpltutorial.1510949747.txt.gz · Last modified: 2017/11/17 15:15 by kajacx