Pattern Creation Guide
What are Patterns?
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
Pattern File Structure
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
Available Variables
When your pattern executes, these variables are available in the namespace:
Movement Keys
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" - right
Why 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
Camera Controls
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 key
Pattern Settings
size # 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 GUI
Macro Methods
self.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 time
Walk 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(".")
Pattern Examples
Example 1: Simple E Pattern (e_lol. py)
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
Example 2: Bambe Pattern (bambe.py)
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
Example 3: Bowl Pattern with Camera Rotation (bowl.py)
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
Best Practices
1. Always Include Size Handling
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
2. Scale All Movements by Size
# ✅ GOOD - Scales with size
self.keyboard.walk(tcfbkey, 0.5 * size)
# ❌ BAD - Ignores user's size setting
self.keyboard.walk(tcfbkey, 0.5)
3. Use Width for Repetitions
# ✅ 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)
4. Use Inverted Keys for Pattern Logic
# ✅ 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 left
5. Test Multiple Sizes
Always 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
6. Add Clear Comments
# 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)
7. Handle Special Cases
# 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
8. Keep Patterns Efficient
# ✅ 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)
9. Consider Field Coverage
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)
10. Document Pattern Behavior
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...
Testing & Debugging
Testing Patterns
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 shorter
4. 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
Check Pattern Output
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
Debug with Print Statements
# 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")
Test in Different Fields
Your pattern should work reasonably well in:
- Small fields (Sunflower, Dandelion, Mushroom)
- Medium fields (Blue Flower, Bamboo, Rose)
- Large fields (Pepper, Pumpkin, Cactus)
Record and Review
- Enable screen recording in macro settings
- Record a full pattern cycle
- Review footage to identify issues
- Make adjustments based on observations
Converting AHK Patterns
The macro includes an automatic AHK-to-Python converter for Natro Macro patterns.
Automatic Conversion
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
Warning
Not all AHK patterns can be converted properly, manual conversion may be needed to fix some bugs.
Manual Conversion
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 commands
Natro'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) |
Full Conversion Example
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)
Additional Resources
- 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
Contributing Patterns
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 Template
"""
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
Credits
- 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!