Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions LANGUAGE_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,49 @@ Signal allBelow1000 = all(levels) < 1000; # True (all values match)
- `any()` compiles to a decider combinator outputting `signal-anything`
- `all()` compiles to a decider combinator outputting `signal-everything`

#### Bundle Filtering

Filter a bundle to include only signals that pass a comparison using the conditional output syntax:

```facto
Bundle requested_items = { ("signal-A", 10), ("signal-B", 5), ("signal-C", -3) };

# Keep only signals > 0 (preserving their values)
Bundle positive_items = (requested_items > 0) : requested_items;
# Result: signal-A=10, signal-B=5 (signal-C=-3 is filtered out)

# Filter with different comparison operators
Bundle above_threshold = (requested_items >= 8) : requested_items; # Only signal-A=10
Bundle non_zero = (requested_items != 0) : requested_items; # All signals (none are zero)
```

**Syntax:** `(bundle COMPARISON scalar) : output`

The comparison evaluates each signal in the bundle against the scalar value. Only signals that pass the comparison are included in the output.

**Output Modes:**

1. **Preserve values** (output is a bundle): The original signal values are preserved
```facto
Bundle filtered = (items > 0) : items; # copy_count_from_input = true
```

2. **Constant output** (output is an integer): Each matching signal outputs the constant value
```facto
Bundle counts = (items > 0) : 1; # Each matching signal outputs 1
```

**Factorio Output:** Compiles to a single decider combinator:
- Input signal: `signal-each` (evaluates each signal independently)
- Comparison: The specified operator and scalar value
- Output signal: `signal-each` (outputs matching signals)
- Output mode: `copy_count_from_input` (true for bundle output, false for constant)

**Common Use Cases:**
- Filtering inventory requests to only positive quantities
- Separating signals by range (e.g., high vs low values)
- Counting signals that meet a condition

#### Bundle Use Cases

Bundles are ideal for:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ Bundle resources = { ("iron-plate", 100), ("copper-plate", 80), ("coal", 50) };
Bundle doubled = resources * 2; # Double all values
Signal iron = resources["iron-plate"]; # Access a single signal
Signal anyLow = any(resources) < 20; # True if any resource is below 20
Bundle positive = (resources > 0) : resources; # Filter to only positive values
```

Bundles are powerful for building generic circuits like balanced train loaders that work regardless of what items you're loading.
Expand Down
20 changes: 20 additions & 0 deletions doc/03_signals_and_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,26 @@ Signal allBelow1000 = all(levels) < 1000; # True
- `any()` compiles to `signal-anything`
- `all()` compiles to `signal-everything`

### Bundle Filtering

Filter a bundle to keep only signals that pass a comparison:

```facto
Bundle requests = { ("signal-A", 10), ("signal-B", 5), ("signal-C", -3) };

# Keep only positive values (preserving their counts)
Bundle pending = (requests > 0) : requests;
# Result: signal-A=10, signal-B=5 (signal-C is filtered out)

# Output constant 1 for each matching signal
Bundle counts = (requests > 0) : 1;
# Result: signal-A=1, signal-B=1
```

This compiles to a single decider combinator using `signal-each`. The syntax is `(bundle COMPARISON scalar) : output`, where output can be:
- A bundle: preserves original signal values
- An integer: outputs that constant for each matching signal

---

## For Loops
Expand Down
36 changes: 36 additions & 0 deletions doc/05_entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,42 @@ The `.output` property returns a **Bundle** — all signals the entity outputs.
- Balancing item distribution
- Controlling production based on storage

### Wiring Signals to Entities: `.input`

To wire signals to an entity's circuit input, use `.input`:

```facto
Bundle resources = { ("iron-plate", 100), ("copper-plate", 80) };
Entity selector = place("selector-combinator", 0, 0, {
operation: "count",
count_signal: "signal-C"
});
selector.input = resources; # Wire resources to selector's input
```

The `.input` property creates a wire connection from a signal source to the entity:

- **For dual-connector entities** (arithmetic, decider, selector combinators): Wires connect to the **input side** of the combinator
- **For single-connector entities** (lamps, chests, inserters): Wires connect to the entity's circuit connection

**Common uses:**
- Providing input signals to combinators
- Connecting signal sources to entities for circuit control
- Building circuits where explicit wiring is needed

**Example with selector combinator:**
```facto
# Count unique signals
Entity chest = place("steel-chest", 0, 0, {read_contents: 1});
Bundle items = chest.output;
Entity counter = place("selector-combinator", 1, 0, {
operation: "count",
count_signal: "signal-C"
});
counter.input = items; # Wire chest contents to selector
Signal count = counter.output["signal-C"]; # Read the count
```

### Balanced Loader Example

```facto
Expand Down
22 changes: 22 additions & 0 deletions doc/07_advanced_concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,28 @@ Signal c = data["signal-C"];
Signal weighted = (a * 3 + b * 2 + c * 1) / 6;
```

### Bundle Filtering

Filter bundles to process only signals meeting a condition:

```facto
Bundle inventory = {
("iron-plate", 500),
("copper-plate", 200),
("coal", -50), # Negative = deficit
("stone", 0)
};

# Get only items we have (positive counts)
Bundle have = (inventory > 0) : inventory;

# Get deficit signals as positive values for requesting
Bundle deficits = (inventory < 0) : (inventory * -1);

# Count how many item types meet a threshold
Bundle above_threshold = (inventory > 100) : 1;
```

---

## For Loop Patterns
Expand Down
Loading