how to move turtles to sequential targets and stop at endpoints - indexing

For clarification on this question, here is the original question with background information.
I have been attempting to make one agentset (ships) move towards another agentset (target-port) and once the ships arrive, move on to the next target (shortest distance away). What i have so far although its not working correctly:
ask ships
[ if distance target-port = 0
[ set target-port min-one-of ports with [who != myself] [distance myself]
face target-port ]
ifelse distance target-port < 1
[ move-to target-port ]
[ fd 1 ]
]
I would also like to have the ships stop moving once they've met the end of the path. (i.e port 0 or 2 in this specific scenario).
Here is an example of the entire code to make it easier to understand:
breed [ships ship]
breed[ports port]
ships-own [current-port target-port]
to setup
clear-all
let index 0
create-ports 3
[
let loc item index [ [4 -4] [ 9 5] [ -11 11] ]
setxy (item 0 loc) (item 1 loc)
set index index + 1
set shape "circle"
set size 5
set color red - 1]
ask ports
[let s who
set label ( word " Port " s )
hatch-ships 1
[ set current-port s
set size 10
set color red
pen-down
set pen-size 1
Set target-port min-one-of ports with [ who != s] [distance myself]
set heading towards target-port
set label (word "target " target-port)
] ]
reset-ticks
end
to go
ask ships
[ if distance target-port = 0
[ set target-port min-one-of ports with [who != myself] [distance myself]
face target-port ]
ifelse distance target-port < 1
[ move-to target-port ]
[ fd 1 ]
]
end
Any help would be greatly appreciated. Thanks

For the first part of your question, you just need to use other.
ask ships [
if (distance target-port = 0) [
let _otherports no-turtles
ask target-port [set _otherports (other ports)]
set target-port min-one-of _otherports [distance myself]
face target-port
]
ifelse (distance target-port < 1) [
move-to target-port
][
fd 1
]
]
You do not really provide enough info to answer the rest of your question, since your code forces ships to pick a new target once they arrive at their current target. One way to proceed is to give a ship a list of ports to visit, in order, and then stop when you reach the end of the list.

Related

Assign variable to breed based on percentage

I'm trying to assign my breed called "evacuees" their age based on a percentage. The number of evacuees is based on a slider in the interface, meaning that I don't have a fixed population to work with. They have two properties, "sex" and "age", which are both based on a percentage.
I assigned the sex the following way:
let women n-of (count evacuees * 0.513) evacuees
ask women [set sex "female"]
ask evacuees [if not member? self women [set sex "male"]]
That works fine if you only have two categories. But when you have more than two (I have five different age groups) this doesn't work anymore. I tried to still use n-of but with if conditions, so that the agents are not drawn from the whole pool of the evacuees, but only the ones that haven't had an age assigned yet:
set men-0-14 n-of (count evacuees with [sex = "male"] * 0.11) evacuees
ask men-0-14 [set age "0-14"]
ask evacuees [
if not member? self men-0-14 [
set men-15-19 n-of (count evacuees with [sex = "male"] * 0.04) evacuees with [sex = "male" AND
not member? self men-0-14]
]
]
ask men-15-19 [set age "15-19"]
ask evacuees [
if not member? self men-0-14 AND not member? self men-15-19 [
set men-20-39 n-of (count evacuees with [sex = "male"] * 0.26) evacuees with [sex = "male" AND
not member? self men-0-14 AND not member? self men-15-19]
]
]
ask men-20-39 [set age "20-39"]
... and so on for all five categories. But in the end I will still have some male evacuees that don't have an age assigned. I think that might be because of the usage of n-of, that it always draws from the whole evacuees, even if using if-conditions. Or it might be a problem of scheduling in NetLogo, that all of the evacuees are still part of the pool because the age group gets assigned definitely when the procedure is finished.
Is there another way to create the five agentsets that have an age assigned based on a certain percentage?
Here's a generic solution that lets you assign sexes and age-groups in a nice table format in setup, then applies those percentages of each group to however many turtles you have, and reports on the results. It seems to work.
globals [ sex-percentages age-percentages ]
turtles-own [ sex_code sex_label age_code age_label ]
to setup
clear-all
let delist []
;; assume the percent lists are % of total population desired, code, and label
set sex-percentages [
[0.4 "M" "male" ]
[0.6 "F" "female" ]
]
set age-percentages [
[0.2 1 "under 10" ]
[0.5 2 "11-30" ]
[0.2 3 "31-50" ]
[0.1 4 "over 50 " ]
]
create-turtles ( 100 + random 20) [set size 2 set shape "person" setxy random-xcor random-ycor
set delist assign sex-percentages
set sex_code first delist
set sex_label last delist
set label sex_code
set delist assign age-percentages
set age_code first delist
set age_label last delist
set label age_code
]
report-sexes
report-ages
reset-ticks
end
to report-sexes
let sexlist []
let n count turtles
ask turtles [ set sexlist lput sex_code sexlist ]
let sexes sort remove-duplicates sexlist
foreach sexes
[ x -> let thiscount length filter [ i -> i = x ] sexlist
let pct ( 100 * thiscount / n )
print (word x " has " thiscount " of " n " = " precision pct 3 " percent" )
]
print "Requested: "
foreach age-percentages [ x -> print x ]
end
to report-ages
let agelist []
let n count turtles
ask turtles [ set agelist lput age_code agelist ]
let ages sort remove-duplicates agelist
foreach ages
[ x -> let thiscount length filter [ i -> i = x ] agelist
let pct ( 100 * thiscount / n )
print (word x " has " thiscount " of " n " = " precision pct 3 " percent" )
]
print "Requested: "
foreach age-percentages [ x -> print x ]
end
to-report assign [ distribution ]
let chooser random-float 1 ;; returns value in range [0, 0.99999]
let assigned false
let running_sum 0
;; set default values in case the code isn't working correctly
let decode "?"
let delabel "?"
foreach distribution
[
x ->
let group-pct item 0 x
let group-code item 1 x
let group-label item 2 x
set running_sum ( running_sum + group-pct)
if ( running_sum > 1) [ print "ERROR - total is over 100%" stop]
if (( assigned = false ) and ( chooser <= running_sum))
[ set decode group-code
set delabel group-label
set assigned true
]
]
report (list decode delabel )
end

Can a turtle variable "logged" for different patches?

[ifelse ( random-float 1 < 0.99 ) [
set security-apprehension security-apprehension + 1 ][
set successful-shoplifts successful-shoplifts + 1 ]
The above is from a section of coding related to shoplifter behaviour and shows two turtles-own variables (security-apprehension and successful-shoplifts), one of which will increase and the other remain the same. This can only occur when a turtle is on a certain patch (A store). I would like 'security-apprehension' to resort back to 0 when the turtle is not on that patch and for the score to be 'logged' i.e. go back to what it was previously when the turtle is back on the patch so I can set a criteria to determine whether a shoplifter should be considered a prolific offender to individual stores.
How can this be achieved?
I'm not 100% sure on the output you're after, but here's an attempt that makes use of the table extension to build a turtle-specific dictionary to store patch coordinates as a key paired with the security apprehension level of the corresponding patch.
First, the setup:
extensions [ table ]
turtles-own [ security-table current-security-apprehension]
to setup
ca
ask n-of 20 patches [
set pcolor green
]
crt 1 [
setxy random-xcor random-ycor
set security-table table:make
set current-security-apprehension "NA"
]
reset-ticks
end
Now, you can have your turtles check if they're at a 'store'. If they are, check if the store already has an associated security apprehension level- if it does not, assign one. Then, query that table to get the appropriate security apprehension level for the current store (more details in comments).
to go
ask turtles [
set current-security-apprehension "NA"
rt random 91 - 45
fd 1
; If you're at a 'store'
if [ pcolor ] of patch-here = green [
; Use the pxcor-pycor pair in a list as a dictionary
; key to store/check security apprehension in a table
let this-key list pxcor pycor
; Check if the store has been visited
if not table:has-key? security-table this-key [
; If not, store the security value for this store
; (randomly chosen, in this example- how you set this
; depends on your model)
table:put security-table this-key one-of [ "high" "medium" "low" ]
]
; Get the security apprehension level for the current patch
set current-security-apprehension table:get security-table this-key
]
if current-security-apprehension != "NA" [
show ( word "Security apprehension on " patch-here " is " current-security-apprehension )
]
]
tick
end
A modified version of the above as per clarification in comments:
extensions [ table ]
turtles-own [ security-table shoplift-table current-security-apprehension]
to setup
ca
ask n-of 20 patches [
set pcolor green
]
crt 1 [
setxy random-xcor random-ycor
set security-table table:make
set shoplift-table table:make
set current-security-apprehension 0
]
reset-ticks
end
to go
ask turtles [
set current-security-apprehension "NA"
rt random 91 - 45
fd 1
; If you're at a 'store'
if [ pcolor ] of patch-here = green [
; Use the pxcor-pycor pair in a list as a dictionary
; key to store/check security apprehension in a table
let this-key list pxcor pycor
; Check if the store has been visited, add shoplift
; and security values as needed
if not table:has-key? security-table this-key [
table:put security-table this-key 0
table:put shoplift-table this-key 0
]
; Try to shoplift- if random value 0-1 is less than
; 0.98, count as a success. Otherwise, add one to
; security score
ifelse random-float 1 < 0.98 [
; Increase the current shoplifting value by one
let cur-shop table:get shoplift-table this-key
table:put shoplift-table this-key cur-shop + 1
] [
; Otherwise, increase the security apprehension by 1
let cur-sec table:get security-table this-key
table:put security-table this-key cur-sec + 1
print "Caught you red-handed."
; Check if they have been caught here 2 or more times:
if table:get security-table this-key >= 2 [
print "CALL THE POLICE!"
]
]
]
]
tick
end

how to hatch turtles that face closest neighbor of agentset doing the hatching

I currently have one agentset(ports) hatching another agentset(ships).
The idea is to have the ships face the closest port to their current location.
[let target min-one-of ports [distance myself]
face target].
Unfortunately this makes the ships face their current location since they are being hatched at a given port. If there is no way to exclude the port they hatch on- I have an index of the locations(ports) and could potentially set the target as the following item in the index however I am not sure how I would accomplish this. any suggestions?
full code example
breed [ships ship]
breed[ports port]
to setup
let index 0
create-ports 3
[ let loc item index [ [459 -324] [670 -233] [677 -356] ]
setxy (item 0 loc) (item 1 loc)
set index index + 1
set shape "circle"
set size 5
set color red - 1]
ask ports
[ hatch-ships 1
[ set size 10
set color red
pen-down
set pen-size 1
let target min-one-of other ports [distance myself]
face target] ]
reset-ticks
end
You can assign the who value of hatching port to the ship as their current port and define their target port as the closes port which is not the current port.
breed [ships ship]
breed[ports port]
ships-own [currentPort targetPort]
to setup
clear-all
let index 0
create-ports 3
[
; let loc item index [ [459 -324] [670 -233] [677 -356] ]
let loc item index [ [4 -4] [ 9 5] [ -11 11] ]
setxy (item 0 loc) (item 1 loc)
set index index + 1
set shape "circle"
set size 5
set color red - 1]
ask ports
[
let s who
set label ( word S " Port " s )
hatch-ships 1
[ set currentPort s
set shape "sailboat side"
set size 10
set color red
pen-down
set pen-size 1
Set targetPort min-one-of ports with [ who != s] [distance myself]
set heading towards targetport
set label (word "target " targetport)
] ]
reset-ticks
end

Ask for the value of a variable of all turltes in Netlogo

Hello i have the next code to give a value to the variable "payoff" of the population of turtles with 3 different colors
turtles-own
[
payoff
]
to pay
let nearby other turtles in-radius 1
ask turtles with [color = blue]
[
if any? nearby with [color = red]
[
set payoff -1
]
]
end
So what i want to do is check the payoff of the turtles with color blue and if the payoff is less than 0 (i.e -1) they change their color to red, but i need to do this for each individual blue turtle so what code can i use? I try using "one-of" and "any?" but i think that this code its not for the purpose that i want. Any suggestions?
ask turtles with [ color = blue ] [
if payoff < 0 [
set color red
]
]
Alternatively:
ask turtles with [ color = blue and payoff < 0 ] [ set color red ]

NetLogo permission oddities

I'm having issues with my netlogo program. Code follows:
globals[
growth-param
money-size-ratio
]
turtles-own[
location
tsize
bbalance
]
to setup
ca
reset-ticks
ask patches[set pcolor blue]
create-turtles initial-telemarketers [
set size 1
set bbalance 0.0
setxy random-xcor random-ycor
set shape "circle"
]
set growth-param 1000
set money-size-ratio 0.001
end
to go
ask patches[set pcolor blue]
sell
accounting
observer-updates
tick
end
to sell
let territory 10 * sqrt size
let maxcalls 100 * size
ask n-of maxcalls patches in-radius territory[
if pcolor = blue [set pcolor black]
set bbalance bbalance + 2
]
end
to accounting
let cost size * 50
ask turtles[
set bbalance bbalance - cost
ifelse bbalance < 1
[die]
[set size bbalance * growth-param]
]
end
to observer-updates
end
It's supposed to be a model of how many telemarketing companies interact, simplistically. It's from Railsback & Grimm's modeling book.
Each time it tries to run, it provides two problems that I can see: in procedure sell, it doesn't want to set bbalance to the new value because it is turtle-only, and tick is observer-context only.
Thanks for any help!
globals[
money-size-ratio
]
turtles-own[
location
tsize
bbalance
maxsize
]
to setup
ca
reset-ticks
ask patches[set pcolor blue]
create-turtles initial-telemarketers [
set size 1
set bbalance 0.0
setxy random-xcor random-ycor
set shape "circle"
set maxsize 0
]
set money-size-ratio 0.001
end
to go
ask patches[set pcolor blue]
ask turtles [sell]
ask turtles [accounting] ;; let's ask the turtles to do this
observer-updates
tick
end
to sell
let territory 10 * sqrt size
let maxcalls 100 * size
if maxcalls > 40401[
set maxcalls 40401;keeps maxcalls within acceptable bounds
]
let coun 0
ask n-of maxcalls patches in-radius territory[
if pcolor = blue[
set pcolor black
set coun coun + 2
]
]
set bbalance bbalance + coun
end
to accounting
let cost size * 50 ;; size is a turtle variable so if you want to access it this way, let's make the whole thing
;; a turtle procedure. That's what was confusing Netlogo about the tick command
set bbalance bbalance - cost
if bbalance > growth-param
[set size size + (bbalance - growth-param) * money-size-ratio
set bbalance growth-param
]
if size > maxsize[
set maxsize size
]
if bbalance <= 0
[show (word "dead. Maximum size: " maxsize)
die
]
if size = 0
[show (word "dead. Maximum size: " maxsize)
die
]
end
to observer-updates
end
sell is a turtle procedure (because it uses turtle primitives such as size and in-radius). But go is an observer procedure. You can't call a turtle procedure directly from an observer procedure; you need to specify which turtles you want to run it. Inside go, I think you may have meant to write ask turtles [ sell ] instead of just sell.