# Inform To RenPy Porting Guide

The Inform source is table-heavy and rule-heavy. A good RenPy port should translate behavior, not line shape.

## Porting Order

1. Identify the content type: location, enemy, NPC, item, quest, event, infection, or system mechanic.
2. Move static table rows into registered dictionaries.
3. Move prose into labels or description functions.
4. Convert Inform conditions into RenPy `if` branches or Python helper functions.
5. Convert state changes into explicit player, quest, NPC, or global variables.
6. Wire the content into navigation, encounters, shops, quests, or menus.
7. Delete source comments and placeholder scaffolding once the content is playable.

## Inform Tables

Common mappings:

- `Table of Random Critters` -> `register_enemy(...)` plus encounter areas.
- `Table of GameRoomIDs` -> `register_location(...)`.
- `Table of Game Objects` -> `register_item(...)`.
- NPC declarations -> `register_npc(...)`.
- Multi-stage scenes -> `register_quest(...)` plus labels.

Do not leave a table as an inert dictionary if no runtime system uses it.

## Inform Rules

Inform rules usually become helper functions. Keep them small and named after the behavior:

```renpy
init python:
    def can_enter_power_plant():
        return has_item_id("power_badge") or player.intelligence >= 16
```

Use the helper from menus, scene labels, or encounter filters.

## Descriptions

Inform often builds descriptions from many conditional fragments. In RenPy, prefer a description label or function that assembles the same result:

```renpy
label power_plant_desc:
    $ desc = "The power plant hums with damaged machinery."
    if is_quest_complete("restore_power"):
        $ desc += " The lights are stable again."
    else:
        $ desc += " Emergency lamps pulse red along the walls."
    "[desc]"
    return
```

When a source sentence only changes one fragment, keep the whole sentence in one Ren'Py dialogue string and splice the variable text inline with an expression. Do not split it into separate `say` lines or standalone `if` blocks unless the Inform source really has separate dialogue beats. If the fragment needs leading or trailing whitespace, include that whitespace in the inserted expression so the rendered sentence still reads naturally.

## Quests And Events

Use events for one-off or repeatable scenes. Use quests when the player should be able to track progress.

Event dictionary:

```renpy
init python:
    register_event({
        "id": "street_ambush",
        "name": "Street Ambush",
        "trigger": "area:Outside",
        "scenes": ["street_ambush_scene"],
        "rewards": {},
    })
```

Quest dictionary:

```renpy
init python:
    register_quest({
        "id": "restore_power",
        "name": "Restore Power",
        "description": "The bunker needs stable electricity.",
        "trigger": "location:power_plant",
        "prereqs": [],
        "stages": [0, 1, 100],
        "scenes": ["restore_power_start", "restore_power_repair", "restore_power_done"],
        "rewards": {},
    })
```

## What Not To Port Literally

- Inform comments.
- Disabled Inform code.
- Debug-only output.
- Placeholder NPCs that exist only as variable containers.
- Repeated conditional text variants collapsed into one unreadable string, or split into multiple dialogue lines when the source only varies a fragment.

When a source section cannot be completed yet, create a small playable fallback and record the missing behavior in an external issue or guide, not in the visible game text.
