서리의 세계

서리의 현재 상태는 매번 임의로 생성되지 않고, 단일한 시뮬레이션 세계 안에서 누적된 일정과 상태를 바탕으로 결정됩니다.

시간, 날씨, 신체 컨디션, 학업 일정, 지인 관계, 소소한 사건과 일기. 10분 주기로 동작하는 생활 시뮬레이션 시스템의 세부 동작 방식을 정리한 문서입니다.
10분시뮬레이션 갱신 주기
8개신체 상태 수치
15~25회일일 모델 호출 횟수
1개공유 세계 수

왜 만들었나

기존 방식에서는 현재 상태에 대한 질의가 들어올 때마다 매번 새로운 상태를 생성했습니다.

이전
  • 물을 때마다 새로 지어내는 근황
  • 5분 전에는 과제, 지금은 카페
  • 어제도 내일도 없음
  • 세계의 내용이 코드에 박혀 있음
  • 갱신 주기가 불규칙해 하루 종일 같은 상태
지금
  • 계획표의 그 시각에 있는 장소
  • 누가 물어도 같은 대답
  • 어제 일기와 이틀 뒤 마감이 있음
  • 세계는 헌법과 한 줄 프리미스에서 생성
  • 10분마다 정확히 한 걸음

재설계 시 적용한 두 가지 원칙

01

세계의 내용은 코드에 없다

장소, 지인, 일정, 이야기, 소지품, 하루 리듬 전부를 서리의 헌법과 한 줄 프리미스에서 생성합니다. 다른 캐릭터에 동일 엔진을 연결해도 각 캐릭터에 맞는 독립된 세계가 생성됩니다.

02

숫자는 코드가, 언어는 모델이

허기 수치, 과제 진척도, 감기 발병 확률 등 상태 수치는 수식으로 계산합니다. 모델은 현재 순간의 묘사, 대화 등 언어 생성이 필요한 영역에만 제한적으로 호출하며, 호출 실패 시 결정론적 기본값으로 대체합니다.

결정론 코드가 정하는 것
컨디션 8종질병 발생과 회복시간날씨공부 진척지출과 잔고기분 강제계획 정규화사건 게이트
모델이 쓰는 것
세계 생성하루 계획지금 순간사건의 내용이야기 진행일기

전체 그림

헌법에서 태어난 세계가 10분마다 굴러가고, 그 상태가 대화로 흘러들어 갔다가 다시 돌아옵니다.

flowchart TB
  A["서리의 헌법 + 한 줄 프리미스"] --> B["`**세계 생성**
장소 · 사람 · 소지품
하루 리듬 · 일정 · 이야기`"]
  B --> C{"10분마다 틱"}
  C -->|결정론 코드| D["`컨디션 · 질병
진척 · 지출`"]
  C -->|모델| E["`계획 · 순간
사건 · 이야기 · 일기`"]
  D --> F["450토큰 상태 블록"]
  E --> F
  E --> G["Discord 상태줄"]
  F --> H["대화 프롬프트"]
  H -->|턴 반영| C
              
세계는 한 번 생성되고, 이후에는 틱이 세계를 굴립니다.

세계의 탄생

출력 길이 초과로 인한 생성 중단을 방지하기 위해 기본 뼈대와 캘린더/서사를 두 단계 호출로 분리했습니다.

flowchart TB
  IN["`이름 · 한 줄 소개 · 헌법 전문
프리미스 · 오늘 날짜와 요일과 계절`"] --> C1["**1차 호출** 뼈대"]
  C1 --> O1["`생활 요약 · 장소 6~9곳
사람 4~6명 · 소지품 6~10개
하루 리듬 5~9슬롯 · 취향과 습관`"]
  O1 --> C2["**2차 호출** 캘린더와 이야기"]
  C2 --> O2["`일정 8~14개 · 이야기 3~4개`"]
  C1 -.실패.-> FB["`**스켈레톤 세계**
집 · 동네 길 · 기본 6슬롯
상태를 실패로 기록`"]
  C2 -.실패.-> FB
              
생성에 실패하면 스켈레톤 기본값을 할당하고 실패 상태를 기록합니다.
6~9장소

집은 반드시 하나. 각 장소에 할 수 있는 활동, 여는 시간, 집에서 걸리는 시간이 붙습니다.

4~6사람

가족, 친구, 선생님처럼 관계가 다양하게. 성격 한 줄, 연락 방식, 생활 리듬, 0~100의 친밀도.

6~10소지품

가방에 있는 것과 방에 있는 것. 브랜드보다 생활감 있는 물건으로.

5~9하루 리듬

요일별로 0분부터 1440분까지 빈틈없이. 수면 슬롯도 포함됩니다.

8~14일정

수업이나 알바처럼 반복되는 것과 시험, 과제, 약속처럼 한 번뿐인 것을 섞어서.

3~4이야기

며칠에서 몇 주에 걸쳐 진행될 실타래. 현재 요약, 다음 비트, 0~1의 긴장도.

두 호출 모두 헌법에 있는 사실은 바꾸지 못합니다. 실존 인물과 유명인은 금지, 큰 비극이나 범죄도 금지입니다. 줄임말은 그 나이대의 통상 의미로 읽으라는 규칙도 있는데, 초기 테스트에서 "마크"를 마인크래프트가 아닌 것으로 읽은 일이 있었기 때문입니다.

컨디션 여덟 숫자

서리의 신체 상태는 0에서 1 사이의 8개 수치로 관리됩니다. 아래는 기본값 기준입니다.

허기0.30
배부름배고픔

높을수록 나쁨

에너지0.70
방전쌩쌩함

낮을수록 나쁨

졸림0.30
말똥말똥졸림

높을수록 나쁨

스트레스0.30
느긋함예민함

높을수록 나쁨

청결0.80
꼬질함개운함

낮을수록 나쁨

사람0.60
심심함충전됨

낮을수록 나쁨

재미0.60
지루함신남

낮을수록 나쁨

건강0.85
골골함튼튼함

낮을수록 나쁨

활동 열두 가지가 숫자를 움직입니다

현재 진행 중인 활동에 따라 시간당 정해진 비율로 변화합니다. 녹색은 개선, 적색은 악화 방향이며 색 농도에 따라 변화 폭이 커집니다.

활동허기에너지졸림스트레스청결사람재미
수면+.02+.12−.14−.06−.01··
식사−.80+.05·−.05−.02+.05+.10
이동+.06−.06+.02+.04−.03·−.01
수업+.06−.05+.05+.04−.01+.02−.02
공부+.06−.06+.04+.05−.01−.02−.03
일+.07−.08+.03+.06−.03+.02−.03
사람 만나기+.05−.04+.01−.06−.02+.25+.15
여가+.05−.02+.03−.08−.01·+.20
씻기+.03+.02·−.05+.90··
휴식+.04+.05−.02−.06−.01·+.03
볼일+.06−.05·+.02−.02+.03+.02
온라인+.05−.02+.04−.03·+.08+.12

시간당 변화량입니다. 여덟 시간 자면 에너지가 0.96 차고, 30분 식사면 허기가 0.4 풀리고, 20분 씻으면 충분히 개운해집니다. 하루 계획이 어디서 오든 수면 6.5시간, 세 끼 식사, 씻기, 숨 돌릴 시간은 결정론으로 보장됩니다.

건강만 규칙이 다릅니다

평소시간당 +0.008
에너지 < 0.25−0.01
스트레스 > 0.75−0.01
허기 > 0.85−0.008
자거나 쉬는 중추가로 +0.01
앓는 중심각도에 비례해 −

각 조건은 중첩 적용됩니다. 수면 부족이나 식사 누락이 지속되면 건강 수치 감쇄 속도가 빨라집니다.

아프기도 합니다

매 시간 발병 확률을 계산하며, 신체 조건 악화 시 확률이 추가로 증가합니다.

기본0.08%
건강 < 0.4+1.2%p
건강 < 0.6+0.4%p
에너지 < 0.25+0.5%p
청결 < 0.3+0.3%p
비 · 폭우 · 눈 · 한파+0.3%p
기온 −3도 이하 또는 34도 이상+0.2%p

시간당 확률입니다. 조건이 중첩되면 합산되며, 완치 후 3일간은 재발하지 않습니다.

걸리는 병 네 가지

감기

2~4일. "목이 칼칼하고 콧물이 남"

몸살

1~2일. "온몸이 무겁고 만사 귀찮음"

두통

1~2일. "머리가 지끈거림"

배탈

1~2일. "속이 더부룩하고 입맛 없음"

심각도는 0.35~0.65 범위에서 시작하며, 앓는 동안 에너지가 추가 감쇄되고 졸림과 스트레스가 증가합니다. 에너지가 0.5 이상이면 회복 속도가 2배 빨라집니다. 해당 상태는 대화 프롬프트의 컨디션 항목에 그대로 반영됩니다.

기분은 계산됩니다

우선순위 조건에 처음 부합하는 항목이 기분을 결정합니다. 조건에 해당하지 않으면 서사 및 대화에서 결정된 이전 기분을 유지합니다.

  1. 병 심각도 ≥ 0.3골골함
  2. 허기 > 0.8배고픔
  3. 에너지 < 0.18방전
  4. 졸림 > 0.82졸림
  5. 스트레스 > 0.8예민함
  6. 사람 < 0.2 그리고 재미 < 0.3심심함
  7. 재미 < 0.2지루함
  8. 여덟 항목 모두 편안 · 재미 > 0.75 · 사람 > 0.65기분 좋음
  9. 그 밖의 모든 경우이전 기분 유지

컨디션이 극단으로 치닫지 않는 한 기분은 서사와 대화가 정하고, 신체 수치가 임계치를 넘으면 신체 상태가 우선합니다.

시간과 날씨

세계의 시간은 실제 시간과 같이 흐릅니다. 날씨는 외부 API 없이, 봇 아이디와 날짜를 시드로 삼아 결정론적으로 뽑습니다.

계절마다 다른 확률표

겨울 12~2월 맑음 34 구름 22 흐림 14 눈 12 한파 10 바람 6 안개 2
봄 3~5월 맑음 36 구름 24 비 14 흐림 12 바람 8 안개 6
장마 6~7월 비 24 구름 22 맑음 18 흐림 16 폭우 12 폭염 8
한여름 8월 폭염 24 맑음 22 구름 18 비 16 폭우 12 흐림 8
가을 9~11월 맑음 42 구름 24 흐림 12 비 10 바람 6 안개 6

월별 평균 기온

0도 −12713 19232627 221581 1234 5678 9101112
한반도 중부 기준입니다. 실제 값은 여기에 변동폭이 얹히고 어제 날씨와 이어지도록 보정됩니다.

같은 날짜에는 항상 같은 날씨가 나옵니다. 날씨는 하루 계획에서 밖 일정을 줄이고, 발병 확률에 반영되고, 궂은 날이면 환경 사건 확률을 두 배 이상 올립니다.

하루 계획

날짜가 바뀌면 오늘 하루를 8~14개의 시간 슬롯으로 채웁니다. 아래는 평일 하루의 예시입니다.

0시6시12시18시24시

각 슬롯에는 시작과 끝 시각, 장소, 활동 종류, 서리 시점의 짧은 이름("카페에서 과제", "방에서 게임"), 왜 그걸 하는지 한 줄, 같이 있는 사람, 연결된 캘린더 항목, 그리고 말 걸기 좋은 정도가 붙습니다.

모델이 짠 계획을 그대로 쓰지는 않습니다

1

빈틈 메우기

새벽과 늦은 밤이면 잠으로, 낮이면 집에서 쉬는 것으로.

2

겹침 정리

겹치면 뒤 슬롯이 우선입니다.

3

없는 장소 교정

세계에 없는 장소를 적었으면 집으로 바꿉니다.

4

고정 블록 덮어쓰기

수업 시간에 카페에 가는 계획이 나와도 수업이 이깁니다.

모델이 실패하면 세계 생성 때 만든 하루 리듬을 펼친 뒤 같은 정규화를 거칩니다. 그래서 계획이 없는 날은 없습니다.

10분마다의 틱

기본 10분 주기의 틱을 통해 시뮬레이션을 진행합니다.

flowchart TB
  T1["`**1** 내 차례인지 확인
잠금은 10분`"] --> T2{"**2** 날짜가 바뀌었나"}
  T2 -->|예| N["`어제 일기 · 지난 일정 정리
오늘 날씨 · 이야기 진행 · 오늘 계획`"]
  T2 -->|아니오| T3
  N --> T3["`**3** 경과 시간을 슬롯 단위로 잘라
컨디션 · 질병 · 진척 · 지출 적용`"]
  T3 --> T4["`**4** 슬롯이 바뀌었으면
지금 순간 다시 쓰기`"]
  T4 --> T5["`**5** 게이트를 통과하면
종류를 골라 사건 생성`"]
  T5 --> T6["**6** 다음 틱 시각 결정"]
              
오프라인 시간은 재기동 시 최대 24시간까지 일괄 보정합니다.

공부 진척 공식

과제와 연결된 공부 슬롯시간당 16 + 에너지 × 14
시험 공부 슬롯시간당 10 + 에너지 × 8
마감이 지난 과제진척 100이면 제출, 아니면 놓침
시험진척 40 이상이면 치른 것

에너지가 1일 때는 시간당 30, 0.3일 때는 20가량 증가합니다. 피로 누적 시 진척 효율이 떨어집니다.

지금 순간

계획 슬롯이 전환되거나 유지 시간이 만료되면 현재 상태를 묘사하는 문장을 생성합니다.

순간 (1~2문장)

방 책상에 엎드려서 이어폰으로 노래 틀어 놓고 수학 문제집을 넘기는 중. 아까 산 커피가 아직 반쯤 남아 있다.

상태줄 (16자)수학 문제 푸는 중
기분무난함
말 걸기보통
유지 시간20~180분

현재 활동과 장소를 유지하면서 세부 맥락(음식, 배경 음악, 동행자 등)을 덧붙입니다. 수면 중에는 모델을 호출하지 않고 상태를 '자는 중'으로 고정합니다. 호출 실패 시에는 슬롯 명칭을 기반으로 기본 문장을 구성합니다.

사건

일상의 변수를 부여하기 위한 시스템입니다. 틱마다 게이트 검사를 거친 후 확률에 따라 사건을 발생시킵니다.

자고 있으면 없음

최근 사건에서 45분이 안 지났으면 없음

하루 상한을 넘었으면 없음

통과하면 자발성과 틱 간격으로 확률 계산

2건자발성 0
3건자발성 40 (기본)
6건자발성 100

일일 사건 상한입니다. 자발성 40, 10분 틱 기준 1회당 약 2.8% 확률로 발생하며, 활동 시간 16시간 동안 평균 2~3건이 실행되도록 조정되어 있습니다.

어떤 종류의 사건이 일어날까

사람40낮 12~23시 ×1.4, 주말 ×1.2, 새벽 ×0.3
이야기10가장 긴장 높은 이야기의 긴장 ×20 가산
학업8D-2 마감이면 20, 수업·공부 중 +8
취미8여가·온라인·휴식 중이면 16
환경7궂은 날씨면 18
건강4건강 0.45 미만이면 14, 앓는 중 +8

기본 가중치와 상황 보정입니다. 사람 사건이면 누가 연락할지도 고르는데, 친밀도가 높을수록 그리고 최근에 안 봤을수록 확률이 높습니다. 72시간 이상 못 본 사람은 가중치가 두 배가 됩니다.

사건이 세계에 남기는 것

컨디션 변화 (항목당 ±0.4) 친밀도 변화 (±10) 그 사람이 기억할 한 줄 쓴 돈, 받은 돈 생긴 생각 (무게 1~10) 새 약속이나 마감 과제 진척 변화 이야기 긴장도 (±0.3) 얻거나 쓴 물건 병의 시작이나 회복

사건은 연락, 날씨 변화, 과제 진행, 취미 등 일상적인 범위로 한정합니다. 중대 사고나 범죄, 실존 인물 관련 내용은 허용하지 않습니다. 생성 실패 시 사건을 임의로 만들지 않고 무시합니다.

이야기

사건이 단발성이라면 이야기는 일정 기간 이어지는 서사 흐름입니다. 6개 단계와 0~1 사이의 긴장도 값을 가집니다.

  1. 씨앗막 시작됨
  2. 상승긴장 0.5 초과
  3. 절정긴장 0.85 초과
  4. 해소긴장 0.1 미만
  5. 해결자연스럽게 끝남
  6. 흐지부지조용히 식음

날짜가 변경될 때마다 전일 일기와 최근 사건을 검토하여 각 이야기의 단계, 긴장도, 요약, 다음 전개 목표를 갱신합니다. 하루에 2단계 이상 건너뛰지 않으며, 사건이 없었던 이야기는 긴장도를 유지하거나 소폭 올립니다. 활성 이야기가 3개 미만이면 새로운 일상 서사를 1~2개 생성합니다.

어떤 이야기가 계속 사건을 부르면 며칠 안에 절정에 이르고, 조용하면 천천히 식습니다.

하루의 일기

자정 경과 시 전일 기록된 사건과 활동 데이터를 바탕으로 일기를 작성합니다.

오늘은 그냥 그랬다. 아침에 늦잠 자서 아침 거르고 뛰었고, 3교시에 졸다가 걸렸다. 점심에 지민이가 편의점 젤리 사 줘서 좀 살아났고. 저녁 먹고 수학 문제집 스무 장 넘겼는데 이틀 뒤 수행평가 생각하면 아직 멀었다.

기분 흐름

아침엔 늘어졌다가 저녁에 좀 풀림

기억에 남을 것

지민이 젤리, 3교시 졸다 걸림, 수행평가 D-2

기록된 사건이 적으면 짧게 정리합니다. 일기 내용은 익일 계획 수립, 서사 갱신 및 과거 일정 관련 질의 응답에 활용됩니다.

대화와의 연결

답변 생성 시 프롬프트에 세계 상태를 요약한 450토큰 규모의 블록이 주입됩니다.

flowchart TB
  W["세계의 지금 상태"] --> B["450토큰 상태 블록"]
  B --> P["대화 프롬프트"]
  P --> R["서리의 답"]
  R --> X["`대화에서 정해진 것
기분 · 행동 · 생각 · 약속`"]
  X --> W
  W --> D["Discord 상태줄"]
              
세계는 대화로 흘러들어 가고, 대화는 작은 폭으로 세계에 돌아옵니다.

상태 블록에 들어가는 것

시각과 날씨지금 몇 시, 어떤 날씨
지금어디에서 무엇을
컨디션"조금 출출함, 좀 피곤함, 에너지 42%"
말 걸기 힌트"집중 중이라 대답이 짧고 느릴 수 있다"
오늘 있었던 일최대 4개
이따 할 일2개
다가오는 일정3개
신경 쓰이는 것최대 5개
요즘 이야기2개
최근 연락한 사람2명과 마지막 한 줄
어제 일기요약

세계 상태는 대화의 보조 맥락으로만 사용됩니다. 질문을 받거나 문맥상 자연스러운 경우에만 상태를 짧게 언급하며, 세계 상태를 핑계로 대화를 회피하거나 중단하지 않도록 시스템 차원에서 제한했습니다.

대화 중 식사나 휴식을 언급하면 관련 수치가 즉시 일부 조정됩니다. 단, 대화로 인한 변동 폭은 경과 시간 한도로 제한되어 반복 질의로 수치가 급변하지 않습니다. 이미 진행 중인 활동은 중복 가산하지 않으며, 새로 생성된 생각은 48시간, 약속은 7일간 상태 블록에 유지됩니다.

Discord 상태줄

세계가 켜져 있으면 Discord 프로필의 상태줄도 세계가 공급합니다. 순간의 상태줄 한 줄이 그대로 올라가고, 자거나 수업 중처럼 말 걸기 좋은 정도가 낮으면 자리비움으로 표시할 수도 있습니다. 장소나 기분은 넣지 않고 실제 활동만 담습니다.

자는 중 과제 하는 중 친구랑 밥 먹는 중 수업 듣는 중

하나의 세계, 둘의 약속

모든 유저가 동일한 세계 시뮬레이션을 공유하지만, 개별 대화에서 발생한 개인 약속과 기억은 분리됩니다.

약속한 당사자에게는

"오늘 밤에 같이 마크 하기로 함"

원문 그대로 프롬프트에 올라갑니다.

다른 사람에게는

"누군가와 하기로 한 일이 있음"

일정이 있다는 사실은 지키되 내용은 밝히지 않습니다.

순간 묘사, 사건, 서사, 일기 작성 시에도 특정 대화의 상세 내용은 익명화된 상태로 전달되어 타 서버나 타인에게 노출되지 않습니다. 대화에서 파생된 생각 역시 해당 대화 상대와의 턴에서만 프롬프트에 주입됩니다.

이 구분은 이용자 사이의 이야기입니다. 서리를 운영하는 저희는 운영 화면에서 세계에 남은 기록을 확인할 수 있습니다. 다른 이용자에게 보이지 않는다는 뜻이지, 기록 자체가 없다는 뜻은 아닙니다.

비용과 운영

호출 횟수와 토큰을 제한하여 운영 비용을 최소화합니다. 하루 총 15~25회 호출되며, 1회당 600토큰 이하로 제어합니다.

지금 순간8~12회
사건2~6회
하루 계획1회
이야기 진행1회
일기1회
세계 생성처음 2회

모든 출력은 정해진 형식으로 검증하고, 형식이 어긋나면 한 번 복구를 시도한 뒤 안 되면 결정론 폴백으로 넘어갑니다. 세계에 쓰는 모델은 대화 모델과 별개로 고를 수 있고, 응답 예산은 엄격하게부터 여유롭게까지 네 단계로 0.75배에서 2.5배까지 조절됩니다.

운영 화면 여섯 탭

지금

오늘 계획, 현재 순간, 컨디션, 오늘 사건.

세계

장소, 사람과 친밀도와 기억, 캘린더, 소지품, 잔고.

이야기

진행 중인 이야기의 단계와 긴장도와 비트, 그리고 일기.

머릿속

지금 신경 쓰이는 생각들. 직접 넣거나 지울 수 있습니다.

관제

세계 켜고 끄기, 모델과 파라미터, 프리미스 재생성, 자발성과 틱 간격, 사건 주입과 시간 앞당기기.

이력

모든 변경을 커밋처럼 기록. 전과 후를 빨간 줄과 초록 줄로 비교합니다. 봇마다 최근 1000건.

아직 못 한 것

현재 구현된 범위와 향후 개발 과제입니다.

  • 선제 연락 기능: 사건 생성 단계에서 발신 필요성을 판단하는 로직은 마련되어 있으나, 디스코드 DM 발송 파이프라인 연동은 별도 과제로 남아 있습니다.
  • 개별 요소 수동 편집 UI: 장소, 인물, 일정을 개별 편집하는 화면을 추가할 예정입니다. 현재는 프리미스 재설정이나 관제 명령을 통해 조정합니다.

서리의 세계는 헌법에서 생성된 하나의 세계 안에서, 10분마다 결정론 코드가 컨디션과 일정과 진척을 계산하고, 언어 모델은 필요한 순간에만 제한적으로 텍스트를 작성합니다. 그 결과는 450토큰 상태 블록으로 모든 대화에 주입되며, 대화 중 발생한 변경점은 유저 격리를 거쳐 다시 시뮬레이션에 안전하게 반영됩니다.

이제 서리에게 "지금 뭐 해?"라고 물으면, 그 답은 계획표의 그 시각에 서리가 있는 장소, 오늘의 날씨, 몇 시간째 비워둔 식사, 이틀 뒤 마감인 과제, 오전에 도착한 친구의 연락 위에서 나옵니다. 5분 뒤에 다른 분이 같은 질문을 해도 같은 맥락의 답이 돌아옵니다. 그것이 캐릭터가 살아 있다는 것의 최소 조건이라고 보았습니다.