wait() - Wait/Pause Function
Summary
The wait() function introduces temporal pauses, delays, or waiting conditions in NDL sequences. It represents time passing, dramatic pauses, reaction delays, or conditions that must be met before the narrative continues. This construct enables NDL to describe not just what happens, but the timing and pacing of events.
Syntax
wait("duration")
wait("condition")
wait(time_value)Parameters
| Parameter | Type | Description |
|---|---|---|
| duration/condition | String or number | Time duration (e.g., “1s”, “3 hours”) or condition (e.g., “response”, “enemy reacts”) |
Description
The wait() function serves multiple purposes in NDL:
- Time Delays: Explicit duration (seconds, minutes, hours)
- Dramatic Pauses: Narrative timing (“tense moment”, “brief silence”)
- Reaction Delays: Waiting for NPC/world response
- Conditional Holds: Waiting until something happens
- Pacing Control: Slowing down or speeding up narrative flow
Unlike do() which represents actions, wait() represents the absence of action or the passage of time between actions.
Narrative Timing
The
wait()function is crucial for pacing. It tells the LLM that time passes or there’s a pause, preventing all actions from feeling rushed or simultaneous.
Real Examples
Basic Wait in Sequence
do($"you", "write some NDL") -> wait("response validation")From veritasr’s Director processing:
Input String: do($"you", "write some NDL")->wait("response validation")
is_ndl: True
Actions: ['do', 'wait']
Interpretation: The character writes NDL, then waits for the response to be validated. This creates a two-beat narrative: action, then pause/anticipation.
Common Wait Types
Time Durations
wait("1s") # 1 second
wait("5m") # 5 minutes
wait("3 hours") # 3 hours
wait("overnight") # Abstract duration
wait("brief moment")
wait("long pause")Response/Reaction Waits
wait("enemy reacts")
wait("NPC responds")
wait("response validation")
wait("answer")
wait("their move")Conditional Waits
wait("door opens")
wait("reinforcements arrive")
wait("spell completes")
wait("sunrise")
wait("trap resets")Dramatic Pauses
wait("tense silence")
wait("dramatic pause")
wait("moment of anticipation")
wait("breath held")
wait("heartbeat")Usage Patterns
Action-Wait-Action
do($"player", "ask question") -> wait("tense silence") -> do($"NPC", "respond")LLM Output:
You ask the question. Silence hangs heavy in the air. Finally, after what feels like an eternity, the stranger responds.
The wait creates tension between question and answer.
Action-Wait-Result
do($"player", "attack") -> wait("enemy reacts") -> result("enemy dodges")LLM Output:
You swing your blade. For a split second, time seems to slow. Then your opponent moves, side-stepping your attack with practiced ease.
Time-Based Scene Transition
do($"party", "rest at camp") -> wait("8 hours") -> new_scene("dawn")LLM Output:
You make camp for the night, taking turns keeping watch. Eight hours pass. As the first light of dawn breaks over the horizon, you prepare to continue your journey.
Combat Timing
do($"player", "feint") -> wait("enemy commits") -> do($"player", "strike true target")LLM Output:
You feint toward the goblin's left side. It takes the bait, shifting its defense. In that instant of commitment, you strike at its undefended right flank.
Multiple Waits
do($"cast spell") -> wait("1s") ~ "channeling energy" -> wait("2s") ~ "energy builds" -> wait("1s") ~ "final surge" -> result("spell releases")LLM Output:
You begin casting, channeling arcane energy. The power builds second by second, swirling around you. The energy reaches a crescendo, and in a final surge, the spell releases in a brilliant flash.
Semantic Interpretations
Duration: Explicit Time
wait("3 hours")LLM Interpretation: Three hours pass. May summarize events, skip details, or transition scene.
Condition: Event Occurs
wait("door opens")LLM Interpretation: Time passes until door opens. May describe anticipation, then the opening.
Dramatic: Narrative Beat
wait("heartbeat")LLM Interpretation: Very brief pause for dramatic effect. Doesn’t necessarily mean literal heartbeat duration.
Response: Reactive Pause
wait("NPC response")LLM Interpretation: Pause while NPC formulates and delivers response. May include NPC deliberation.
Integration with Other Constructs
With Actions (Sequencing)
do($"action1") -> wait("delay") -> do($"action2")Most common pattern: action, pause, action.
With Results
do($"attack") -> wait("enemy reacts") -> result("miss")Pause before outcome is revealed.
With Manner
do($"speak") -> wait("pause") ~ "uncomfortable" -> do($"continue")The manner can modify the wait itself (uncomfortable pause, tense silence, etc.).
With System Response
do($"action") -> result("failure") -> wait("recover") -> system_response("You can try again")Pause before meta-information.
Scene Transitions
Long waits often trigger scene transitions:
Time Skip
wait("overnight") -> new_scene("next morning")
wait("several days") -> arrive($"destination")Travel Time
do($"depart city") -> wait("3 days travel") -> arrive($"fortress")LLM Output:
You leave the city gates behind. Three days of travel through rolling hills and dense forests bring you to the fortress, its dark towers looming against the sky.
Healing/Recovery
do($"rest") -> wait("full night") -> restore("health") -> wake($"refreshed")Implementation Notes
Parsing Wait Functions
import re
def parse_wait(ndl_string):
"""Extract wait value from NDL."""
match = re.search(r'wait\("([^"]+)"\)', ndl_string)
if match:
return match.group(1)
return None
# Usage
condition = parse_wait('do(action) -> wait("response")')
# Returns: "response"Interpreting Wait Durations
def parse_duration(wait_value):
"""Parse wait duration into time units."""
patterns = {
r'(\d+)s': ('seconds', 1),
r'(\d+)m': ('minutes', 60),
r'(\d+)\s*hours?': ('hours', 3600),
r'(\d+)\s*days?': ('days', 86400),
}
for pattern, (unit, multiplier) in patterns.items():
match = re.match(pattern, wait_value)
if match:
amount = int(match.group(1))
return {
'amount': amount,
'unit': unit,
'seconds': amount * multiplier
}
# Non-numeric duration (dramatic pause, etc.)
return {
'amount': None,
'unit': 'narrative',
'description': wait_value
}
# Usage
duration = parse_duration("3 hours")
# Returns: {'amount': 3, 'unit': 'hours', 'seconds': 10800}
dramatic = parse_duration("tense moment")
# Returns: {'amount': None, 'unit': 'narrative', 'description': 'tense moment'}Backend Wait Processing
def process_wait(wait_condition, game_state):
"""Determine if wait condition is met."""
if is_duration(wait_condition):
# Time-based wait
game_state.advance_time(parse_duration(wait_condition))
return True
elif is_condition(wait_condition):
# Conditional wait
return game_state.check_condition(wait_condition)
else:
# Dramatic/narrative wait (always proceeds)
return True
# Usage
if process_wait("3 hours", state):
continue_narrative()Generating Wait NDL
def create_wait(duration_or_condition):
"""Create wait NDL."""
return f'wait("{duration_or_condition}")'
# Usage
ndl = create_wait("enemy responds")
# Returns: 'wait("enemy responds")'
# In sequence
seq = f'{action1} -> {create_wait("1s")} -> {action2}'Anti-Patterns
❌ Waiting Without Context
wait("wait")Problem: Unclear what is being waited for.
Better:
wait("response") # or "1s" or "door opens"❌ Redundant Waits
wait("pause") -> wait("pause") -> wait("pause")Problem: Multiple identical waits with no intervening action.
Better:
wait("long pause")❌ Contradictory Wait
do($"immediate action") -> wait("never ends")Problem: Semantically contradictory.
❌ Missing Wait for Pacing
do($"ask life-or-death question") -> do($"NPC answers")Problem: No dramatic pause where one is expected.
Better:
do($"ask life-or-death question") -> wait("tense silence") -> do($"NPC answers")Best Practices
1. Use Waits for Dramatic Pacing
# Add tension
do($"light fuse") -> wait("fuse burns") -> result("explosion")
# Build anticipation
do($"knock on door") -> wait("footsteps approach") -> door_opens()2. Specify Duration Clearly
✓ wait("3 hours")
✓ wait("brief moment")
✗ wait("time") # Too vague3. Match Wait to Context
# Combat: Short, dramatic
wait("split second")
# Travel: Long, summarized
wait("several days")
# Dialogue: Medium, tense
wait("uncomfortable pause")4. Use Waits for NPC Reactions
do($"player", "say shocking thing") -> wait("NPC processes") -> do($"NPC", "respond")This gives NPCs realistic reaction time.
5. Combine with Scene Transitions
wait("overnight") -> new_scene("morning") -> describe("well-rested")Design Philosophy
Narrative Pacing
Wait controls the tempo of narration:
- Fast-paced: Few or no waits
- Deliberate: Frequent short waits
- Epic scope: Long waits (days, weeks)
Realism
Characters don’t act instantaneously:
# Realistic
do($"ask") -> wait("NPC thinks") -> do($"NPC answers")
# Unrealistic
do($"ask") -> do($"NPC answers")LLM Guidance
The wait() function signals to the LLM:
- “Slow down the narration here”
- “Time passes”
- “Create a pause for effect”
- “Show anticipation or reaction time”
Scene Boundary Detection
From veritasr’s implementation, certain waits trigger scene transitions:
is_ndl: True
end_scene: True
transition_scene_type: "both" # time, place, or bothLong waits often indicate:
transition_scene_type: "time"- Hours/days passtransition_scene_type: "place"- Travel timetransition_scene_type: "both"- Journey over time and space
Related Constructs
- sequencing - The
->operator chains waits with actions - do-action - Actions that waits separate
- result - Outcomes that waits precede
- system_response - Meta-information after waits
See Also
- 00-NDL-INDEX - Main NDL reference
- 01-lexical-elements - Function syntax
- 02-grammar - Wait in formal grammar
- scene-transitions - Using wait for transitions
Key Takeaway
The
wait()function is NDL’s mechanism for controlling narrative pacing and representing the passage of time. By explicitly specifying pauses, delays, and timing between events, NDL enables the LLM to generate properly paced narration with realistic reaction times, dramatic tension, and scene transitions. Withoutwait(), all actions would feel simultaneous and rushed. With it, stories flow naturally with proper timing.