CRPL Ideas/Questions

Started by Tiuipuv, December 24, 2012, 04:44:06 PM

Previous topic - Next topic

Tiuipuv

I love the new CRPL, and can't wait to get started. So, I'm starting now ;D. As a language, I found it unusual to get used to, but very efficient once I got more accustomed to programming backwards. Unfortunately, I don't know a lot about it. I took one of my ideas and put it into code, and have *some* things to ask about it.

I attempted to create a Mobile Creeper Launcher. The idea behind it is to move to the deepest creeper on the map, and pick it up, put it into a spore that targets the shallowest/no creeper area on the the map. Whatever amount it picks up, the spore drops on impact. The more creeper it picks up, the faster the spore travels. Of course, all the particular numbers would be subject to balancing through testing. Here is what I have:


Mobile Creeper Launcher


#1
GetQueuedMoveCount eq0 if

#2
CurrentCoords GetShallowestCreeperCoords

#3
0

#4
CurrentY 3 add CurrentY 2 sub do

CurrentX 3 add CurrentX 2 sub do

#5
I J GetCreeperCount add

I J 0 SetCreeper

loop

loop

#6
20 div Duplicate 20 mul CreateSpore

#7
GetDeepestCreeperCoords 1 QueueMove

endif


#1
GetQueuedMoveCount eq0 if

Does eq0 turn the number on top of the stack into a true/false value (true if equals 0, false otherwise)? Then the if won't do anything unless the top of the stack is a true? That would make sense to me.

#2
CurrentCoords GetShallowestCreeperCoords

GetShallowestCreeperCoords is what I have inserted; there would be some complicated code here searching the map for the area with the lowest/no creeper, defining ties and such. It would be nice to just make things up like I did here :).

There was an interesting problem with stack order here. These sets of coords are later used for a spore (#6). This should work as long as I keep the stack under control, right?

#3
0

This 0 is because the do loop will be adding up a total count, and I think this would provide a number for it to add to. This could be subject to balancing in game, a nonzero number would provide a minimum spore amount. A negative number has interesting effects...

#4
CurrentY 3 add CurrentY 2 sub do

My entire exposure to do loops is what virgil showed in the video, so I probably have it all wrong. How could this be used correctly?

This could be rendered unnecessary with a clever command pre-built. Something like SetCreeperInRange and GetCreeperCountInRange.

Why does Virgil's add 2 and subtract 1? Does it have something to do with how the do loop handles the center square?

#5
I J GetCreeperCount add

In the Video I noticed a strange I J, those seem to be taking information out of the do loop, but I don't understand the do loop to begin with. Why I and J, and how do their values get assigned?

I haven't noticed the command GetCreeperCount, but I'm assuming it would be possible to find the amount of creeper in a single cell.

Here is where I try to make a total of how much creeper was in the 5 by 5 cell area in a single number, and put that on top of the stack. I also try to set the creeper in the 5 by 5 area to 0. Again my lack of experience with do loops leaves me stuck.

#6
20 div Duplicate 20 mul CreateSpore

Here I use another unseen, but very necessary command. Where I put "Duplicate" I would take the current value from the top of the stack, and put it on top of the stack above itself. I don't see a workaround here, there must be some sort of command for it.

"div" stands for divide, and "mul" stands for multiply.

Here is where I create a spore, without providing enough information "directly" beforehand. I assume that it would be possible to retrieve older values from the stack in just the same way, in this case from #2.

#7
GetDeepestCreeperCoords 1 QueueMove

Again with the search for creeper levels. It would probably be possible to use the previous one (#2) to find this as well, for performance reasons.



So there's clearly a lot I don't get yet, and even still I think I get it better than the general population. I would love to see what some of you smart people are thinking put into code (even if we don't have much to work with yet). It should help all of us who want to use this infinitely malleable new feature :).
What?! Why? How? Just work, you field!

J

Sorry, but I don't know if and how much I can reveal from beta...
But there are some things you already seem to know from the vid, a few improvements:
Duplicate -> dup
I J GetCreeperCount -> I J GetCreeper
#3 is completely unnecessary
div needs 2 values (10 2 div -> 10/2=)

Grauniad

What we cannot do at this time is to discuss the specific set of CRPL commands or the capabilities of units using it. Those things are subject to change and to beta-test validation.

We can help you with syntax validation and with questions on how the language (Reverse Polish Notation) works in specific circumstances.

Also, refer to my PSA thread on this board to a link where you can play with a similar language to test how logic and stack operations function.

Quote from: Tiuipuv on December 24, 2012, 04:44:06 PM

#1
GetQueuedMoveCount eq0 if

Does eq0 turn the number on top of the stack into a true/false value (true if equals 0, false otherwise)? Then the if won't do anything unless the top of the stack is a true? That would make sense to me.

Yes, assuming that there is a command "GetQueuedMoveCount" then that will be on the stack as an integer. If it is 0, then the equation would evaluate to True.

This is how we would write it in stack notation:

0 -- 1


The zero queued moves will result in a True condition.

Quote
#2
CurrentCoords GetShallowestCreeperCoords

GetShallowestCreeperCoords is what I have inserted; there would be some complicated code here searching the map for the area with the lowest/no creeper, defining ties and such. It would be nice to just make things up like I did here :).

There was an interesting problem with stack order here. These sets of coords are later used for a spore (#6). This should work as long as I keep the stack under control, right?

Well, I see a logic problem here. For CurrentCoords you will have a single co-ordinate pair. THat would be the coordinates where the unit is located. That will only return one value - the depth of creeper at that location.

For you to do what you want, you'd have to devise a different algorithm. I'll leave that to you as a learning exercise. :)

Quote
#3
0

This 0 is because the do loop will be adding up a total count, and I think this would provide a number for it to add to. This could be subject to balancing in game, a nonzero number would provide a minimum spore amount. A negative number has interesting effects...

Not sure what you mean here.  Addition works as follows:

4 5 add

in stack notation:


4 5 -- 9


Quote

#4
CurrentY 3 add CurrentY 2 sub do

My entire exposure to do loops is what virgil showed in the video, so I probably have it all wrong. How could this be used correctly?

This could be rendered unnecessary with a clever command pre-built. Something like SetCreeperInRange and GetCreeperCountInRange.

Why does Virgil's add 2 and subtract 1? Does it have something to do with how the do loop handles the center square?

Virgil's code probably process a square of 9 cells centered around the current coordinates. Thus +1 and _1 from where the current {x,y} coordinate pair is located.

for your code, let's analyze it in stack notation again:

CurrentY 3 add CurrentY 2 sub do

Assume CurrentY is 40 and CurrentX is 36



40 3 -add- 43 40 2 -sub- 43 38 -do-


So now we can deduce that your do-loop will iterate over the values from 38 to 43.

Quote
#5
I J GetCreeperCount add

In the Video I noticed a strange I J, those seem to be taking information out of the do loop, but I don't understand the do loop to begin with. Why I and J, and how do their values get assigned?

Each do-loop has an internal index that gets adjusted from the starting index number (see above) to the limit of the do loop.  For the sake of this, that is what the I, J (and K) values are.  Simply the index for each nested loop.


Quote

#6
20 div Duplicate 20 mul CreateSpore

Here I use another unseen, but very necessary command. Where I put "Duplicate" I would take the current value from the top of the stack, and put it on top of the stack above itself. I don't see a workaround here, there must be some sort of command for it.

"div" stands for divide, and "mul" stands for multiply.

Here is where I create a spore, without providing enough information "directly" beforehand. I assume that it would be possible to retrieve older values from the stack in just the same way, in this case from #2.

You are absolutely right. RPL does have a "dup" and "dup2" operation to duplicate one or two stack items.

As for your code, it would fail from what I can see, since both division and multiplication requires two operands on the stack.

Here is how to get the square of 5 in a RPL.

5 dup *[/quote]

Stack notation"[code] 5-dup- 5 5 -*- 25



Hope that guides you a little on using RPL (and eventually CRPL. :)[/code]
A goodnight to all and to all a good night - Goodnight Moon

lurkily

#3
Here's an example of RPL in a vertical table.  One way to think of "20 2 div 5 mult" it is that it uses the operators to 'collapse' the values on the bottom of the stack.  It creates a stack of 2 over 20, and with Div, collapses them to 10.  Then it has the two operands necessary for the multiplication.

Most people used to modern language are probably going to have trouble thinking of their code as a stack of values, so some visualization can help.  For instance, 20 2 div 5 mult:
step 1 step 2step 3
mult
5
divmult
25
201050

It can also help to duplicate your code in a comment, and there, section it out to verify that you have enough operands for each item.  I used a personal notation kind of like this when first getting my shoes wet with CRPL (about a week ago) and still find that it helps when using long, complex strings.

# ((20 2 div) 5 mult)
20 2 div 5 mult

Grauniad

Quote from: lurkily on December 24, 2012, 06:35:41 PM
Here's an example of RPL in a vertical table.  One way to think of "2 20 div 5 mult" it is that it uses the operators to 'collapse' the values on the bottom of the stack.  It creates a stack of 2 over 20, and with Div, collapses them to 10.  Then it has the two operands necessary for the multiplication.


There's a problem with your example.


2 divided by 20 yields 0 as integer


Test it here: http://forthfreak.net/jsforth80x25.html
A goodnight to all and to all a good night - Goodnight Moon

Tiuipuv


0

CurrentY 3 add CurrentY 2 sub do

CurrentX 3 add CurrentX 2 sub do

I J GetCreeperCount add

I J 0 SetCreeper

loop

loop


The idea was to end up with a number on top of the stack, equal to the amount of creeper that had been in the area. Both J and Grauniad said that this doesn't happen. How could you achieve the result of a single number on the stack (the total amount of creeper) once the loop is done?

Quote from: Grauniad on December 24, 2012, 05:56:32 PM
Quote
#2
CurrentCoords GetShallowestCreeperCoords

GetShallowestCreeperCoords is what I have inserted; there would be some complicated code here searching the map for the area with the lowest/no creeper, defining ties and such. It would be nice to just make things up like I did here :).

There was an interesting problem with stack order here. These sets of coords are later used for a spore (#6). This should work as long as I keep the stack under control, right?

Well, I see a logic problem here. For CurrentCoords you will have a single co-ordinate pair. THat would be the coordinates where the unit is located. That will only return one value - the depth of creeper at that location.

For you to do what you want, you'd have to devise a different algorithm. I'll leave that to you as a learning exercise. :)

Where I put GetShallowestCreeperCoords, I'm not using anything previously on the stack. What it is supposed to mean is that it finds the X and Y coordinates on the map where the Creeper is shallowest. Perhaps I should have put FindShallowestCreeperCoords instead. Unless I have something completely misunderstood...

Quote from: Grauniad on December 24, 2012, 06:46:52 PM
Quote from: lurkily on December 24, 2012, 06:35:41 PM
Here's an example of RPL in a vertical table.  One way to think of "2 20 div 5 mult" it is that it uses the operators to 'collapse' the values on the bottom of the stack.  It creates a stack of 2 over 20, and with Div, collapses them to 10.  Then it has the two operands necessary for the multiplication.


There's a problem with your example.


2 divided by 20 yields 0 as integer


Test it here: http://forthfreak.net/jsforth80x25.html

So all numbers in the stack will be integers? Good. As much as it may get in the way, it will prove easier on my brain I think. Is that by rounding or flooring? But wait, in Virgil's picture he has a .8...

I do believe that lurkily meant 20 2 div, because that would match the table and the math.
What?! Why? How? Just work, you field!

Grauniad

Quote from: Tiuipuv on December 24, 2012, 08:13:53 PM
The idea was to end up with a number on top of the stack, equal to the amount of creeper that had been in the area. Both J and Grauniad said that this doesn't happen. How could you achieve the result of a single number on the stack (the total amount of creeper) once the loop is done?

Suppose we want to calculate the amount of creeper in a 3 x 3 cell around a tower at coordinates {x,y: 30,15}. Then, using this pseudo-code we can do it. This is more an example of the use of RPL than of CRPL, since you cannot rely that any command I use in the pseudo-code will eventually be implemented in CRPL.


#define a variable to hold the amount of creeper and set it to zero.
0->AllCreeper
# stack notation for above: 0 --

#set center X: Stack 30 --
30 ->MyX

#set center Y: Stack 15 --
15 ->MyY

#Calculate low and high X: There is a more elegant way, but the code gets increasingly complex.
# So I'm doing it in steps and hopefully you can follow.

<-MyX 1 add dup 2 sub ->LowX ->HighX
#stack notation: 30 1 -add- 31 -dup- 31 31 -sub- 31 29 ->LowX=29, HighX=31

#Outer loop for x
<-HighX <-HighY do

   #same for Y:
      <-MyY 1 add dup 2 sub ->LowY ->HighY
      #stack notation: 15 1 -add- 16 -dup- 16 16 -sub-16 14 ->lowY=14, HighY=16

       #inner loop for y
       <-HighX <-HighY do
             
            # the loop indexes are I for the y-coordinate (inner loop) and J for the outer (X) loop
             J I GetCreeper <-AllCreeper add ->AllCreeper
             #stack notation: (first iteration) 29 14 -GetCreeper- (assume creeper level 5) 5 0 -add- 5 ->
       
        Loop #inner loop
    Loop #outer loop

#we'll iterate over the loops and add creeper to the AllCreeper variable


Pretty sure I might have made a mistake, it's hard to be accurate without the aid of a compiler. :)

the condensed version of the loops (as Virgil probably used them) are:


<-MyX 1 add dup 2 sub do  #stack notation:30 1 -add- 31 -dup- 31 31 -sub- 31 29 -do-
  <-<-MyY 1 add dup 2 sub do #stack notation: 15 1 -add- 16 -dup- 16 16 -sub-16 14 -do-
      #code to execute goes here
  loop
loop
/code]

I hope this helps you to wrap your head around RPL code writing and design....
A goodnight to all and to all a good night - Goodnight Moon

Grauniad

Quote from: Tiuipuv on December 24, 2012, 08:13:53 PM

So all numbers in the stack will be integers? Good. As much as it may get in the way, it will prove easier on my brain I think. Is that by rounding or flooring? But wait, in Virgil's picture he has a .8...


If you do integer division, then the result will be integer (with modulus support).  There is support for floating point numbers and the core will convert as needed or you can explicitly convert.
A goodnight to all and to all a good night - Goodnight Moon

florrat

#8
Quote from: Grauniad on December 24, 2012, 05:56:32 PM
40 3 -add- 43 40 2 -sub- 43 38 -do-

So now we can deduce that your do-loop will iterate over the values from 38 to 43.
Excluding 43, right?




As far as I understand the (C)RPL (which is not very "far"), the code of Tiuipuv is correct and does what he wants (if the functions GetShallowestCreeperCoords, GetDeepestCreeperCoords and GetCreeperCount are (somehow) defined, and he replaces Duplicate by dup).

In the first iteration on the do loop, the stack is
<4 numbers from CurrentCoords GetShallowestCreeperCoords> 0
and then the command
I J GetCreeperCount add
first looks what the amount of creeper is on (I,J), say x, and then adds it to the 0 on the stack, so the stack would become
<4 numbers from CurrentCoords GetShallowestCreeperCoords> x
and the next iteration the same happens, it adds the amount of creeper on (I+1,J) to the last number on the stack (x). After all 25 iterations, the last number of the stack represents the total value of creeper in these 25 cells (before it was removed), and then he uses this value to make the spore.

This sounds perfectly legal to me.

Quote from: Tiuipuv on December 24, 2012, 04:44:06 PMThe more creeper it picks up, the faster the spore travels.
Wait, the speed of the spore is independent of the amount of creeper it picked up, right? Since CreateSpore does not have "spore speed" as argument in the version of the video.




EDIT: There will probably also be commands to interchange to elements on the stack, right? How do these work in stack bases languages? For example suppose that my stack is X Y Z and I want it to be (X+1) Y Z Then I first have to move X to the top of the stack, then add 1 to it, and then move it back, right? How can you achieve this?

lurkily

#9
Yes, "20 2 div 5 mult" was what I intended - corrected.  I got it right three out of four times, at least.

Anyway, the point of the exercise is to illustrate how the code 'thinks'.  A lot of modern languages are somewhat analogous to english in that you can toss in a few extra words here and there and it makes sense - the thought processes involved in the english language can guide you in structuring the code you write.  Because that isn't the case here, I think it's important to be able to visualize the processes the code goes through as it reduces itself to a result.

Quote from: Tiuipuv on December 24, 2012, 08:13:53 PMCurrentY 3 add CurrentY 2 sub do

CurrentX 3 add CurrentX 2 sub do

I J GetCreeperCount add

I J 0 SetCreeper

loop

loop


The idea was to end up with a number on top of the stack, equal to the amount of creeper that had been in the area. Both J and Grauniad said that this doesn't happen. How could you achieve the result of a single number on the stack (the total amount of creeper) once the loop is done?

0 ->CreeperTotal

#Repeat 5 times, for a height of 5
CurrentY 3 add CurrentY 2 sub do

#Repeat 5 times, for a width of 5
CurrentX 3 add CurrentX 2 sub do

#Get the creeper in this cell, and add it to a total
I J GetCreeperCount <-CreeperTotal add ->CreeperTotal

loop

loop
Does this look what you're trying to do?   You appear to be trying to count the total creeper in all cells in a 5x5 area, yes?

Tiuipuv

Grauniad:
Thank you! You clearly have a strong understanding of how this works right from the ground up.

Florrat:
Thank you for explaining what I was trying to say. I couldn't get all the steps so completely.

I said speed...oops. Health belongs there, but I suppose it works just the same anyway.

Interchanging elements of the stack would be very convenient, maybe if the situation was right it could be necessary.

Lurkily:
Yes, precisely.
What?! Why? How? Just work, you field!

Grauniad

#11
Quote from: florrat on December 24, 2012, 09:13:14 PM
Excluding 43, right?

I probably said it very badly.

The loop construct (here is a good reference) has the syntax:

limit index DO ... LOOP

The description is:
Quote
In Forth, you do this by specifying a beginning number and an ending number (in reverse order) before the word DO. Then you put the words which you want to have repeated between the words DO and LOOP. For example

  : TEST   10 0 DO  CR ." Hello "  LOOP ;

This will print the word "Hello" 10 times.

So yes, I think I made a mistake in specifying the bounds of the loop.

Edit: Fixed reference.
A goodnight to all and to all a good night - Goodnight Moon

florrat

@Grauniad: Could you please fix the link to the good reference, I'd like to see it.

@lurkily: That's what he's indeed trying to do, but - I think - also doing. I still think his code should work, unless the stack is emptied every line or so (which seems rather strange)... I'd like to hear more about your reasons why his code will (probably) not work, because you say stack he tries to use the add- and div-command while the stack has only 1 number in it, but that's not true, unless I'm missing something

I'd also like to hear (or read in a good reference :) ) how interchanging numbers on the stack works.

lurkily

#13
The line I referred to was:

20 div Duplicate 20 mul CreateSpore

Div only has a single operand, '20'.

Also,
I J GetCreeperCount add
gives 'add' only a single operand.

EDIT:By interchanging numbers, are you referring to the use of 'swap'?

florrat

In this post I assume the stack is not emptied every newline. If this is false, this whole message contains rubbish. And maybe I'm wrong in how stack-based languages work... In that case, sorry for my wrong statements below. If it makes you feel better: please read every sentence as if it started with "If my understanding of stack bases languages is correct ..."


@lurkily: I agree that the following two codes are invalid by themselves. 20 div dup 20 mul CreateSporeI J GetCreeperCount add

But, suppose these two lines are executed when there are already numbers on the stack (before the line is executed), then these lines can be executed correctly: they will use the last value which was on the stack to evaluate the div and the add (and use up even more numbers from the stack when resolving CreateSpore).

For example the first piece of code. Suppose, before this code gets executed the stack contains 5 numbers, and to simplify things, lets assume the last number is 200. So the stack is A B C D 200 for some numbers A, B, C and D.
After 20 is evaluated, the stack contains A B C D 200 20;
After div is evaluated, we remove the 200 and the 20 from the stack, and compute 200/20=10, so the stack contains A B C D 10;
After dup is evaluated, the last element of the stack is duplicated, so we get A B C D 10 10;
After 20 is evaluated, we get A B C D 10 10 20;
After mul is evaluated, we get A B C D 10 200 (10 and 20 are replaced by 200);
Now CreateSpore removes all these numbers from the stacks and creates a spore with the right properties.

And this is exactly what Tiuipuv code is doing.


Or maybe even simpler: when my code is
0

dup


If you read the line "dup" by itself, it is an invalid use. But in the code as above, the dup will just duplicate the 0 which was on the stack from two lines above (resulting in 0 0 as stack).


About "swap": probably, I don't know that command; could you describe what it does (probably easiest with an example).