Official CRPL examples

Started by Grauniad, December 20, 2012, 12:31:44 PM

Previous topic - Next topic

Grauniad

Please submit all new/future contributions to the wiki.

This thread contains CRPL code examples. Feel free to offer your own examples by posting them in a reply. If we accept them, they will be incorporated in the main body. If not, they will be deleted without comment. For consideration, please make sure that all steps are well documented.

Discussion of any examples should happen in a different thread. Non-relevant posts on this thread will be summarily removed.

Ex 1: Contributor: VirgilW
Purpose: Creates 10 units of Creeper every second at the unit's coordinates.

# Creates 10 units of Creeper every second at the units coordinates.
CurrentCoords 10 SetCreeper
30 Delay



Ex 2: Contributor: VirgilW
Purpose:

# Makes a runner at the units current coordinates every three seconds, but only if there is digitalis underneath.
# The runner moves at speed 2, has a health of 10, and carries 20 units of Creeper as a payload.
CurrentCoords GetDigitalis
if
  CurrentCoords 2 10 20 CreateRunner
  90 Delay
endif


Ex 3: Contributor: VirgilW
Purpose:

# Show the trace log, clear it, then show the numbers 0 through 9 in the log
ShowTraceLog
ClearTraceLog
5 0 do
  I Trace
loop


Ex 4: Contributor: VirgilW
Purpose:

#Emit Creeper along a line 5 cells wide and centered over the unit.
CurrentX 3 add CurrentX 2 sub
do
  I CurrentY 10000000 SetCreeper
loop



Ex 5: Contributor: VirgilW
Purpose:

#Emit Creeper over a 5x5 area centered on unit.
CurrentY 3 add CurrentY 2 sub
do
  CurrentX 3 add CurrentX 2 sub
  do
     I J 10 SetCreeper
  loop
loop


Ex 6: Contributor: VirgilW
Purpose:


# Fills the map with 1000 walls of varying health each game loop.
# The outer loop iterates 1000 times (hence the 1000 walls per game loop).
# Inside the loop, random map coordinates are chosen.
# Then, a random float is chosen to serve as the wall's health.
1000 0 do
  RandCoords RandFloat SetWall
loop


Ex 7: Contributor: VirgilW
Purpose:


# Creates a random wall 'matrix' pattern in the upper left hand corner of the map.
# When, and only when, the unit is destroyed emit 9 cells (a 3x3 grid) over the unit filled with the maximum amount of Creeper a cell can hold.
0 10 RandInt 0 10 RandInt RandFloat SetWall

:destroyed
CurrentY 2 add CurrentY 1 sub do
CurrentX 2 add CurrentX 1 sub do
I J 2000 SetCreeper
loop
loop


Ex 8: Contributor: VirgilW
Purpose:

# Mr. Evil to Zorg...
# Useless for gameplay, but interesting to look at.
10000 0 do
  CurrentCoords 50 RandCoordsInRange RandFloat 2000 mul
  SetCreeper
loop



Ex 9: Contributor: VirgilW
Purpose:


# Create a wandering emitter.  
# The emitter leaves a Creeper trail as it moves around.
# Whenever it changes directions, it leaves a pool of creeper.
# When destroyed, it emits a bunch of Creeper and fires spores at player units.

# Setup an initial movement.  
# This is so we don't leave a pool
# of Creeper on the first movement.
once
  RandCoords swap 2 div swap 1 QueueMove
endonce

# If the current movement queue is empty, pick a new spot to move to.
GetQueuedMoveCount eq0 if
  # We will move randomly around on the left side of the map.
  # So we pick Random Coordinates, but then divide
  # the X coordinate by 2 so it is on the left side of the map.
  RandCoords swap 2 div swap 1 QueueMove
 
  # Leave a pool of Creeper since we are changing
  #directions and moving to a new spot.
  CurrentCoords 100 AddCreeper
endif

# We want to leave a trail of Creeper behind.  So we emit 2 Creeper every 10 frames
GetTimer0 eq0 if
  CurrentCoords 2 AddCreeper
  10 SetTimer0
endif

# When Destroyed, emit a bunch of Creeper and choose 5 units and fire spores at them.
:destroyed
CurrentCoords 1000 AddCreeper
5 0 do
  CurrentCoords RandUnitCoords 1 20 CreateSpore
loop


Ex 10: Contributor: VirgilW
Purpose:


# Make a tower that moves around randomly leaving both a
# Creeper and a Digitalis trail.  Also deposits up to 10
# Runners as it moves.

GetQueuedMoveCount eq0 if
  RandCoords 3 QueueMove
endif

CurrentCoords 2 SetCreeper

CurrentY 2 add CurrentY 1 sub do
  CurrentX 2 add CurrentX 1 sub do
     I J true SetDigitalisGrowth
     I J 1 SetDigitalis
  loop
loop

GetRunnerCount 10 lt if
  GetTimer0 eq0 if
     CurrentCoords 1 10 10 CreateRunner
     150 SetTimer0
  endif
endif


Ex 11: Contributor: VirgilW
Purpose:


#Makes the tower move between two points.
#The points are defined once and assigned to local variables.

once
  10 ->x1
  20 ->y1
  40 ->x2
  50 ->y2
endonce

#Check to see if we are moving. If not queue up a movement
GetQueuedMoveCount eq0 if
  #If we are at the first position, move to the second.  
  #Otherwise move to the first position.
  CurrentX <-x1 eq if
     <-x2 <-y2 1 QueueMove
  else
     <-x1 <-y1 1 QueueMove
  endif
endif


Ex 12: Contributor: VirgilW
Purpose:


# Draw a grid of walls with spaces between each cell.
# The grid deposits 10 wall segments per frame.
once
  0 ->x
  0 ->y
  0 ->counter
  1 ->level
endonce

while
  <-y 50 lt
repeat
  <-x <-y <-level SetWall

  <-x 2 add ->x
  <-x 50 gt if
     0 ->x
     <-y 2 add ->y
  endif

  <-counter 10 gt if
     0 ->counter
     break
  endif
  <-counter 1 add ->counter
endwhile

<-y 50 gte if
  0 ->y
  <-level 0.2 add 1 mod ->level
endif


Ex: 13 Contributor: VirgilW
Purpose: Demonstrate function support.


# --- Main Body ---------------------
10 @emit

1 @chance if
  100 @relocate  #Move quickly
endif
#--------------------------------------

# --- Emit Creeper ---------------------
# --- Only emit creeper while not moving.
# --- [ Amt -- ]
:emit
->amt   #Grab the amount from the stack and store it in a var
GetQueuedMoveCount eq0 if
  CurrentCoords <-amt SetCreeper
endif
#--------------------------------------

# --- Relocate -------------------------
# --- Move  to a new location.
# --- [Speed -- ]
:relocate
->speed   #Grab the speed from the stack and store it in a var
RandCoords <-speed QueueMove

#--------------------------------------

# --- Roll a 100 sided die--------------
# --- Return true or false randomly.
# --- The value on the stack is the percentage chance.
# --- [ Chance_in_100 -- true/false]
:chance
# Take an item from the stack, divide by 100,
# then compare to a random float.
100.0 div RandFloat gt
#--------------------------------------
A goodnight to all and to all a good night - Goodnight Moon

knucracker

Image spinner.  Specify a rate and which image to rotate.  Positive rotation rates are counterclockwise and the rotation rate is in radians per frame.

$rotationRate:0.1
$imageToRotate:"main"

# Make a part spin around
Self <-imageToRotate GetImageRotation ->currentRotation
<-currentRotation <-rotationRate add ->currentRotation
Self <-imageToRotate <-currentRotation SetImageRotation

# This version is more terse and more efficient, but harder to read.
#Self <-imageToRotate Self <-imageToRotate GetImageRotation <-rotationRate add SetImageRotation



Alpha blink.  Can be used for making a blinking light.  Changes the transparency of an image from fully transparent to fully opaque in a cycle.  The red, green, and blue values can be used to tint the color of the image.

$name:"light"
$customImageName:"custom0"
$red:255
$green:255
$blue:255
$rate:10
$active:1

once
self <-name <-customImageName SetImage
self <-name -0.01 SetImagePositionZ
endonce



<-active if
<-alpha 0 lt if
0 ->alpha
<-rate abs ->rate
else
<-alpha 255 gt if
255 ->alpha
<-rate abs -1 mul ->rate
endif
endif

<-alpha <-rate add ->alpha

self <-name <-red <-green <-blue <-alpha SetImageColor
else
self <-name 0 0 0 0 SetImageColor
endif

Grauniad

You can modify posts yourself. Feel free to put them up top where they belong. Saves me the editing. Next time. Now I'll just delete my two posts above and all will be hunky dory.
A goodnight to all and to all a good night - Goodnight Moon

Grauniad

A goodnight to all and to all a good night - Goodnight Moon

Grauniad

Even more code examples (Hope springs eternal)
A goodnight to all and to all a good night - Goodnight Moon

J

#5
# moves the core in a circle around x and y with a set speed
# ------------------------------------------
$speed:1
$size:16
$x:32
$y:32
$precision:0.2
once
0.0 ->step
endonce
GetQueuedMoveCount eq0 if
<-step cos <-size mul <-x add <-step sin <-size mul <-y add <-speed QueueMove
<-step <-precision add ->step
endif


Creates a moving wall of creeper.
You can adjust the speed of the wall, the amount of creeper it creates, the initial delay and if the wall should release all creeper after reaching the right side of the map, repeat with the creeper still in the wall or release all creeper and repeat from the left side (without creating any more creeper).

EDIT: I've updated to code, you can now keep other creeper out of the moving wall. If you have any ideas of features I could add to this script, please PM me. Also, it might not be a good idea to use this on high maps (wide no problem), as this script uses 50-100 opcodes/frame/mapheight, and 75-200 more when it moves (haven't counted them, 236 opcodes total).

# MoveWall.crpl
# Created on: 2/4/2013 8:00:55 PM
# Author: J
# This script creates a wall of creeper on the left side of the map that moves forward every x frames
# You may choose in-game if the wall should keep going or release the creeper at the end
# If RepeatAtEnd=2 the creeper is released at the right side of the map while a new (empty) wall will run over the map
# If you choose to enable KeepCreeperOut, it will try to keep all other creeper out of the wall
# Spacing is the number of cells the KeepCreeperOut will keep 100% clean of creeper
# ------------------------------------------
$MoveDelay:30
$InitialWallHeight:500
$InitialDelay:0
$RepeatAtEnd:1
$KeepCreeperOut:1
$Spacing:1

once
<-InitialDelay Delay false ->stop 0 ->stepx <-MoveDelay ->stept
MapHeight 0 do 0 I <-InitialWallHeight SetCreeper loop
endonce

<-stop not if
MapHeight 0 do
#move creeper back from the left side
<-stepx neq0 if
<-stepx I <-stepx 1 sub I GetCreeper AddCreeper
<-stepx 1 sub I 0 SetCreeper
endif
#move creeper back from the right side
<-stepx MapWidth 1 sub neq if
<-stepx I <-stepx 1 add I GetCreeper AddCreeper
<-stepx 1 add I 0 SetCreeper
endif
<-KeepCreeperOut if
#keep creeper out of the wall, left side
<-stepx 3 gte if
<-stepx 3 sub <-Spacing sub I <-stepx 2 sub <-Spacing sub I GetCreeper AddCreeper
<-stepx 2 sub <-Spacing sub I 0 SetCreeper
endif
#keep creeper out of the wall, right side
<-stepx <-Spacing add MapWidth 4 sub lte if
<-stepx 3 add <-Spacing add I <-stepx 2 add <-Spacing add I GetCreeper AddCreeper
<-stepx 2 add <-Spacing add I 0 SetCreeper
endif
endif
loop

<-stept 1 sub ->stept
#move creeper forward if stept is 0
<-stept eq0 if
<-stepx MapWidth 1 sub eq if
<-RepeatAtEnd eq0 if
true ->stop
endif
<-RepeatAtEnd neq0 if
<-MoveDelay ->stept
0 ->stepx
<-RepeatAtEnd 1 eq if
MapHeight 0 do
0 I MapWidth 1 sub I GetCreeper AddCreeper
MapWidth 1 sub I 0 SetCreeper loop
endif
endif
else
<-MoveDelay ->stept
MapHeight 0 do
#move the creeper in the wall forward
<-stepx 1 add I <-stepx I GetCreeper AddCreeper
<-stepx I 0 SetCreeper
#move the creeper in front of the wall forward
<-KeepCreeperOut if
<-stepx <-Spacing add MapWidth 5 sub lte if
<-stepx 4 add <-Spacing add I <-stepx 3 add <-Spacing add I GetCreeper AddCreeper
<-stepx 3 add <-Spacing add I 0 SetCreeper
endif
endif
loop
<-stepx 1 add ->stepx
endif
endif
endif

Old Code

# MoveWall.crpl
# Created on: 2/4/2013 8:00:55 PM
# Author: J
# This script creates a wall of creeper on the left side of the map that moves forward every x frames
# You may choose in-game if the wall should keep going from the left side or release the creeper at the end
# If RepeatAtEnd=2 the creeper is released at the right side of the map while a new (empty) wall will run over the map
# ------------------------------------------
$MoveDelay:30
$InitialWallHeight:1000
$InitialDelay:0
$RepeatAtEnd:1

once
<-InitialDelay Delay false ->stop 0 ->stepx <-MoveDelay ->stept
MapHeight 0 do 0 I <-InitialWallHeight SetCreeper loop
endonce

<-stop not if
MapHeight 0 do
#move creeper back from the left side
<-stepx neq0 if
<-stepx I <-stepx 1 sub I GetCreeper AddCreeper <-stepx 1 sub I 0 SetCreeper
endif
#move creeper back from the right side
<-stepx MapWidth neq if
<-stepx I <-stepx 1 add I GetCreeper AddCreeper <-stepx 1 add I 0 SetCreeper
endif
loop

<-stept 1 sub ->stept
#move creeper forward if stept is 0
<-stept eq0 if
<-stepx MapWidth 1 sub eq if
<-RepeatAtEnd eq0 if
true ->stop
endif
<-RepeatAtEnd neq0 if
<-MoveDelay ->stept
0 ->stepx
<-RepeatAtEnd 1 eq if
MapHeight 0 do
0 I MapWidth 1 sub I GetCreeper AddCreeper MapWidth 1 sub I 0 SetCreeper loop
endif
endif
else
<-MoveDelay ->stept
MapHeight 0 do
<-stepx 1 add I <-stepx I GetCreeper AddCreeper <-stepx I 0 SetCreeper loop
<-stepx 1 add ->stepx
endif
endif
endif
[close]

The next piece of code can remove ALL ammo from the nearest unit (if in range). It doesn't matter if it's energy or AC, all ammo will be removed. This also is a good example for unit attributes.

#Remove all ammo from the nearest unit within range

$KillAmmo:1      #you can turn it off in-game
$AmmoRange:15

<-KillAmmo neq0 if
<-AmmoRange ->range
@GetClosestUnit
<-closestUnit neq0 if
<-closestUnit CONST_AMMO GetUnitAttribute neq0 if
<-closestUnit CONST_AMMO 0 SetUnitAttribute
endif
<-closestUnit CONST_AMMOAC GetUnitAttribute neq0 if
<-closestUnit CONST_AMMOAC 0 SetUnitAttribute
endif
endif
endif

:GetClosestUnit
99999999 ->closestDistance
0 ->closestUnit
CurrentCoords <-range GetUnitsInRange ->unitCount
<-unitCount neq0 if
<-unitCount 0 do
->unit
CurrentCoords <-unit CONST_COORDX GetUnitAttribute <-unit CONST_COORDY GetUnitAttribute Distance ->d
<-d <-closestDistance lt if
<-d ->closestDistance
<-unit ->closestUnit
endif
loop
endif


Time for another piece of code
This will make the tower move at the edge of the map slowly creating more digi growth area:

#This script make the tower move around the edge of the map
#It will create more D growth area as it moves
#Works on all maps, creates D growth area faster on larger maps

$movespeed:1

once
1 ->x1
1 ->y1
MapWidth 2 sub ->x2
1 ->y2
MapWidth 2 sub ->x3
MapHeight 2 sub ->y3
1 ->x4
MapHeight 2 sub ->y4
0 MapWidth do
"DX" I concat 0 ->!
loop
0 MapHeight do
"DY" I concat 0 ->!
loop
endonce

#Create D and growth area on current position
CurrentY 2 add CurrentY 1 sub do
CurrentX 2 add CurrentX 1 sub do
I J true SetDigitalisGrowth
I J 1 SetDigitalis
loop
loop

# Add even more D growth area
CurrentX 1 gt CurrentX MapWidth 2 sub lt and if
RandFloat 0.99 MapHeight asfloat 1000 div sub gt if
"DX" CurrentX concat <-! ->numb
CurrentY 3 lt if
CurrentX <-numb 1 SetDigitalisGrowth
else
CurrentX MapHeight <-numb sub 1 SetDigitalisGrowth
endif
<-numb 1 add "DX" CurrentX concat ->!
endif
endif
CurrentY 1 gt CurrentY MapHeight 2 sub lt and if
RandFloat 0.99 MapWidth asfloat 1000 div sub gt if
"DY" CurrentY concat <-! ->numb
CurrentX 3 lt if
<-numb CurrentY 1 SetDigitalisGrowth
else
MapWidth <-numb sub CurrentY 1 SetDigitalisGrowth
endif
<-numb 1 add "DY" CurrentY concat ->!
endif
endif

#Check for a queued movement
GetQueuedMoveCount eq0 if
#queue moves
<-x2 <-y2 <-movespeed QueueMove
<-x3 <-y3 <-movespeed QueueMove
<-x4 <-y4 <-movespeed QueueMove
<-x1 <-y1 <-movespeed QueueMove
endif


And another piece of code to create runners randomly:

# runnerpower<3600: it will wait (3600-runnerpower) frames before creating any runners
# runnerpower>3600: First runner is extra strong

$runnerpower:0

#Create runners
<-runnerpower 1 add ->runnerpower
0 GetRunnerCount 5 add RandInt eq0 <-runnerpower 3600 gt and if
CurrentCoords 0.9 <-runnerpower 3598 sub 3 div <-runnerpower 3600 sub CreateRunner
3600 ->runnerpower
endif

albrittbrat

I hope it's alright for non-beta and non-mod users to post example scripts here, if not just delete this post.

Create an emitter that increases its output rate over time

#Program to ramp creeper deployment rate over time
#Time is in seconds
#-------------------------------------------------------------------------
$BaseRate:25
$MaxRate:150
$RampTime:600
$NumIncrements:100
$DeployRate:15
once
<-BaseRate ->CRate
0 SetTimer0
<-RampTime 30 mul ->RampTime
<-RampTime <-NumIncrements div 0 round ->TimerRate
endonce
#If the queue is empty, queue next move
#Drop AC based on input parameters
GetTimer0 eq0 if
@DetermineCAmount
endif
CurrentCoords <-CRate SetCreeper
<-DeployRate Delay
#Function to determine amount of creeper to drop
#Range goes from BaseRate to MaxRate
:DetermineCAmount
<-CRate <-MaxRate lte if
<-CRate 1 add ->CRate
<-TimerRate SetTimer0
endif
#End DetermineCAmount Function

Grauniad

We are happy to accept community contributions. Thank you.

We would also be delighted if you could add them to the wiki page for code examples.
A goodnight to all and to all a good night - Goodnight Moon

Xindaris

#8
# HydraEmitter.crpl
# A basic emitter at first.
# Creates an emitter which spawns new emitters in random locations within a defined range when it dies, which themselves also spawn new emitters.
# Note that the decay rates are multiplied, so in theory you could make them bigger than 1 and have the rate/amount/range increase with each death rather than decrease.
# Note also, the spawn code checks to make sure it's not spawning on void. You can comment out that line if you want it to spawn in void, but be careful to not spawn outside of the map!
# ------------------------------------------
$rate:15
$amount:100
$rateDecay:1.0
$amountDecay:.5
$newHeads:3
$headLossPerDeath:1
$headRange:100
$headRangeDecay:.80

CurrentCoords <-amount AddCreeper
<-rate Delay

:destroyed
0 ->count
while <-count lt(<-newHeads) repeat
CurrentCoords <-headRange RandCoordsInRange ->deathX ->deathY
if(<-deathX <-deathY GetVoid not)
"CRPLCORE" <-deathX <-deathY CreateUnit ->currUnit
<-currUnit "main" "CustomEmitter" SetImage
<-currUnit "HydraEmitter.crpl" AddScriptToUnit
<-currUnit "HydraEmitter.crpl" "rate" <-rate mul(<-rateDecay) SetScriptVar
<-currUnit "HydraEmitter.crpl" "amount" <-amount mul(<-amountDecay) SetScriptVar
<-currUnit "HydraEmitter.crpl" "rateDecay" <-rateDecay SetScriptVar
<-currUnit "HydraEmitter.crpl" "amountDecay" <-amountDecay SetScriptVar
<-currUnit "HydraEmitter.crpl" "newHeads" <-newHeads sub(<-headLossPerDeath) SetScriptVar
<-currUnit "HydraEmitter.crpl" "headLossPerDeath" <-headLossPerDeath SetScriptVar
<-currUnit "HydraEmitter.crpl" "headRange" <-headRange mul(<-headRangeDecay) SetScriptVar
<-currUnit "HydraEmitter.crpl" "<-headRangeDecay" <-headRangeDecay SetScriptVar
<-count add(1) ->count
endif
endwhile


Hopefully this will be useful to somebody. Can't seem to find the edit button on the wiki.

Grauniad

Quote from: Xindaris on October 24, 2013, 11:16:46 AM
Can't seem to find the edit button on the wiki.

This button is not visible?
A goodnight to all and to all a good night - Goodnight Moon

Xindaris

I had a magnifying glass leading to a read-only version of the source, but then it occurred to me to try and log in, and now it's quite visible. Sorry about that.

Grauniad

I forgot one had to be logged in.. :)
A goodnight to all and to all a good night - Goodnight Moon

eduran

Something I coded after unsuccessfully trying to get AscendToOrbit to work:

# Ascend.crpl
# Created on: 10/25/2013 4:05:03 PM
# ------------------------------------------

#Script to make a unit look like it is ascending to orbit.
$duration:60 #ascend duration in frames
$destroy:1  #if set to 1 the unit is destroyed after ascension
#if set to 0 it is just hidden by setting all image slots to "NONE"
$playSound:1

once
CreateList ->ImageSlots
#########################################################################
#add the name of all image slots of your unit here (usually just "main"):
"main"
"AdditionalImage1"
"AdditionalImage2"


#########################################################################
AppendStackToList(<-ImageSlots)
0 ->counter
if(<-playSound)
PlaySound("UnitTakeOff")
endif
endonce

<-counter mul(0.025) mul(60) div(<-duration) add(1) ->scale
<-counter mul(60) div(<-duration) ->position
do(GetListCount(<-ImageSlots 0))
SetImagePositionY(Self GetListElement(<-ImageSlots I)  <-position)
SetImageScale(Self GetListElement(<-ImageSlots I) <-scale <-scale)
loop
<-counter add(1) ->counter
if(gte(<-counter <-duration))
if(<-destroy)
Destroy(Self 0)
else
do(GetListCount(<-ImageSlots 0))
SetImage(Self GetListElement(<-ImageSlots I) "NONE")
loop
SetUnitAttribute(Self CONST_TAKEMAPSPACE 0)
endif
endif

Tistel

#13
Hi there are no need to write AscendToOrbit it already exists.
(found in Notepad++ autocomplete file)

[edit]
Tested a bit more.
It looks like AscendToOrbit only work ok after DropFromOrbit, it ascends from the cell it droped on (or lower left corner if not)


Example of an unit that lands and take off again

# visit.crpl
# Created on: 10/25/2013 7:18:48 PM
# ------------------------------------------

once
 SetUnitAttribute(Self CONST_COUNTSFORVICTORY False)
 SetUnitAttribute(Self CONST_CREATEPZ False)
 DropFromOrbit(CurrentCoords)
 SetTimer0(110)
endonce

GetTimer0 eq0 if
 once
   AscendToOrbit
 endonce
endif

knucracker

There was a bug in AscendToOrbit that I just fixed in the last few hours.  I will be doing an updated build shortly (probably this weekend) and will make it available on the forums in an open beta.  That should have the fix....