Cheat Sheet

Buzz Syntax Cheatsheet

Comments

# This is a comment

File inclusion

include "otherfile.bzz"

# NOTE: A specific file can be included only once.
# Any 'include' statement for a file is ignored after the first inclusion
# occurred.
# Relative paths are automatically transformed into absolute paths before
# including a file.

Variables

# assignment (by default variables are global)
x = 2.55   # number
x = "ciao" # string

# local variables
function f() {
   var x = 42
   # do stuff with x
}

# printing on the ARGoS logger
log("INFO: x = " , x)

Conditionals

# simple if/then
if (x > 3) {
   log("x is too big")
}

# if/else
if (x > 3)
   log("x is too big")
else if (x < 3)
   log("x is too small")
else
   log("maybe I just don't like x")

# checking for equality
if x == 3
   log("x is equal to 3")

# checking for inequality
if (x != 4)
   log("x is different from 4")

# combining conditions with OR
if (x < 3) or (x > 3)
   log("x is not 3")

# combining conditions with AND
if ((x > 3) and (y > 3))
   log("x and y are too big")

# negating a condition
if (not (x < 3))
   log("x is <= 3")

String

x = "This is buzz"
y = "language"

# Getting length of string
log("Length of string x: ", string.length(x))

# Return a substring, string.sub(i,j)
# The substring starts at i. 
# If the third argument j is not given, the substring will end at the end of the string. 
# If the third argument is given, the substring ends at and includes j.
z = string.sub(x, 3)

# Concatenate a string
z = string.concat(x," ",y)

# Converting type to string
z = string.tostring(5512)

# Converting type to int
z = string.toint("2")

# Converting type to float
z = string.tofloat("3.6")

Loops

# 'while' loop to print 1 2 3 4 5
x = 0
while (x < 5) {
   x = x + 1
   log(x)
}

Tables

# creating an empty table
t = {}

# creating a table with some initial value
t = { .x=3 }

# using the contents of a table: two equivalent ways
log("t.x = ", t.x)       # dot syntax
log("t['x'] = ", t["x"]) # string syntax

# printing the contents of a table: a custom function
function table_print(t) {
  foreach(t, function(key, value) {
      log(key, " -> ", value)
    })
}

# tables are always passed by reference!
t1 = { .x=3 }
t2 = t1      # now t2 points to the contents of t1 -> no deep copy
t2.x = 5
log(t1.x)    # prints 5, not 3!

# copying tables the right way
function table_copy(t) {
  var t2 = {}
  foreach(t, function(key, value) {
      t2[key] = value
    })
  return t2
}

t1 = { .x=3 }
t2 = table.copy(t1)
t2.x = 5
log(t1.x)    # prints 3
log(t2.x)    # prints 5

# prints the number of elements in a
log(size(a))

Functions

# defining a function
function my_fun(p) {
   log("Called my_fun(", p, ")")
}

# returning a value
function my_add(a, b) {
   return a + b
}

# creating a lambda
lambda = function(a, b) {
   return a + b
}
lambda(1,2)

Math

# All the math functions are part of the 'math' table
# Functions consists of: abs, log, log2, log10, exp, sqrt, min, max, pi
# Trigonomerty functions: sin, cos, tan, asin, acos, atan2

# Example of usage
a = math.abs(-3)
b = math.min(332,42)

# Setting a 2D vector from length and angle
function vec2_new_polar(length, angle) {
   var vec2 = {
      x = length * math.cos(angle)
      y = length * math.sin(angle)
   }
   return vec2
}
v = vec2_new_polar(2, math.pi/3)

# Summing two 2D vectors (v1 = v1 + v2)
function vec2_sum(v1, v2) {
   v1.x = v1.x + v2.x
   v1.y = v1.y + v2.y
}
v1 = { .x=1, .y=2 }
v2 = { .x=3, .y=1 }
vec2_sum(v1, v2)

# Getting the angle of a 2D vector
function vec2_angle(v) {
   return math.atan2(v.y, v.x)
}


# Random

# Set seed
rng.setseed(11)

# No arguments: [-int_max,int_max]

# One argument A:
#  A is BUZZTYPE_INT: [0, A]
#  A is BUZZTYPE_FLOAT: [0.0, A]

# Two arguments (A,B):
#   Both A and B are BUZZTYPE_INT: [A, B] as BUZZTYPE_INT
#   A is BUZZTYPE_INT and B is BUZZTYPE_FLOAT: [A.0, B] as BUZZTYPE_FLOAT
#   A is BUZZTYPE_FLOAT and B is BUZZTYPE_INT: [A, B.0] as BUZZTYPE_FLOAT
#   Both A and B are BUZZTYPE_FLOAT: [A, B] as BUZZTYPE_FLOAT

x = rng.uniform()


# No arguments: 1 stddev, 0 mean
# 1 argument A: A stddev, 0 mean
# 2 arguments (A,B): A stddev, B mean

x = rng.gaussian()

I/O

# Open file for reading("r") or writing("w")
f = io.fopen("text.txt", "w")

# Writing to a file
io.fwrite(f, "Buzz", "Swarm")

# Reading and iterating a file 
f = io.fopen("text.txt", "r")
io.fforeach(f, function(line) {
    print(f.name, ": ", line)
    })
}
io.fclose(f)

Swarm management

# creation of a swarm with identifier 1
s = swarm.create(1)

# Join the swarm if the robot identifier (id) is even
# - 'id' is an internal symbol that refers to the
#   numeric id of the robot executing the script
# - % is the modulo operator
s.select(id % 2 == 0)

# Join the swarm unconditionally
s.join()

# Leave the swarm if the robot id is greater than 5
s.unselect(id > 5)

# Leave the swarm unconditionally
s.leave()

# Check whether a robot belongs to s
if(s.in()) { ... }

# Assigning a task to a swarm
s.exec(function() { ... })

# a, b are swarms defined earlier in the script
# Create new swarm with robots belonging to both a and b
# The first argument is a unique swarm identifier
i = swarm.intersection(100, a, b)

# Create new swarm with robots belonging to a or b
u = swarm.union(101, a, b)

# Create new swarm with robots belonging to a and not to b
d = swarm.difference(102, a, b)

# Create a new swarm n as the negation of swarm s
n = s.others(103)

Neighbor management

# Iteration (rid is the neighbor's id)
neighbors.foreach(
  function(rid, data) {
    log("robot ", rid, ": ",
        "distance  = ", data.distance, ", ",
        "azimuth   = ", data.azimuth, ", ",
        "elevation = ", data.elevation) })

# Transformation
cart = neighbors.map(
  function(rid, data) {
    var c = {}
    c.x = data.distance * math.cos(data.elevation) *
          math.cos(data.azimuth)
    c.y = data.distance * math.cos(data.elevation) *
          math.sin(data.azimuth)
    c.z = data.distance * math.sin(data.elevation)
    return c
  })

# Reduction (accum is a table)
# with values x, y, and z, initialized to 0
result = cart.reduce(function(rid, data, accum) {
    accum.x = accum.x + data.x
    accum.y = accum.y + data.y
    accum.z = accum.z + data.z
    return accum
  }, {.x=0, .y=0, .z=0})

# Filtering
onemeter = neighbors.filter(function(rid, data) {
    # We assume the distance is expressed in centimeters
    return data.distance < 100 })

# Listening to a (key,value) pair
neighbors.listen("key",
   function(vid, value, rid) {
      log("Got (", vid, ",", value, ") from robot #", rid)
   }
)

# Stopping listening to a key
neighbors.ignore("key")

# Broadcasting a (key,value) pair
neighbors.broadcast("key", value)

Virtual stigmergy

# Create a new virtual stigmergy
# A unique id (1 here) must be passed
v = stigmergy.create(1)

# Write a (key,value) entry into the structure
v.put("a", 6)

# Read a value from the structure
x = v.get("a")

# Get the number of keys in the structure
log("The vstig has ", v.size(), " elements")

# Return local value if
#  Remote value is smaller than local, OR
#  Values are equal, robot of remote record is smaller than local one
v.onconflict(function(k,l,r) {  
    if(r.data < l.data or (r.data == l.data and r.robot < l.robot)) {
        return l
    }
    # Otherwise return remote value
    else return r
})