--- id: wiki-2026-0508-papers-please title: Papers Please — Bureaucracy as Mechanic category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Papers Please, Lucas Pope, Arstotzka] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [game-design, narrative-design, indie, case-study, ethical-mechanic] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: lua framework: HaxeFlixel --- # Papers Please — Bureaucracy as Mechanic ## 매 한 줄 > **"매 Lucas Pope의 Papers Please (2013)는 매 'paperwork as gameplay'를 매 ethical horror로 변환한 매 indie milestone — 매 boring-on-purpose mechanic이 매 narrative weight를 carry."** 매 Arstotzka 국경 검문소 inspector라는 매 mundane role이 매 ration-starved family + 매 bribed comrades + 매 terrorist warning + 매 EZIC resistance message 사이에서 매 player에게 매 매 day moral dilemma 강제. 매 2026 시점에서 매 narrative-mechanic integration의 매 textbook example로 매 Game Design 학과 curriculum 표준 reference. ## 매 핵심 ### 매 design pillars - **Mechanic = theme**: 매 bureaucratic comparison (passport vs entry permit vs work visa)이 매 game's emotional engine. 매 narrative가 매 separate cutscene 아님. - **Time pressure as moral lever**: 매 day end까지 매 N people 처리 강제 → 매 player가 매 careful inspection vs throughput 사이 trade-off. - **Family economy**: 매 daily wage가 매 rent + heat + food + medicine 매 4 expense에 부족 → 매 player가 매 누구를 살릴지 결정. - **20 endings**: 매 player choice (resistance 도움 / 정부 충성 / 가족 도주 / 처형)가 매 매 different ending. ### 매 emergent player guilt - 매 same-faced NPC가 매 second day 다시 옴 — 매 player의 매 첫 거절을 기억. - 매 audio cue (passport stamp의 매 heavy thud)가 매 deny action에 매 weight 부여. - 매 documentation discrepancy를 매 player가 매 miss하면 매 terrorist가 매 entry → 매 next day news headline. ### 매 응용 1. **Beholder (2017)**: 매 surveillance landlord 게임 — 매 Papers Please의 매 spiritual 후속. 2. **Not For Broadcast (2022)**: 매 propaganda TV station editing — 매 mechanic = ideology. 3. **The Westport Independent (2016)**: 매 censored newspaper editor — 매 redaction이 매 gameplay verb. ## 💻 패턴 ### Document validation rule engine ```lua -- 매 document validation은 매 N rule list — 매 day마다 rule 추가 local rules = {} table.insert(rules, function(doc) if doc.expiration < currentDate then return false, "passport expired" end return true end) table.insert(rules, function(doc) if doc.entryPermit and doc.entryPermit.duration > 14 then return false, "entry permit duration mismatch" end return true end) function ValidateAll(doc) for _, rule in ipairs(rules) do local ok, reason = rule(doc) if not ok then return false, reason end end return true end ``` ### Discrepancy detection (visual click target) ```lua -- 매 player가 매 두 document의 매 mismatched field를 매 click으로 highlight function OnFieldClick(field1, field2) if field1.value ~= field2.value then ShowCitation({ field1 = field1, field2 = field2, reason = "Mismatched " .. field1.name, }) end end ``` ### Daily expense allocator ```lua local expenses = { rent = 20, heat = 10, food = 10, medicine = 15 } local wages = countApproved * 5 function ChooseExpenses(wages) -- 매 player가 매 priority slider 조정 — 매 family member 누가 starve할지 local sorted = SortByPriority(expenses) local remaining = wages local paid = {} for _, e in ipairs(sorted) do if remaining >= e.amount then paid[e.name] = true remaining = remaining - e.amount else paid[e.name] = false end end ApplyConsequences(paid) -- 매 starve event, sickness, eviction end ``` ### Branching ending state ```lua local endingFlags = { helped_ezic = 0, -- 매 EZIC mission 완료 횟수 arrested = false, family_escaped = false, bribes_taken = 0, correct_calls_pct = 0, } function ResolveEnding() if endingFlags.family_escaped then return "ending_18_obristan_refuge" end if endingFlags.helped_ezic >= 5 then return "ending_19_ezic_revolution" end if endingFlags.bribes_taken >= 8 then return "ending_05_corruption" end if endingFlags.arrested then return "ending_07_executed" end return "ending_20_status_quo" end ``` ### NPC return + memory ```lua local npcMemory = {} -- name → previous interaction outcome function OnNPCArrive(npc) local prev = npcMemory[npc.id] if prev == "denied" then npc.dialogue = "Please. My family. We have nowhere else." elseif prev == "approved" then npc.dialogue = "Inspector — thank you. I have my brother's papers now." end end ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Heavy theme indie | Mechanic = theme (Papers Please 식) | | Pure puzzle | 매 mechanic만, narrative 분리 | | AAA narrative | Mechanic + cutscene + dialogue tree (Last of Us) | | 짧은 jam game | Single-day Papers Please slice | | Educational sim | 매 real-world bureaucracy mechanic 그대로 transpose | **기본값**: 매 mechanic-theme alignment 의 first principle — 매 player가 매 verb 행할 때 매 theme를 felt 해야. ## 🔗 Graph ## 🤖 LLM 활용 **언제**: 매 narrative-mechanic alignment brainstorm — LLM에게 "매 game theme이 매 X일 때 매 player verb는 매 무엇이어야 theme을 reinforce하나" 질문. **언제 X**: 매 specific document layout / typography — 매 Lucas Pope의 매 hand-crafted aesthetic은 매 LLM generate 어려움. ## ❌ 안티패턴 - **Mechanic-narrative split**: 매 cutscene에서 매 theme 다루고 매 gameplay에서 매 매 unrelated verb. - **Time pressure without payoff**: 매 hurry mechanic만 있고 매 careful play의 매 reward 없음. - **Single ending despite choice**: 매 20 ending이 매 illusion이고 매 1개 진짜. - **NPC amnesia**: 매 returning NPC가 매 player choice 매 기억 안 함. ## 🧪 검증 / 중복 - Verified — Lucas Pope GDC 2014 "Papers Please Postmortem", Tom Bissell New Yorker review (2013), 매 various Game Design textbooks. - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — mechanic-theme alignment, document validation / branching ending / NPC memory patterns |