> ## Documentation Index
> Fetch the complete documentation index at: https://docs.razebot.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Logic and randomness

> Branch on conditions with if/elseif/else and roll random values inside a response.

# Logic and randomness

> Branch on conditions with if/elseif/else and roll random values inside a response.

Conditionals and random tags run inside the core scripting engine, so they work in custom commands and anywhere else raze accepts a script.

***

## Conditionals

```text theme={null} theme={null}
{if:CONDITION}shown when true{else}shown otherwise{endif}
```

`{/if}` is an alias for `{endif}`, and the colon is optional (`{if CONDITION}` also parses).

<Steps>
  <Step title="Start with a single branch">
    ```bash theme={null} theme={null}
    ;cc set vip -- {if:user has role VIP}Welcome back, VIP.{endif}
    ```
  </Step>

  <Step title="Add an else">
    ```bash theme={null} theme={null}
    ;cc set vip -- {if:user has role VIP}Welcome back, VIP.{else}Ask a mod about VIP perks.{endif}
    ```
  </Step>

  <Step title="Chain more cases with elseif">
    ```bash theme={null} theme={null}
    ;cc set tier (score) -- {if:{score}>=100}gold{elseif:{score}>=50}silver{else}bronze{endif}
    ```

    ```bash theme={null} theme={null}
    ;tier 70
    ```

    > silver
  </Step>
</Steps>

### Condition types

<AccordionGroup>
  <Accordion title="Comparisons" icon="equals">
    Operators: `==`, `!=`, `>=`, `<=`, `>`, `<`.

    If **both** sides parse as numbers they are compared numerically; otherwise they are compared as text.

    ```text theme={null} theme={null}
    {if:{arg.count}>2}too many arguments{endif}
    {if:{choice}==heads}you called it{endif}
    ```
  </Accordion>

  <Accordion title="contains" icon="magnifying-glass">
    Case-insensitive substring test.

    ```text theme={null} theme={null}
    {if:{message} contains discord.gg}No invites, please.{endif}
    ```
  </Accordion>

  <Accordion title="user has role" icon="user-shield">
    Accepts a role mention, a role ID, or a role name.

    ```text theme={null} theme={null}
    {if:user has role @Staff}...{endif}
    {if:user has role 1234567890}...{endif}
    {if:user has role Moderator}...{endif}
    ```
  </Accordion>

  <Accordion title="user has permission" icon="key">
    Accepts any Discord permission name in any casing — `ManageMessages`, `manage_messages`, and `Manage Messages` all resolve to the same permission.

    ```text theme={null} theme={null}
    {if:user has permission ManageMessages}staff-only text{endif}
    ```
  </Accordion>

  <Accordion title="Truthiness" icon="check">
    A bare value is true unless it is empty or one of `false`, `none`, `n/a` (any casing, surrounded whitespace ignored). `exists (value)` does the same check explicitly.

    ```text theme={null} theme={null}
    {if:{message}}You said: {message}{else}You said nothing.{endif}
    {if:exists {reason}}Reason: {reason}{endif}
    ```
  </Accordion>
</AccordionGroup>

<Info>
  Variables are substituted **before** conditions are evaluated, which is why `{if:{score}>=100}` works. By evaluation time a condition should contain no leftover `{ }` — an unresolved variable inside a condition breaks the block.
</Info>

<Warning>
  [Database tags](/server-config/custom-commands/stored-data) resolve **after** conditionals, so `{db.get:...}` and `{db.exists:...}` cannot be tested inside a condition.
</Warning>

<Warning>
  Blocks may nest up to 20 levels deep, and a single script may contain at most 500 conditional tags. Past either limit the remaining tags are left as-is instead of being evaluated.
</Warning>

***

## Random values

| Tag                           | Does                                                   |
| :---------------------------- | :----------------------------------------------------- |
| `{choose:a\|b\|c}`            | Picks one option at random.                            |
| `{random:a\|b\|c}`            | Alias of `{choose}`.                                   |
| `{range:(low)-(high)}`        | A random whole number between low and high, inclusive. |
| `{choice:(name):a\|b\|c}`     | Picks one option **and saves it** as `{name}`.         |
| `{range:(name):(low)-(high)}` | Rolls a number **and saves it** as `{name}`.           |

```bash theme={null} theme={null}
;cc set coinflip -- {choose:heads|tails}
;cc set d20 -- You rolled a {range:1-20}.
```

### Reusing a rolled value

Plain `{choose}` and `{range}` reroll on every occurrence. Use the named forms when the same result has to appear more than once — including inside a condition.

```bash theme={null} theme={null}
;cc set flip -- You got **{choice:result:heads|tails}**! That's {if:{result}==heads}lucky{else}unlucky{endif}.
```

```bash theme={null} theme={null}
;flip
```

> You got **heads**! That's lucky.

<Warning>
  `{range}` bounds must be **literal digits**. Random tags resolve before argument substitution, so `{range:1-{sides}}` never rolls — it renders as plain text. Branch on the argument instead:

  ```bash theme={null} theme={null}
  ;cc set roll (sides) -- {if:{sides}==6}{range:1-6}{elseif:{sides}==20}{range:1-20}{else}Use 6 or 20.{endif}
  ```
</Warning>

<Note>
  Saved names may contain letters, digits, `_`, `.`, and `-`. A saved value replaces every `{name}` that appears anywhere later in the script.
</Note>
