| description | This guide explains how to create custom gathering patterns for the Fuzzy Macro. |
|---|
Patterns define the movement your character performs while gathering in fields. They determine how efficiently you collect pollen from flowers. Patterns are Python scripts located in settings/patterns/.
When gathering is active, the macro:
- Navigates to your selected field
- Positions at the start location
- Executes your pattern repeatedly
- Collects pollen while moving
Patterns are .py files that execute within the macro's gather function context. Basic structure:
# Size conversion (standard for all patterns)
if sizeword.lower() == "xs":
size = 0.5
elif sizeword.lower() == "s":
size = 1
elif sizeword.lower() == "l":
size = 2
elif sizeword. lower() == "xl":
size = 2.5
else:
size = 1.5 # Default: M
# Pattern movement logic
self.keyboard.walk(tcfbkey, 0.5 * size)
for _ in range(width):
self.keyboard.walk(tclrkey, 0.17)
self.keyboard.walk(afcfbkey, 0.5 * size)File Naming:
- Use lowercase with underscores:
my_pattern.py - Avoid spaces or special characters
- Name should be descriptive:
zigzag_tight.py,circle_large.py
When your pattern executes, these variables are available in the namespace:
tcfbkey # True camera forward/backward key (affected by invert_fb)
afcfbkey # Alternate forward/backward key (opposite of tcfbkey)
tclrkey # True camera left/right key (affected by invert_lr)
afclrkey # Alternate left/right key (opposite of tclrkey)
# Base keys (unaffected by inversions)
fwdkey # "w" - forward
backkey # "s" - backward
leftkey # "a" - left
rightkey # "d" - rightWhy use inverted keys?
- Using
tcfbkeyinstead offwdkeyrespects user's "Invert Forward/Back" setting - Using
tclrkeyinstead ofleftkeyrespects user's "Invert Left/Right" setting - This makes your pattern work correctly regardless of user preferences
rotleft # "," - rotate camera left
rotright # "." - rotate camera right
rotup # "pageup" - rotate camera up
rotdown # "pagedown" - rotate camera down
zoomin # "i" - zoom in
zoomout # "o" - zoom out
sc_space # "space" - space keysize # Float: Calculated from sizeword (XS=0.5, S=1, M=1.5, L=2, XL=2.5)
sizeword # String: "XS", "S", "M", "L", or "XL" from GUI
width # Integer: 1-8, number of pattern repetitions from GUIself.keyboard.walk(key, duration) # Walk in direction for duration seconds
self.keyboard.multiWalk([keys], duration) # Walk multiple directions simultaneously
self.keyboard.press(key) # Press key once
sleep(seconds) # Sleep for specified timeWalk Method Details:
# Walk forward for 1.5 seconds
self.keyboard.walk("w", 1.5)
# Walk diagonally (forward + left) for 2 seconds
self.keyboard.multiWalk(["w", "a"], 2.0)
# Press rotate right (single tap)
self.keyboard.press(".")This pattern traces an "E" shape, ideal for rectangular fields.
if sizeword.lower() == "xs":
size = 0.5
elif sizeword.lower() == "s":
size = 1
elif sizeword.lower() == "l":
size = 2
elif sizeword.lower() == "xl":
size = 2.5
else:
size = 1.5
# Move back to start position
self.keyboard.walk(afcfbkey, 0.5 * size)
# Top horizontal line
for _ in range(width):
self.keyboard.walk(tclrkey, 0.17)
self.keyboard.walk(tclrkey, 0.17)
# Downward zigzag (first half of E)
for _ in range(width):
self.keyboard.walk(tcfbkey, 0.5 * size)
self.keyboard.walk(afclrkey, 0.17)
self.keyboard.walk(afcfbkey, 0.5 * size)
self.keyboard.walk(afclrkey, 0.17)
# Middle horizontal line
self.keyboard.walk(tcfbkey, 0.5 * size)
for _ in range(width):
self.keyboard.walk(tclrkey, 0.17)
self.keyboard.walk(tclrkey, 0.17)
# Downward zigzag (second half of E)
for _ in range(width):
self.keyboard. walk(afcfbkey, 0.5 * size)
self.keyboard.walk(afclrkey, 0.17)
self.keyboard.walk(tcfbkey, 0.5 * size)
self.keyboard.walk(afclrkey, 0.17)How it works:
- Moves back slightly to position
- Walks right to form top of "E"
- Zigzags down and back to form top section
- Walks right to form middle of "E"
- Zigzags down and back to form bottom section
A complex pattern with tight movements, good for dense fields.
# Size conversion (custom scaling)
if sizeword.lower() == "xs":
size = 0.25
elif sizeword.lower() == "s":
size = 0.5
elif sizeword.lower() == "l":
size = 1
elif sizeword.lower() == "xl":
size = 1.25
else:
size = 0.75
size = size / 5. 5
# Setup walk function compatibility (for Natro pattern conversion)
nm_walk = self.keyboard.walk
fwdkey = tcfbkey
backkey = afcfbkey
leftkey = tclrkey
rightkey = afclrkey
# Position at start
nm_walk(rightkey, 13 * size)
nm_walk(backkey, 9 * size)
nm_walk(leftkey, 4. 5 * size)
nm_walk(fwdkey, 6 * size)
# Main pattern loop
for i in range(width):
# Left sweep
nm_walk(fwdkey, 9 * size)
nm_walk(leftkey, 2 * size)
nm_walk(backkey, 9 * size)
nm_walk(leftkey, 2 * size)
nm_walk(fwdkey, 9 * size)
nm_walk(leftkey, 2 * size)
nm_walk(backkey, 9 * size)
nm_walk(leftkey, 2 * size)
# Right sweep
nm_walk(fwdkey, 9 * size)
nm_walk(rightkey, 2 * size)
nm_walk(backkey, 9 * size)
nm_walk(rightkey, 2 * size)
nm_walk(fwdkey, 9 * size)
nm_walk(rightkey, 2 * size)
nm_walk(backkey, 9 * size)
nm_walk(rightkey, 2 * size)How it works:
- Positions character at specific start point
- Performs serpentine pattern moving left
- Performs serpentine pattern moving right
- Repeats for each width increment
Advanced pattern using camera rotation and diagonal movements.
# Configuration variables
digistops = False # Set True if using Digital Bee
passivefdc = 0.3 # Field drift compensation amount
# Pattern-specific variables
stepsize = 3
rightdrift = 2
rightoff = 2
downdrift = 1
downoff = 3
# Size conversion
if sizeword.lower() == "xs":
size = 0.5
elif sizeword.lower() == "s":
size = 1
elif sizeword.lower() == "l":
size = 2
elif sizeword.lower() == "xl":
size = 2.5
else:
size = 1.5
sizemulti = 1/10 * 1.2
size *= sizemulti
passivefdc *= sizemulti
# Rotate camera up (reset camera angle)
for _ in range(4):
self.keyboard.press(rotup)
# Pattern movement with camera rotations
self.keyboard.walk(backkey, stepsize * size)
self.keyboard.walk(rightkey, stepsize * size)
self.keyboard.walk(fwdkey, stepsize * size)
# Rotate left and compensate for drift
self.keyboard.press(rotleft)
self.keyboard.press(rotleft)
sleep(0.05)
self.keyboard.walk(backkey, (rightdrift + rightoff) * sizemulti)
self.keyboard.walk(fwdkey, rightoff * sizemulti)
if digistops:
sleep(0.8)
# Rotate back right
self.keyboard.press(rotright)
self.keyboard.press(rotright)
sleep(0.05)
self.keyboard.walk(leftkey, stepsize * size * 2)
if digistops:
sleep(0.85)
# Diagonal movements
self.keyboard.press(rotleft)
sleep(0.05)
self.keyboard.multiWalk([backkey, leftkey], stepsize * size)
self.keyboard.multiWalk([backkey, rightkey], stepsize * size)
self.keyboard.multiWalk([fwdkey, rightkey], stepsize * size * 2)
self.keyboard.press(rotright)
sleep(0.05)
# Continue pattern...
self.keyboard.multiWalk([backkey, rightkey], stepsize * size + passivefdc)
if digistops:
sleep(0.85)Advanced features:
- Camera rotation to change perspective
- Diagonal walking with
multiWalk() - Digital Bee compatibility with sleep delays
- Custom drift compensation
- Complex multi-directional sweeps
Every pattern must convert the size setting:
if sizeword. lower() == "xs":
size = 0.5
elif sizeword.lower() == "s":
size = 1
elif sizeword.lower() == "l":
size = 2
elif sizeword. lower() == "xl":
size = 2.5
else:
size = 1.5 # Medium (default)You can customize the multipliers for your pattern's needs:
# Tighter pattern
if sizeword.lower() == "xs":
size = 0.25
elif sizeword. lower() == "s":
size = 0.5
# ...
# Or add additional scaling
size = size / 5.5 # Make pattern much tighter# ✅ GOOD - Scales with size
self.keyboard.walk(tcfbkey, 0.5 * size)
# ❌ BAD - Ignores user's size setting
self.keyboard.walk(tcfbkey, 0.5)# ✅ GOOD - Respects width setting
for _ in range(width):
self.keyboard.walk(tcfbkey, 1.0 * size)
self.keyboard.walk(tclrkey, 0.5 * size)
# ❌ BAD - Hardcoded repetitions
for _ in range(5):
self.keyboard.walk(tcfbkey, 1.0 * size)# ✅ GOOD - Respects invert settings
self.keyboard.walk(tcfbkey, 1.0) # Forward (respects Invert F/B)
self.keyboard.walk(tclrkey, 0.5) # Left (respects Invert L/R)
# ❌ BAD - Ignores invert settings
self.keyboard.walk(fwdkey, 1.0) # Always forward
self.keyboard.walk(leftkey, 0.5) # Always leftAlways test your pattern with different size settings:
- XS: Very tight, small areas
- S: Small fields or dense gathering
- M: Default, balanced coverage
- L: Large fields, spread out
- XL: Very large fields, maximum coverage
# Position character at pattern start point
self.keyboard.walk(afcfbkey, 0.5 * size)
# Top horizontal line of E shape
for _ in range(width):
self.keyboard.walk(tclrkey, 0.17)
# Downward vertical sweep with lateral movement
for _ in range(width):
self.keyboard.walk(tcfbkey, 0.5 * size)
self.keyboard.walk(afclrkey, 0.17)# For Digital Bee users - add pause after camera rotations
digistops = False # User can change this at top of pattern
if digistops:
sleep(0.8)
# Field-specific adjustments
passivefdc = 0.3 # Passive field drift compensation
# Adjust for different field shapes
if "bamboo" in field_name: # Would need to pass field name
size *= 1.2 # Bamboo is larger# ✅ GOOD - Continuous movement
self.keyboard.walk("w", 2.0)
self.keyboard.walk("a", 1.0)
# ❌ BAD - Unnecessary stops
self.keyboard.walk("w", 1.0)
sleep(0.5)
self.keyboard.walk("w", 1.0)
sleep(0.5)Good patterns should:
- Cover most of the field area
- Avoid revisiting the same spots too much
- Work in fields of different shapes
- Adapt to size/width settings
# Balanced coverage example
for _ in range(width):
# Forward sweep
self.keyboard.walk(tcfbkey, 2.0 * size)
# Lateral shift
self.keyboard.walk(tclrkey, 0.3 * size)
# Backward sweep
self.keyboard.walk(afcfbkey, 2.0 * size)
# Lateral shift
self.keyboard.walk(tclrkey, 0.3 * size)Add a header comment explaining your pattern:
"""
Pattern: Spiral Outward
Description: Starts at center and spirals outward in expanding squares
Best for: Square fields (Clover, Dandelion, Sunflower)
Width: Controls number of spiral loops
Size: Controls distance between spiral rings
Author: YourName
"""
# Pattern code here... 1. Enable a Test Field
In the macro GUI:
- Select a field to use your pattern
- Set gathering time to 1-2 minutes (quick tests)
- Enable only that field
- Disable other tasks
2. Watch the Pattern Execute
- Start the macro
- Observe if the pattern covers the field well
- Look for:
- Missed areas
- Overlapping paths
- Drift over time
- Getting stuck
3. Adjust Size Scaling
If pattern is too large/small, adjust size multipliers:
# Pattern is too large
size = size * 0.8 # Make pattern 20% smaller
# Pattern is too small
size = size * 1.2 # Make pattern 20% larger
# Pattern needs different proportions
size_horizontal = size * 1.0
size_vertical = size * 0.7 # Make vertical movements shorter4. Test All Size Settings
Test each size from the GUI:
XS → Should work in very tight spaces
S → Should work in small areas
M → Should be balanced (most common)
L → Should cover large areas
XL → Should maximize coverage
5. Test All Width Settings
Test width values 1-8:
Width 1 → Minimal repetitions
Width 4 → Moderate coverage
Width 8 → Maximum repetitions
View Logs
Pattern errors appear in:
- Terminal/console output
- Discord webhook (if enabled): "Incompatible pattern"
Common Errors
# Error: NameError: name 'tcfbkey' is not defined
# Fix: Check spelling, use correct variable names
# Error: TypeError: unsupported operand type(s)
# Fix: Ensure size is defined, check math operations
# Error: SyntaxError
# Fix: Check for missing colons, parentheses, quotes# Add debug prints to see what's happening
print(f"Size: {size}, Width: {width}")
print(f"Moving forward for {1.0 * size} seconds")
self.keyboard.walk(tcfbkey, 1.0 * size)
print("Forward movement complete")Your pattern should work reasonably well in:
- Small fields (Sunflower, Dandelion, Mushroom)
- Medium fields (Blue Flower, Bamboo, Rose)
- Large fields (Pepper, Pumpkin, Cactus)
- Enable screen recording in macro settings
- Record a full pattern cycle
- Review footage to identify issues
- Make adjustments based on observations
The macro includes an automatic AHK-to-Python converter for Natro Macro patterns.
Place .ahk pattern files in settings/patterns/. On macro startup:
# Macro automatically converts . ahk files to .py
ahkPatterns = [x for x in os.listdir(patterns_dir) if ".ahk" in x]
for pattern in ahkPatterns:
python = ahkPatternToPython(ahk)
# Saves as .py file with same name{% hint style="warning" %}
{% endhint %}
If automatic conversion fails, convert manually using these equivalents:
Basic Movement
AHK:
Send {w down}
Sleep 1000
Send {w up}Python:
self.keyboard.walk("w", 1.0)Loops
AHK:
Loop %reps%
{
; Movement commands
}Python:
for i in range(width):
# Movement commandsNatro's nm_Walk Function
AHK:
nm_Walk(2, FwdKey)
nm_Walk(1. 5, LeftKey)Python:
self.keyboard.walk(tcfbkey, 2)
self.keyboard.walk(tclrkey, 1.5)Common Replacements
| AHK | Python |
|---|---|
reps |
width |
a_index |
i |
&& |
and |
| ` | |
; (comment) |
# (comment) |
:= |
= |
sqrt |
math.sqrt |
Sleep 500 |
sleep(0.5) |
Before (AHK):
; Simple zigzag pattern
Loop %reps%
{
Send {w down}
Sleep 500
Send {w up}
Send {a down}
Sleep 200
Send {a up}
Send {s down}
Sleep 500
Send {s up}
Send {a down}
Sleep 200
Send {a up}
}After (Python):
# Simple zigzag pattern
for i in range(width):
self.keyboard.walk("w", 0.5)
self.keyboard.walk("a", 0.2)
self.keyboard.walk("s", 0.5)
self.keyboard.walk("a", 0.2)Better (Python with proper keys):
# Simple zigzag pattern (respects inversions)
for i in range(width):
self.keyboard.walk(tcfbkey, 0.5 * size)
self.keyboard.walk(tclrkey, 0.2 * size)
self.keyboard.walk(afcfbkey, 0.5 * size)
self.keyboard.walk(tclrkey, 0.2 * size)- Pattern Inspiration: Check existing patterns in
settings/patterns/ - Natro Macro Patterns: Many patterns are compatible with conversion
- Discord Community: Share patterns and get help at https://discord.gg/c4XM7XJjrP
- Documentation: https://fuzzy-team.gitbook.io/fuzzy-macro
If you create useful patterns:
- Test thoroughly across different fields and scenarios
- Add clear comments explaining the pattern logic
- Include size handling and width support
- Test all size/width combinations
- Share in Discord community
- Consider submitting a PR to the repository
"""
Pattern Name: [Your Pattern Name]
Description: [What the pattern does]
Best For: [Which fields work best]
Width: [What width controls]
Size: [What size controls]
Author: [Your Name]
Date: [Creation Date]
"""
# Size conversion
if sizeword.lower() == "xs":
size = 0.5
elif sizeword. lower() == "s":
size = 1
elif sizeword.lower() == "l":
size = 2
elif sizeword.lower() == "xl":
size = 2.5
else:
size = 1.5
# Configuration (optional)
# Add any user-configurable variables here
# Pattern logic
# Your pattern movement code here- Macro Inspiration:Natro Macro, Stumpy Macro, Existance Macro
- Developers: Logan
Original Macro code: Existance - Pattern Makers: Existance, NatroTeam, tvojamamkajenic, sev, dully176, chillketchup, Electro
Happy pattern making!