Is there an else command in netlogo? - netlogo

I am trying to create a program in netlogo where there are blocks that come down the screen and when their y-coordinate reaches a certain value they reverse their direction and move in the opposite way.
So far I was able to make them move in one direction and then switch directions when they reach the critical y-coordinate value, but once they take one step in the reverse direction it glitches and they get stuck moving one step forward and one step backward.
I wanted to know if there was an else command in netlogo so I could specify that if the while command wasn't fulfilled it could reverse its direction and move without glitching.
Here is my code.
to maze
while [abs pycor < 16 ] [fd 1 wait .1]
bk 1 wait .1
end

There is no separate else keyword in NetLogo, but the ifelse command allows you to specify two blocks: one that is executed if the condition is true, and another (the "else" block) that is executed if the condition is false.
It seems, however, like you should rethink your general approach to the problem. Turtles in NetLogo always face in a particular direction, and you could take advantage of that: instead of having them "back up", you could have them turn around.
Also, it's generally ill-advised to try to do things in a while loop. If you want your turtles to repeat a behavior, a "forever button" is usually the way to go.
In the following example, you should call the go procedure from a forever button:
to setup
clear-all
ask patches with [ pycor = max-pycor - 1 ] [
sprout 1 [
set heading 180 ; head down
]
]
reset-ticks
end
to go
ask turtles [
if abs pycor = max-pycor [
rt 180 ; turn around!
]
fd 1
]
tick
end
This probably doesn't achieve exactly what you wanted, but there is a good chance that you can modify it to fit your needs.
Also note that this will work better using tick-based updates.

Related

Netlogo: subtracting previously diffused values

Is it possible to subtract previously diffused values?
I have a land-use model where residential use (yellow patches) diffuses its land value with the diffuse primitive:
diffuse land-value 1
In the first image below, land value is represented as white tones, the brighter the tone, the higher the land value. Residential use sometimes abandons the patch, but their land value influence stays (second image). Is there a way that, when the land use disappears, the value it previously diffused to all patches be subtracted and also disappear?
Following comments under the question and following Luke's suggestion of framing the diffusion of land-value as a function of distance instead of a recurring diffuse, I have set up the following solution (in point 1).
Below (in point 2), you find a possible approach (not fully coded, but sketched-out enough) for addressing the issue if you want to stick to diffuse.
1 - Approach with function of distance
What happens here is that, when a patch gains residential status (to create-residence), all other patches in a certain radius calculate how much spill-over land-value they get based on the residential value of the new residential patch and on how much it is distant (to-report diffused-value).
The advantage of this approach is that this calculation is fully replicable at any moment because it is based on two constants: the distance between patches and the initial residential value of the patch in question (for which I created the patches-own own-residential-value, distinct from the general land-value).
For this reason, when a patch loses residential use (to dismantle-residence) it is possible to perform the same calculation but, instead of having patches add diffused-value to their land-value, they will subtract it.
I think the code I place below best illustrates its functionality if you create the create-residence and dismantle-residence buttons in the Interface, and play with them to see how overlapping land-values add and subtract in the View.
globals [
; Agentsets for patches.
residence
non-residence
]
patches-own [
land-value
own-residential-value
]
to setup
clear-all
set non-residence (patch-set patches)
set residence (patch-set)
end
to create-residence
let new-res one-of non-residence
ask new-res [
set non-residence (patch-set other non-residence)
set residence (patch-set self residence)
set own-residential-value (random 10) + 1
set land-value (land-value + own-residential-value)
set pcolor yellow
diffuse-value
]
update-colours
end
to diffuse-value
ask other patches in-radius 10 [
set land-value (land-value + diffused-value)
]
end
to dismantle-residence
let target one-of residence
ask target [
set residence (patch-set other residence)
set non-residence (patch-set self non-residence)
; As opposed to 'to create-residence', where 'diffuse-value' is at the end of this block of commands,
; here 'subtract-value' has to be placed before the patch updates its 'own-residential-value' to 0,
; because that value is needed to calculate 'diffused-value'.
subtract-value
set land-value (land-value - own-residential-value)
set own-residential-value 0
]
update-colours
end
to subtract-value
ask other patches in-radius 10 [
set land-value (land-value - diffused-value)
]
end
to-report diffused-value
; Here, 'myself' is the new residential patch (as 'new-res' in 'to create-residence') or
; the new non-residential patch (as 'target' in 'to dismantle-residence').
let d distance myself
let v [own-residential-value] of myself
report v * (0.9 / d) ; Just an arbitrary function of value and distance.
end
to update-colours
ask non-residence [
set pcolor scale-color white land-value 0 15
]
end
2 - Approach if sticking to diffuse
I have though of an approach for this case too, but I also want to understand if diffuse really is what you want to use.
As we know, diffuse is a zero-sum game: what is diffused by a patch is also lost by a patch.
Therefore, I imagine you will not be just using diffuse land-value 1, because in that case land-value of the residential patch will be 0 after one tick, will very slightly recover on the subsequent tick, and will then progressively approach 0 from the third tick on.
For example, the following code gives the results as in the table below:
patches-own [
land-value
]
to setup
clear-all
reset-ticks
ask patch 0 0 [set land-value 50]
end
to go
diffuse land-value 1
tick
end
I doubt this is anything you are interested in replicating, so I assume the approach would be something like:
patches-own [
land-value
temp
]
to setup
clear-all
reset-ticks
ask patch 0 0 [set land-value 50]
end
to go
diffuse-value
tick
end
to diffuse-value
ask patches [
set temp land-value
]
diffuse land-value 1
ask patches [
set land-value (land-value + temp)
]
end
However, I think that even in this case diffuse seems to be not fit for representing a residential value spreading to near-by areas. By using the code above, in fact, the result is the following:
The table above shows that, in 15 ticks, the patch which should be the one diffusing some value in the area experienced a 93593% increase (no, I didn't forget any decimal point!) in its land value. I know of course this might be mitigated with some formula, but I think it shows the tendency of diffuse in this case: to create an escalating positive feedback between patches, so that a small residential value grows without control.
I'm not the expert of residential values here, but I felt these results (from both the former and the latter use of diffuse) were worth pointing out from a NetLogo perspective.
That said, if the idea is to stick to diffuse...
patches-own [
land-value
own-residential-value
residential-start
temp
]
to setup
; Some code.
end
to go
; Some code.
end
to create-residence ; Executed by the observer. This procedure cannot be executed by the patch becoming residence because it contains 'diffuse'.
let target ; <- Identify here the patch that needs to become residence.
ask target [
; Set 'own-residential-value' to something.
set land-value (land-value + own-residential-value)
set residential-start ticks
]
; Have some code here that uses 'diffuse own-residential-value'.
end
to dismantle-residence ; Executed by the observer. This procedure cannot be executed by the patch being dismantled because it contains 'diffuse'.
ask patches [set temp 0] ; This is crucial in order to avoid any overlap among patches when using 'diffuse'.
let target ; <- Identify here the patch that needs to be dismantled.
let time-as-residence (ticks - [residential-start] of target)
ask target [
set temp own-residential-value
]
repeat time-as-residence [
; Insert here the exact same code that
; was used for using 'diffuse' but
; diffusing the 'temp' variable instead
; (e.g. 'diffuse temp 1').
]
ask patches with [temp > 0] [
set land-value (land-value - temp)
]
end
What happens above is that, whenever a patch loses residential use, the program performs exactly the same number of diffuse operations as it performed when actually diffusing land-value during the residential life of the patch at stake, but on temp instead of land-value. This way, all the surrounding patches will store in temp the same value they gained over time from the patch being dismantled - so they can subtract this value from their current land-value.
The success of this approach depends on the ask patches [set temp 0] statement: given that diffuse operates on each patch, by setting all temp to 0 and then doing ask target [set temp own-residential-value] we make sure that we only reproduce the pattern of value-diffusion that can be attributed to the patch being dismantled - avoiding any overlap that might have occurred over time, when patches may have gathered (and then re-diffused) value from other residential patches.
(This is based on the assumption that you use diffuse at every tick, as you said in a comment to the question. Even if that ceases to be the case, it will be easy to set time-as-residence in an alternative way according to the number of times that diffuse took place since a particular patch became residential)
Potential problem This is something that you will have to untangle yourself, but consider that there remains a possible issue: you have to decide whether you want to diffuse own-residential-value or land-value, with both options presenting some problem.
Diffusing own-residential-value seems intuitive to me, since that is the added value; however, this means that the diffused value would go into own-residential-value of the other patches (and not into their land-value) even if they really do not have any residential value of their own, which will create the need for extra computation (a possible option could be to rename own-residential-value to something more appropriate, like residential-value, and create a further tot-value patches-own variable that is updated at every tick as set tot-value land-value + residential-value).
On the other hand, diffusing land-value would be more straightforward in terms of coding (land-value would just propagate to other patches' land-value) but seems less precise based on what I can understand, given residential patches would be propagating land-value which often will not be just the new residential value that they bring, but also the result of that positive feedback discussed before, building on other patches' residential values.
Conclusions
While I'm quite confident that the second approach is viable and technically good, I definitely prefer the first based on the doubts that I expressed over the use of diffuse for this particular goal (at least based on the understanding I have of your intentions, which I might not understand fully) - and the feeling that a function of distance looks like a neat approach to diffusion of value in this scenario.

Set value of speed slider programmatically

In setup, I draw a bunch of turtles--as small circles--to display two curves defined by functions. A very simple way to do this is
ask patches with [pycor = (myfunction pxcor)] [sprout 1 [...]]
and that's what my code does at present. It's kind of wasteful, since every patch has to be consulted--in random order--for each curve, but it's simple and easy to read, and it only happens during setup.
However, there's a little bit of a pause as the curves are constructed. If I move the speed slider all the way to the right, the pause is not noticeable. If I wrap the curve display routines in no-display and display, the user doesn't see the curves being constructed, but the speed is unchanged, AFAICS. If I move the slider to the left, it takes a long time to construct the curves even with no-display; the user doesn't see the points being placed one by one, but nevertheless has to wait while twiddling her/his thumbs.
Is there a way to set the model speed programmatically (for normal, "headfull" use)? I don't want to tell users "Move the speed slider to the right, then press setup, then move it back to the center before pressing go.
If not, maybe I'll code the curves properly using loops, but I thought I'd ask. Seems like there would be a way to do this, but I haven't found anything in the dictionary or programming docs so far.
(edit: no-display, if it did help, isn't available in NetLogo Web, which I am targetting along with regular NetLogo.)
I don't believe there is. However, you are asking all patches, when you could simply ask the pxcor values. This should speed it up a lot - square root of the number of iterations if a square world. Something like:
to testme
clear-all
let counter min-pxcor
while [counter <= max-pxcor]
[ let fn-out (function counter)
if fn-out >= min-pycor and fn-out <= max-pycor
[ ask patch counter fn-out [ set pcolor red]
]
set counter counter + 1
]
end
to-report function [#invalue]
report #invalue ^ 2
end

Constraining Movement of Agents to a Home Range in Netlogo

I'm relatively new to NetLogo, and I'm working to model moose density in New Hampshire and its correlation to winter tick parasitism.
I'd like to program my moose agents to move randomly within a set home range (~5km2), that originates from the randomly chosen patch they first enter the model on.
I'm not really sure how to bound agents based on area, rather than just patch color... Any suggestions on how to do this would be most appreciated!
Thank you!
General stackoverflow tip: typically, stackoverflow encourages specific programming questions. So including the code you've actually tried so far is generally preferred.
Alright, on to your problem.
One really simple way to do this is, first, store the mooses' starting patch. Second, when the moose is moving around, check the distance to the starting patch. If the distance exceeds the starting amount, have the moose towards the starting patch. Here's some template code to give you ideas:
breed [ mooses moose ]
mooses-own [
starting-patch
]
to setup
clear-all
;; only using one moose as it's easier to see the behavior
create-mooses 1 [
setxy random-xcor random-ycor
set starting-patch patch-here
]
reset-ticks
end
to go
ask mooses [
move
]
tick
end
to move
;; If farther than 10 patches from starting patching, take a step towards starting patch, otherwise, move randomly
ifelse distance starting-patch > 10 [
face starting-patch
] [
rt random 90
lt random 90
]
fd 1
end

When using the forward command is the movement specified carried out after each tick?

I am trying to make turtles move along fixed paths that the user can draw in the u.i. The forward command can make turtles move a certain fraction of a patch forward per tick I assume, however to instigate smooth movement would it be possible to specify a fixed movement per tick in the setup commands for turtles? If this is possible what would be the basic structuring of the code I would use to achieve this?
The fd command (bk as well) accept floating-point inputs. I.e.
Ask turtles [ fd .01 ]
Makes each turtle move forward 1/100th of a patch. This movement happens at the time of the command.
Tick does not have any connection to when commands are carried out. If you set view updates to on ticks it can effect when you see updates otherwise it is usually a scheme for keeping track of how many times go has run.
A sample model of turtles moving at different speeds.
Turtles-own [speed]
To setup
Crt 100[
Set speed random-float 1
]
End
To go
Ask turtles[ rt 1 fd speed]
End
Copy and paste that into a new model make setup and go buttons. Mess with it for a while.

In NetLogo how agents actions are performed?

In my go function I have a few conditions which might be true and then call an action, if more than one condition are true does it mean in one tick agents can do more than one action ? or in another case I have a function that agents have to move to a target and after facing the target agent should find the distance and fd 1 until reaches the target, does it mean it should take n ticks to complete?
to move [t]
face t
let n distance self t
repeat n
[fd 1]
end
to go
action 1 = > [move]
action 2
action 3
tick
end
I need the agents to do only one task at the time, and I am not sure how to make sure that for example not all the agents have the same target! sorry if these questions are out of context but I am new to Multi-agent modeling.
This is a great question!
First, specific answers:
if more than one condition are true does it mean in one tick agents can do more than one action ?
Just to be clear, are you talking about a situation like this?
to go
ask turtles [ move ]
tick
end
to move
if xcor > 5 [ fd 1 ]
if ycor > 7 [ rt 15 ]
if color = red [ bk 2 ]
end
If so, then yes, if xcor > 5, ycor > 7, and color = red are all true, the turtle will move forward 1, turn right 15, and move backward 2. The main way to prevent this is by using a sequence of ifelses:
to move
ifelse xcor > 5 [
fd 1
] [
ifelse ycor > 7 [
rt 15
] [
if color = red [ bk 2 ]
]
]
end
That way, the second condition (ycor > 7) will only be looked at if the first condition (xcor > 5) is false. Similarly, the third condition will only be looked at if the first two fail.
I have a function that agents have to move to a target and after facing the target agent should find the distance and fd 1 until reaches the target, does it mean it should take n ticks to complete?
I would recommend taking n ticks to complete it. Otherwise, only one turtle will move to its target at a time! However, repeat n [ fd 1 ] will make the turtle go forward n all at once. In fact, it's the same as fd n. The repeat block will finish before the turtle is done performing the move procedure.
You can edit your move function as follows to get it to take n ticks:
to move [t]
face t
fd 1
end
Then, just have a condition to look for when the turtle gets to its target (for example, distance t < 1) and then do something accordingly.
I recommend just messing around with these various techniques with multiple turtles using them so you can get a feel for the differences.
I am not sure how to make sure that for example not all the agents have the same target!
This depends quite a bit on context. Supposing there is a turtles-own variable called target that stores each turtle's target, you could do something like this:
to-report get-available-target [ possible-targets ]
report one-of possible-targets with [ not any? turtles with [ target = myself ] ]
end
get-available-target will report a random agent from possible-targets that is not anyone's target. one-of just gets random agent from an agentset.
How can I schedule tasks in netlogo, I have conditions and actions but how can I make the agents do one task at the time?
Often this just takes care of itself. For example, say, when an agent is hungry, it should walk over to a food supply and eat. As it's walking over, you don't want it to go off and do anything. However, it will still be hungry, so if you've used an ifelse, it will just keep going to the food supply. Thus, your agent stays focused for free! In general, it's best to design your conditions such that they remain in effect until the agent addresses them. You can order them in an ifelse chain or something similar to establish the general priority of actions (for instance, if the agent walking to the food supply is threatened by a predator, it should still run away).
If you really want to the agent to do something for several ticks, you'll basically just extend this same idea, but in a more artificial way. For instance, if an agent should walk forward three times, have a turtles-own variable set to three. If that variable is greater than zero, the agent walks forward and decreases that variable, and doesn't do anything else.
#Bryan Head already answered your question, I had the same problem when I started Netlogo and agent based modeling, So I have added a current-task variable and in my Go Procedure I have added a function to check all the conditions and set the task of agents and when the task is completed the variable is set to "" again. This might be useful for your case as well.
if current-task = "move" [move]
if current-task = "A1" [A1]
if current-task = "..." [...]
if current-task = "" [select-current-task]