# PHP-DTS Game State Transitions: Complete Guide to the 7-State Game Loop

> Explore the PHP-DTS game loop and master the 7-state game state transitions. Learn triggers like time checks and player counts for efficient battle royale management.

- Repository: [Nemo Ma/phpdts](https://github.com/amarillonmc/phpdts)
- Tags: deep-dive
- Published: 2026-02-24

---

**The PHP-DTS game engine manages battle royale matches through a strict 7-state machine defined by the `$gamestate` variable, with transitions triggered by time checks, player counts, and zone expansions in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) and [`system.func.php`](https://github.com/amarillonmc/phpdts/blob/main/system.func.php).**

The `amarillonmc/phpdts` repository implements a real-time battle royale system where **game state transitions** control everything from lobby countdowns to final duels. Understanding how the `$gamestate` variable evolves from `0` (not started) through `50` (duel mode) reveals the core timing logic that drives the entire match lifecycle.

## Core Game State Architecture

The game loop relies on a single integer variable `$gamestate` that persists across requests. Each numeric value represents a distinct phase with specific entry conditions and exit triggers. The state machine enforces sequential progression with one exception: the **Duel** state (`50`) can interrupt any active combat phase.

| State | Value | Description |
|-------|-------|-------------|
| Not started | `0` | Server idle or post-game reset |
| Preparation | `10` | Lobby open, countdown active |
| Game start | `20` | Combat enabled, safe zone expanding |
| Activation stop | `30` | Registration closed, zone limits reached |
| Combo | `40` | Continuous battle mode, no safe zone resets |
| Duel | `50` | Special key-item triggered duel mode |
| Game over | `0` | Final results recorded, server reset |

## State Transition Triggers in Detail

### Not Started (0) → Preparation (10)

The transition from idle to lobby mode occurs when the current server time enters the pre-game countdown window. In [`include/common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/include/common.inc.php) lines 165–170, the system checks if the `$starttime` is within `$startmin` minutes of opening:

```php
if($now > $starttime - $startmin*60 && $gamestate == 0) {
    $gamestate = 10;
    // Lobby initialization logic
}

```

This trigger fires once per round when the server clock crosses the preparation threshold.

### Preparation (10) → Game Start (20)

At the exact scheduled start time, the **game state transition** moves from lobby to active combat. The condition in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 181–186 verifies the clock has reached `$starttime`:

```php
if($gamestate == 10 && $now >= $starttime) {
    $gamestate = 20;
    // Battle initialization begins
}

```

This transition is strictly time-gated and irreversible without manual intervention.

### Game Start (20) → Activation Stop (30)

The **Activation Stop** phase triggers when either the participant cap is reached or the safe zone expansion hits its limit. According to [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 220–227, the system monitors two variables during the `$gamestate == 20` block:

- **Participant threshold**: `$validnum >= $validlimit`
- **Zone expansion**: `$areanum >= $arealimit * $areaadd`

```php
if($validnum >= $validlimit || $areanum >= $arealimit * $areaadd) {
    $gamestate = 30;
    // Close registration, lock zone settings
}

```

Either condition immediately seals the match roster.

### Activation Stop (30) → Combo (40)

The **Combo** state enables continuous combat without safe zone resets. This **game state transition** fires when survival pressure intensifies, detected in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 230–244 through two alternative triggers:

1. **Low population**: `$alivenum <= $combolimit`
2. **Death threshold**: `$deathnum >= $real_combonum` (calculated from `$validnum` and `$deathdeno`)

```php
if($alivenum <= $combolimit) {
    $gamestate = 40;
} elseif($deathnum >= $real_combonum) {
    $gamestate = 40;
}

```

Once entered, the game remains in Combo mode until conclusion or a Duel interrupt.

### Combo Phase and Anti-AFK (≥40)

While in Combo state, the loop runs periodic anti-AFK checks. In [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 248–254, the system monitors the `$afktime` timestamp against `$antiAFKertime`:

```php
if($now > $afktime + $antiAFKertime*60) {
    antiAFK();
    $afktime = $now;
}

```

This does not change the `$gamestate` value but maintains state integrity by removing inactive players during the high-intensity phase.

### Duel Mode (50)

The **Duel** state represents an exception to the linear progression. Triggered by player action via [`include/system.func.php`](https://github.com/amarillonmc/phpdts/blob/main/include/system.func.php) lines 11–13, any player holding a duel key can force the entire server into duel mode:

```php
function duel() {
    global $gamestate;
    $gamestate = 50;
    // Save state and broadcast duel start
}

```

This overrides the current state regardless of whether the match is in standard combat (`20`), activation stop (`30`), or combo (`40`).

### Game Over (Reset to 0)

The final **game state transition** occurs when survival conditions terminate the match. Inside the `$gamestate >= 40` block, when player counts drop to one or zero, [`system.func.php`](https://github.com/amarillonmc/phpdts/blob/main/system.func.php) lines 31–34 invoke the reset sequence:

```php
function gameover() {
    // Record winners and statistics
    rs_sttime();
    $gamestate = 0;
}

```

The `rs_sttime()` function recalculates the next round's schedule before clearing the state variable in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 332–334.

## The Game Loop Execution Flow

Understanding the **game state transitions** requires following the execution order in the main loop:

1. **Lock acquisition**: The script obtains `process.lock` to prevent concurrent state modifications
2. **State persistence**: Game info loads from storage into the `$gamestate` variable
3. **Transition evaluation**: Conditions check for numeric state changes based on time, counts, or zone data
4. **Action execution**: State-specific logic runs (lobby management, combat resolution, or duel handling)
5. **State persistence**: Updated `$gamestate` values save back to storage before lock release

This cycle repeats every server tick, ensuring **game state transitions** occur at precise thresholds defined in the configuration variables (`$starttime`, `$validlimit`, `$combolimit`, etc.).

## Summary

- **PHP-DTS** uses a numeric `$gamestate` variable with 7 distinct values (0, 10, 20, 30, 40, 50) to control match phases
- **Preparation (10)** triggers when `$now` enters the `$startmin` window before `$starttime`
- **Game Start (20)** fires exactly at `$starttime`, moving from lobby to combat
- **Activation Stop (30)** occurs when `$validnum` meets `$validlimit` or zone expansion completes
- **Combo (40)** activates from low survivor counts (`$alivenum <= $combolimit`) or death thresholds
- **Duel (50)** interrupts any state via the `duel()` function in [`system.func.php`](https://github.com/amarillonmc/phpdts/blob/main/system.func.php)
- **Game Over** resets to `0` through `rs_sttime()` after `gameover()` detects final elimination

## Frequently Asked Questions

### What triggers the transition from Preparation to Game Start?

The transition from state `10` to `20` triggers when the server timestamp `$now` becomes greater than or equal to the configured `$starttime`. This check runs in [`include/common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/include/common.inc.php) lines 181–186 and represents the exact moment the battle royale match begins.

### How does the game enter the Combo state?

The **Combo** state (`40`) activates through two alternative conditions in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 230–244: either the number of alive players drops below `$combolimit`, or the death count exceeds the calculated `$real_combonum` threshold derived from total participants and the `$deathdeno` divisor.

### Can players trigger game state transitions manually?

Yes. The **Duel** state (`50`) can be triggered by any player possessing a duel key, which calls `duel()` in [`include/system.func.php`](https://github.com/amarillonmc/phpdts/blob/main/include/system.func.php) lines 11–13. This forces the server into duel mode regardless of the current state, pausing normal zone expansion and combo calculations.

### What happens when the game ends?

When the alive player count reaches one or zero while `$gamestate >= 40`, the `gameover()` function executes in [`include/system.func.php`](https://github.com/amarillonmc/phpdts/blob/main/include/system.func.php) lines 31–34. It records final statistics, calls `rs_sttime()` to schedule the next round, and resets `$gamestate` to `0` in [`common.inc.php`](https://github.com/amarillonmc/phpdts/blob/main/common.inc.php) lines 332–334.