diff --git a/src/core/utils.jl b/src/core/utils.jl
index ddffe480275f34dc7980a58753a2e05f7faf53cb..27ef4d7d9efbba4cfcc8e3f21eba3e50ad64a7cf 100644
--- a/src/core/utils.jl
+++ b/src/core/utils.jl
@@ -166,3 +166,13 @@ function bounds(x::Number; max::Number=Inf, min::Number=0)
         x < min ? min :
         x
 end
+
+"""
+    @areaof(npixels)
+
+Calculate the area of a given number of landscape pixels, knowing the resolution of the
+world map (requires the `model` object to be available).
+"""
+macro areaof(npixels)
+    :($(esc(npixels)) * $(esc(:model)).settings["world.mapresolution"]^2)
+end
diff --git a/src/crop/farmplot.jl b/src/crop/farmplot.jl
index 26eda952af2e65075ce77b1bcbf6262c4953fc7a..d4b5787807b6a2069a9267da040506b3a9a5140f 100644
--- a/src/crop/farmplot.jl
+++ b/src/crop/farmplot.jl
@@ -12,7 +12,6 @@ mutable struct FarmPlot{T} <: ModelAgent
     const id::Int64
     pixels::Vector{Tuple{Int64, Int64}}
     farmer::Int64
-    croprotation::Vector{String}
     cropstate::T
 end
 
@@ -53,19 +52,39 @@ function harvest!(farmplot::FarmPlot{T}, model::SimulationModel) where T
     harvest!(farmplot.cropstate, model)  # TODO: multiply with area to return units of `g`
 end
 
+"""
+    @sow(cropname)
+
+Sow the named crop on the current field. Requires the variables `field` and `model`.
+"""
+macro sow(cropname)
+    :(sow!($(esc(:field)), $(esc(:model)), $(esc(cropname))))
+end
+
+"""
+    @harvest()
+
+Harvest the current field. Requires the variables `field` and `model`.
+"""
+macro harvest()
+    :(harvest!($(esc(:field)), $(esc(:model))))
+end
+
 ## UTILITY FUNCTIONS
 
 """
     isgrassland(farmplot, model)
 
-Classify a farmplot as grassland or not (i.e., is the landcover of >90% of its pixels grass?)
+Classify a farmplot as grassland or not (i.e., is the landcover of >80% of its pixels grass?)
 """
 function isgrassland(farmplot::FarmPlot, model::SimulationModel)
-    proportiongrass = count(pos -> @landcover() == grass, farmplot.pixels) / length(farmplot.pixels)
-    if proportiongrass > 0.9
+    proportiongrass = count(pos -> landcover(pos, model) == grass, farmplot.pixels) /
+        length(farmplot.pixels)
+    if proportiongrass > 0.8
         return true
-    elseif proportiongrass > 0.1
+    elseif proportiongrass > 0.2
         @warn "Unclear classification: farm plot $(farmplot.id) has $(proportiongrass*100)% grass."
+        proportiongrass >= 0.5 && return true
     end
     return false
 end
@@ -78,7 +97,7 @@ Calculate the average field size in hectares for the model landscape.
 function averagefieldsize(model::SimulationModel)
     sizes::Vector{Float64} = []
     for fp in model.farmplots
-        push!(sizes, length(fp.pixels)*@param(world.mapresolution)^2)
+        push!(sizes, @areaof(length(fp.pixels)))
     end
     return sum(sizes)/length(sizes) |> ha
 end
diff --git a/src/nature/populations.jl b/src/nature/populations.jl
index 2f45c71759ce2ff5de1e653cdde9aeac51898da2..144f0462fc612ffc14c1e4b4f075350aaf4fa362 100644
--- a/src/nature/populations.jl
+++ b/src/nature/populations.jl
@@ -84,7 +84,7 @@ function initpopulation!(species::Type, p::PopInitParams, model::SimulationModel
     lastn = 0
     width, height = size(model.landscape)
     if p.indarea > 0m²
-        pixelsperind = Int(round(p.indarea / @param(world.mapresolution)^2))
+        pixelsperind = Int(round(p.indarea / @areaof(1)))
     end
     while n == 0 || n < p.popsize
         for x in @shuffle!(Vector(1:width))
@@ -160,7 +160,7 @@ return the size as a plain number.
 function territorysize(a::Union{Animal,Int64}, model::SimulationModel,
                        units::Unitful.Units=ha, stripunits::Bool=false)
     a isa Int && (a = @animal(a))
-    size = length(a.territory) * @param(world.mapresolution)^2 |> Float64
+    size = length(a.territory) * @areaof(1) |> Float64
     stripunits ? ustrip(units, size) : size |> units
 end
 
diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl
index ac582dc0aeed8f0af845d884d88583ce88053f56..feaa063a7be5e538c88895f2bef913bc8d06e965 100644
--- a/src/nature/species/skylark.jl
+++ b/src/nature/species/skylark.jl
@@ -319,7 +319,7 @@ function findterritory(skylark::Skylark, model::SimulationModel)
             (isoccupied(model, "Skylark", c)) && continue
             push!(territory, c)
             quality = foragequality(skylark, model, c)
-            effectivesize += @param(world.mapresolution)^2*quality
+            effectivesize += @areaof(quality)
             (quality > 0) && (constrained = false)
             #XXX check for nesting habitats?
         end