CRPL related questions

Started by eduran, October 13, 2013, 09:10:10 AM

Previous topic - Next topic

knucracker

You are modifying the list as you loop over it, so the indexes change (the list gets shorter).  Imagine you have a list 5 elements long.  0, 1, 2, 3, 4 are the indexes of the elements.  You are looping from 0 through 4 inclusive.  Say that when you are on index 2 you remove the element.  That shrinks the list to 4 elements in length but you will still loop over 5 elements.

This is a common problem that shows up in many situations in many languages and scenarios; modifying a list while iterating over it.  Some languages have iterators that help you deal with it.  CRPL is old school, though, so you have to use an old school solution.  You could use a while/repeat/endwhile loop to go over the list and keep up with an index variable yourself.  Another solution would be to not modify the list but to build a new list each time (leaving out the items you want to discard).

If I had the time I'd work up an couple examples for you. But, I'm rushing to get Colonial Space done this week...

J

Try adding one to a variable each time you remove an element. Substruct this value from I.
0 ->numb
<-Collectors GetListCount 0 do
 <-Collectors I <-numb sub GetListElement CONST_ISDESTROYED GetUnitAttribute if
   <-Collectors I <-numb sub RemoveListElement
   <-numb 1 add ->numb
 endif
loop

Lost in Nowhere

For whatever reason, this isn't functioning properly:
# CircleDecay.crpl
# Created on: 11/23/2013 12:50:12 PM
# ------------------------------------------

$rad:30
$Increase:1
$Decrease:1
$Range:3

once
  PlaySound("Retro25")
  1 ->row
endonce

if (<-row lt (<-rad))
@GetRow
@DoRow
<-row add(1) ->row
endif

:GetRow
<-row 12 mul asfloat PI mul ->circ
<-circ 0 gt if
<-circ 0 do
I @GetCoords ->x ->y
<-x <-y GetTerrain ->t
<-t "x" <-x concat "y" <-y concat concat ->!
loop
endif

:DoRow
<-row 2 mul asfloat PI mul ->circ
<-circ 0 gt if
<-Range 2 mul 1 add ->tr
<-circ 0 do
I @GetCoords ->x ->y
"x" <-x concat "y" <-y concat concat <-! ->t
I ->n
0 ->total
<-n <-Range add <-n <-Range sub do
I @GetCoords swap GetTerrain <-total add ->total
loop
<-total <-tr asfloat div ceil ->nt
<-t <-nt @Check ->ft
<-x <-y <-ft SetTerrain
loop
endif

:GetCoords
->b
<-b <-circ div cos <-row mul CurrentX add ->xgc
<-b <-circ div sin <-row mul CurrentY add ->ygc
<-ygc <-xgc

:Check # oldT newT -> finalT
->newT ->oldT
<-Increase not if
<-newT <-oldT gt if
<-oldT ->newT
endif
endif
<-Decrease not if
<-newT <-oldT lt if
<-oldT ->newT
endif
endif
<-newT

It's supposed to decay higher areas in a circular manner, which it does for about 1/8 of the area; elsewhere, it does nothing.
Don't die! :)

Flabort

It's not exactly CRPL, but recently I tried to set the middle 3 upgrades at the forge to "-1", meaning you can infinitely upgrade your energy production and ore production, as long as you can afford the increasing price. However, it acted as if I had put in 0. There's a pretty obvious formula for producing the prices for the first 10, but no matter what I try, I can't make it go over 10.
Not that that's a pressing issue, but maybe in a future patch an ability to go over those current bounds would be nice.

Meanwhile, I was wondering, does anyone have a script that changes a core between two states depending on whether it's sitting on creeper or anticreeper? Such as an emitter, that releases 50 AC every 2 seconds if the last thing that was under it was AC, or 100 creeper every 2 seconds if the last thing that was under it was creeper. I'm having trouble with the figuring out whether it's on creeper or not bit.
My maps: Top scores: Sugarplum, Cryz Dal, Cryz Torri, Cryz Bohz (Click fetch scores, page courtesy of kwinse)

kwinse

CurrentCoords GetCreeper should work (though you may have to be more creative if you want anti/creeper under any part of it to affect its output). Positive number should be creeper, negative ac. Having it change output like that shouldn't be hard.

Grauniad

Quote from: Flabort on December 30, 2013, 01:58:35 AM
It's not exactly CRPL, but recently I tried to set the middle 3 upgrades at the forge to "-1", meaning you can infinitely upgrade your energy production and ore production, as long as you can afford the increasing price. However, it acted as if I had put in 0. There's a pretty obvious formula for producing the prices for the first 10, but no matter what I try, I can't make it go over 10.
Not that that's a pressing issue, but maybe in a future patch an ability to go over those current bounds would be nice.
Those are hard limits.
Quote

Meanwhile, I was wondering, does anyone have a script that changes a core between two states depending on whether it's sitting on creeper or anticreeper? Such as an emitter, that releases 50 AC every 2 seconds if the last thing that was under it was AC, or 100 creeper every 2 seconds if the last thing that was under it was creeper. I'm having trouble with the figuring out whether it's on creeper or not bit.

Obtain the unit coordinates, the do "getcreeper" at those coordinates and examine the return value.
A goodnight to all and to all a good night - Goodnight Moon

Flabort

Well, with the first one, I was trying to make a map with two totems, a single ore patch, a free forge, and not enough room to build an energy economy that would support >1 blaster. With only 3 energy upgrades available, but infinite ore upgrades. However, if it's a hard limit, and that's not going to be changing any time soon, I'll just have to go without.  8)

And, oh, OK, so I was obviously getting my notation backwards, the coordinates go before the getcreeper. And I would use an if statement, but... what about staying in it's last state when neither AC or C is present?
My maps: Top scores: Sugarplum, Cryz Dal, Cryz Torri, Cryz Bohz (Click fetch scores, page courtesy of kwinse)

Michionlion

Quote from: Flabort on December 30, 2013, 03:15:33 PM
Well, with the first one, I was trying to make a map with two totems, a single ore patch, a free forge, and not enough room to build an energy economy that would support >1 blaster. With only 3 energy upgrades available, but infinite ore upgrades. However, if it's a hard limit, and that's not going to be changing any time soon, I'll just have to go without.  8)

And, oh, OK, so I was obviously getting my notation backwards, the coordinates go before the getcreeper. And I would use an if statement, but... what about staying in it's last state when neither AC or C is present?

Set a variable, that way, as long as you don't change the var except to change to the opposite type, you can emit based on the variables value.
"Remember kids, the only difference between science and messing around is writing it down."
                                                                                                                         - Adam Savage

My website
My CW1, and CW2 maps!

Flabort

#68
Right, so let me know if I did anything wrong here:
$amtCreeper:50
$amtAnti:-25
$interval:60
CurrentCoords GetCreeper 0 gt if
1 ->state
endif
CurrentCoords GetCreeper 0 lt if
0 ->state
endif
<-state if
CurrentCoords <-amtCreeper SetCreeper
else
CurrentCoords <-amtAnti SetCreeper
endif
<-interval Delay

As I imagine it, it starts as an AC emitter, but a much stronger emitter quickly overtakes it, converting it to a regular creeper emitter, but stronger. You can change it back if you can spray enough AC at it... Is there flaws in my logic/script?

edit: Yes, I missed several "<-"s. Except for that. Edited those in.

Edit2: I can confirm it works as intended, and am playing a map I threw together with it. It's very fun, somewhat difficult (not too much), and I am attaching a picture of the map in progress.
My maps: Top scores: Sugarplum, Cryz Dal, Cryz Torri, Cryz Bohz (Click fetch scores, page courtesy of kwinse)

Grayzzur

The only thing I would do is add this after your initial variables before the rest of the code:

once
   0 ->state
endonce

This little script works without it, because you're relying on uninitialized variables to have a value of zero at the start. That's a bad practice and might get you into unintended behavior in future script projects. Always initialize your variables.
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

knucracker

I posted a slight update to your script in your map discussion thread:
http://knucklecracker.com/forums/index.php?topic=15081.msg110691#msg110691

This update makes it so that friendly flip emitters don't have to be nullified to win the map.

Flabort

OK, after having played Nano in Neon, which is just evil genius in it's use of colors, I went and tried to make a script that continually messes with the color of creeper. After some trial and error, finding out that the Get and Set commands use two different number formats, and discovering I had used lte when I wanted gte, I got it to work. I was going to ask how to fix it here, but I'll just share it instead.
Spoiler
# psychedelicCreeper.crpl
# Created on: 1/4/2014 4:00:31 PM
# ------------------------------------------

once #Initializing my variables. Actually, this may as well be ripped off the official examples page for changing creeper color to red. Except I use blue. And the whol Mul thing, that's due to the floating point vs whole number.
GetCreeperColors 255 mul ->acB 255 mul ->acG 255 mul ->acR 255 mul ->creeperB 255 mul ->creeperG 255 mul ->creeperR
20 ->creeperR 20 ->creeperG 220 ->creeperB
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
endonce

#Start the loop by getting the current colors. Pop off the AC colors to make sure I don't mess with them by accident. Same as initialization.
GetCreeperColors 255 mul ->acB 255 mul ->acG 255 mul ->acR 255 mul ->creeperB 255 mul ->creeperG 255 mul ->creeperR

#manipulate two colors, making sure not to touch the third if it's at it's lowest point.
<-creeperR 20 lte <-creeperB <-creeperR gte Or <-creeperG <-creeperR gt and if
<-creeperG 20 sub ->creeperG
<-creeperB 20 add ->creeperB
endif
#Same thing. Note that when one of the two I manipulated reaches it's lowest point, it triggers TRUE in the next one.
<-creeperG 20 lte <-creeperR <-creeperG gte Or <-creeperB <-creeperG gt and if
<-creeperB 20 sub ->creeperB
<-creeperR 20 add ->creeperR
endif
#And the third pair of colors. Pattern should be Blue to Purple to Red to Orange/Yellow to Green to Cyan to Blue.
<-creeperB 20 lte <-creeperG <-creeperB gte Or <-creeperR <-creeperB gt and if
<-creeperR 20 sub ->creeperR
<-creeperG 20 add ->creeperG
endif
#Update the color set, and wait a little bit so as not to lag the game too much.
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
10 Delay
[close]
My maps: Top scores: Sugarplum, Cryz Dal, Cryz Torri, Cryz Bohz (Click fetch scores, page courtesy of kwinse)

Flabort

Actually working on a non-theoretical script, and I'm stuck. VirgilW himself told me to try marrying the Flip Emitter concept with the Slip Emitter concept.

So I concieved two new scripts. Everything works except the X coordinate of the Slip Emitter. Much of the code was stolen from the Phantom Emitter script on... I forget which world.
The Converterv2.crpl script goes on a core with the SlipEmitSet.crpl code. You set the variables for where you want the slip emitter to go, and do not actually make a core for the child emitter, the script does that.

The scripts:
Converterv2.crpl
# Converterv2.crpl
# Created on: 1/3/2014 1:53:35 PM
# ------------------------------------------
$amtCreeper:50
$amtAnti:-25
$interval:60
$startState:0
#Initializes state, thanks to Grayzzur for the idea.
Once
<-startState ->state
"
" ->lineBreak
endonce
#Checks if there is creeper, if there is, sets the converter to make creeper.
CurrentCoords GetCreeper 0 gt if
1 ->state
SetPopUpText("amt: " <-amtCreeper <-lineBreak "delay: " <-interval 30 div concat concat concat concat)
SetUnitAttribute(Self CONST_COUNTSFORVICTORY TRUE)
endif
#Checks if there is anticreeper, if there is, sets the converter to make AC
CurrentCoords GetCreeper 0 lt if
0 ->state
#the linebreak is on purpose, and concat because the amt isn't always the same.
SetPopUpText("amt: " <-amtAnti <-lineBreak "delay: " <-interval 30 div concat concat concat concat)
SetUnitAttribute(Self CONST_COUNTSFORVICTORY FALSE)
endif
#Checks the state, remember if there was nothing under it, it will use it's last state!
<-state if
CurrentCoords <-amtCreeper SetCreeper
else
CurrentCoords <-amtAnti SetCreeper
endif
<-interval Delay
[close]
SlipEmitSet.crpl
# SlipEmitSet.crpl
# Created on: 1/12/2014 5:48:16 PM
# ------------------------------------------

$childX:10
$childY:10
$percentEmit:20
$interval:15
once
"CRPLCore" <-childX <-childY CreateUnit ->child
<-child "SlipEmitasChild.crpl" AddScriptToUnit
<-child "SlipEmitasChild.crpl" "interval" <-interval setScriptVar
endonce
Self "Converterv2.crpl" "state" GetScriptVar if
<-child "SlipEmitasChild.crpl" "amtCreeper" Self "Converterv2.crpl" "amtCreeper" getScriptVar <-percentEmit mul 100 div setScriptVar
else
<-child "SlipEmitasChild.crpl" "amtCreeper" Self "Converterv2.crpl" "amtAnti" getScriptVar <-percentEmit mul 100 div setScriptVar
endif

:destroyed
<-child 0 Destroy
[close]
SlipEmitasChild.crpl
# SlipEmitasChild.crpl
# Created on: 1/12/2014 5:48:07 PM
# ------------------------------------------

$interval:15
$amtCreeper:5

once
Self "CONST_CANREQUESTAMMO"  setUnitAttribute
Self "CONST_CELLHEIGHT" 3 setUnitAttribute
Self "CONST_CELLWIDTH" 3 setUnitAttribute
Self "CONST_COUNTSFORVICTORY" false setUnitAttribute
Self "CONST_CREATEPZ" false setUnitAttribute
Self "CONST_DESTROYONDAMAGE" false setUnitAttribute
Self "CONST_NULLIFIERDAMAGES" false setUnitAttribute
Self "CONST_TAKEMAPSPACE" true setUnitAttribute
Self "Main" "Custom2" SetImage
endonce

if (GetTimer0 eq0)
SetCreeper(CurrentX CurrentY <-amtCreeper)
@FullAlphaImage
SetTimer0(<-interval)
endif
@FadeImage

:FadeImage
GetImageColor(Self "main") ->alpha ->blue ->green ->red
if (<-alpha gt(0))
<-alpha sub(15) ->alpha
SetImageColor(Self "main" <-red <-green <-blue <-alpha)
endif

:FullAlphaImage
GetImageColor(Self "main") ->alpha ->blue ->green ->red
SetImageColor(Self "main" <-red <-green <-blue 255)
[close]

Basically my problem is when I start up the map, the slip emitters all appear on the left edge of the map. They have their proper Y coordinate, but not the X coordinate.
My maps: Top scores: Sugarplum, Cryz Dal, Cryz Torri, Cryz Bohz (Click fetch scores, page courtesy of kwinse)

Michionlion

spoilers don't work well with code tags...
"Remember kids, the only difference between science and messing around is writing it down."
                                                                                                                         - Adam Savage

My website
My CW1, and CW2 maps!

Flabort

Nothing appears wrong with the BBcode on my end. I can open the spoilers and find the code block within, and from there scroll through my code.

As to the CRPL... what did I do wrong?
My maps: Top scores: Sugarplum, Cryz Dal, Cryz Torri, Cryz Bohz (Click fetch scores, page courtesy of kwinse)