State Machine Concepts

Category: Development

State Machine Concepts

This guide explains how to organize your PowBot Desktop scripts using state machines for better structure and maintainability.

What is a State Machine?

A state machine organizes script logic into distinct states, where each state represents a specific behavior or goal. The script transitions between states based on conditions.

Basic State Machine Pattern

local script = {
    name = "StateMachineExample",
    version = "1.0.0",
    state = "IDLE"  -- Initial state
}

function script:poll()
    if self.state == "IDLE" then
        self:handle_idle()
    elseif self.state == "MINING" then
        self:handle_mining()
    elseif self.state == "BANKING" then
        self:handle_banking()
    end
    
    sleep(50)
end

function script:handle_idle()
    -- Check conditions and transition
    if inventory:full() then
        self.state = "BANKING"
    else
        self.state = "MINING"
    end
end

function script:handle_mining()
    -- Mining logic
    if inventory:full() then
        self.state = "BANKING"
    end
end

function script:handle_banking()
    -- Banking logic
    if not inventory:full() then
        self.state = "MINING"
    end
end

return script

State Transitions

States transition based on conditions:

-- Simple transition
if condition then
    self.state = "NEW_STATE"
end

-- Transition with validation
if condition and self:can_transition_to("NEW_STATE") then
    self.state = "NEW_STATE"
end

Best Practices

  1. Clear State Names: Use descriptive names like "MINING", "BANKING", "WALKING"
  2. Single Responsibility: Each state should handle one specific task
  3. Explicit Transitions: Make state transitions clear and documented
  4. State Validation: Validate conditions before transitioning
  5. Error States: Include error handling states for failure cases

Advanced Patterns

State with Sub-states

self.state = "BANKING"
self.sub_state = "WALKING_TO_BANK"

if self.sub_state == "WALKING_TO_BANK" then
    -- Walk logic
    if at_bank then
        self.sub_state = "OPENING_BANK"
    end
elseif self.sub_state == "OPENING_BANK" then
    -- Open bank logic
end

State History

self.state_history = {}

function script:transition_to(new_state)
    table.insert(self.state_history, self.state)
    self.state = new_state
end