{% extends "base.html" %} {% block title %}Events — df-storyteller{% endblock %} {% block content %}

Events

A live record of happenings in the fortress

Connecting...
{% if events %} {% set ns = namespace(current_group='') %} {% for event in events %} {% set group = event.season | title ~ ' ' ~ event.year %} {% if group != ns.current_group %} {% set ns.current_group = group %}
{{ group }}
{% endif %}
{{ event.date_label | default(event.type | replace('_', ' ') | title) }} · {{ event.type | replace('_', ' ') | title }}
{{ event.description }}
{% endfor %} {% else %}

No events captured yet. Events auto-start when you load a fortress.

{% endif %}
{% macro render_blowbyblow(raw_lines) %}
{% for line in raw_lines %} {% set lower_line = line.lower() %} {% if 'hacks' in lower_line or 'slashes' in lower_line or 'stabs' in lower_line or 'strikes' in lower_line or 'punches' in lower_line or 'kicks' in lower_line or 'bites' in lower_line or 'scratches' in lower_line or 'bashes' in lower_line or 'gores' in lower_line %}
{{ line }}
{% elif 'artery' in lower_line or 'tendon' in lower_line or 'nerve' in lower_line or 'has been' in lower_line %}
{{ line }}
{% elif 'the force' in lower_line %}
{{ line }}
{% elif 'falls over' in lower_line or 'gives in' in lower_line or 'knocked unconscious' in lower_line or 'collapses' in lower_line %}
{{ line }}
{% elif 'cloven asunder' in lower_line or 'sails off' in lower_line or 'flies off' in lower_line %}
{{ line }}
{% else %}
{{ line }}
{% endif %} {% endfor %}
{% endmacro %} {% if combat_encounters %}

Expand a fight to see blow-by-blow details{% if not no_llm_mode %} or generate a battle report{% endif %}

{% for encounter in combat_encounters %} {% if encounter.is_engagement is defined and encounter.is_engagement %} {# Grouped engagement — multiple fights in one battle/siege #}
{% if encounter.is_siege is defined and encounter.is_siege %}Siege{% else %}Battle{% endif %} — {{ encounter.fight_count }} fights {{ encounter.total_blows }} blows · {{ encounter.participants | length }} combatants {% if encounter.casualties %} · {{ encounter.casualties }} killed{% endif %}
{{ encounter.season | title }} {{ encounter.year }}
{# Condensed target summary #} {% if encounter.targets is defined and encounter.targets %}
{% for target in encounter.targets %}
vs {{ target.name }} — {{ target.blows }} blow{{ 's' if target.blows != 1 else '' }} ({{ target.attackers | join(', ') }}) {% if target.defeated %}☠ defeated{% endif %} {% if target.lethal %}[FATAL]{% endif %}
{% endfor %}
{% endif %} {# Detailed fight breakdown — collapsed by default #}
Show {{ encounter.fight_count }} individual fight{{ 's' if encounter.fight_count != 1 else '' }}
{% for fight in encounter.fights %}
{{ fight.attacker }} vs {{ fight.defender }} {% if fight.weapon %} — {{ fight.weapon }}{% endif %} {{ fight.blow_count }} blow{{ 's' if fight.blow_count != 1 else '' }}{% if fight.outcome %} · {{ fight.outcome }}{% endif %}{% if fight.is_lethal %} [FATAL]{% endif %}
{{ render_blowbyblow(fight.raw_lines) }} {% if fight.outcome %}
{{ fight.defender }} {{ fight.outcome }}{% if fight.is_lethal %} — FATAL{% endif %}
{% endif %}
{% endfor %}
{% if not no_llm_mode %}
{% endif %}
{% else %} {# Solo fight #}
{{ encounter.attacker }} vs {{ encounter.defender }} {% if encounter.weapon %} — {{ encounter.weapon }}{% endif %} {{ encounter.blow_count }} blow{{ 's' if encounter.blow_count != 1 else '' }}{% if encounter.outcome %} · {{ encounter.outcome }}{% endif %}{% if encounter.is_lethal %} [FATAL]{% endif %}
{{ encounter.season | title }} {{ encounter.year }}
{{ render_blowbyblow(encounter.raw_lines) }} {% if encounter.outcome %}
{{ encounter.defender }} {{ encounter.outcome }}{% if encounter.is_lethal %} — FATAL{% endif %}
{% endif %}
{% if solo_reports and loop.index0 in solo_reports %}
Battle Report — {{ solo_reports[loop.index0].author }}
{{ solo_reports[loop.index0].text }}
— {{ solo_reports[loop.index0].author }}
{% if not no_llm_mode %} {% endif %}
{% else %} {% if not no_llm_mode %} {% endif %} {% endif %}
{% endif %} {% endfor %}
{% endif %} {% if saved_battle_reports %}

Accounts of past engagements, written by those who were there

{% for report in saved_battle_reports | reverse %}
{{ report.season | default('') | title }} of Year {{ report.year | default('?') }} — {{ report.participants | join(', ') | truncate(60) }} {% if report.is_siege %}[Siege]{% endif %} {% if report.is_lethal %}[Fatal]{% endif %}
{{ report.text }}
— {{ report.author }}
{% if report.encounter_index is defined and not no_llm_mode %} {% endif %}
{% endfor %}
{% endif %} {% if chat_lines %}

What the dwarves have been saying and feeling

{% if not no_llm_mode %}
{% endif %}
{% for chat in chat_lines %}
{{ chat.name }}, {{ chat.profession }}: {{ chat.message }}
{% endfor %}
{% if saved_chat_summaries %}
Chat Summaries ({{ saved_chat_summaries | length }})
{% for summary in saved_chat_summaries | reverse %}
{{ summary.season }} of Year {{ summary.year }}
{{ summary.text }}
{% endfor %}
{% endif %} {% endif %} {% endblock %} {% block scripts %} {% endblock %}