File size: 90,534 Bytes
fd8f1df
ba63f2d
 
5cdb81a
ba25b53
ba63f2d
fd8f1df
 
 
 
f3edf46
ba25b53
 
f3edf46
3d57d8f
 
 
 
 
 
 
 
ba25b53
 
 
3d57d8f
 
 
 
 
 
 
ba25b53
 
3d57d8f
 
 
 
 
 
 
ba25b53
 
 
 
3d57d8f
 
 
ba25b53
fd8f1df
ba25b53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd8f1df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba25b53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd8f1df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba25b53
 
fd8f1df
ba25b53
3d57d8f
ba25b53
 
fd8f1df
 
 
 
 
 
ba25b53
fd8f1df
3d57d8f
f3edf46
3d57d8f
 
 
ba25b53
 
3d57d8f
ba25b53
2e88a0b
 
f3edf46
 
3d57d8f
ba25b53
 
 
2e88a0b
3d57d8f
baca1c4
 
f3edf46
3d57d8f
 
2e88a0b
3d57d8f
 
f3edf46
 
2e88a0b
fd8f1df
3d57d8f
 
ba25b53
2e88a0b
ba25b53
f3edf46
2e88a0b
fd8f1df
3d57d8f
ba25b53
3d57d8f
ba25b53
f3edf46
 
ba25b53
2e88a0b
 
 
 
 
3d57d8f
baca1c4
ed648bd
 
3d57d8f
 
 
 
 
 
 
 
ba25b53
3d57d8f
 
 
ba25b53
3d57d8f
ba25b53
3d57d8f
 
 
 
 
 
ba25b53
fd8f1df
 
ba25b53
fd8f1df
ba25b53
fd8f1df
ba25b53
3d57d8f
 
 
 
 
 
ba25b53
3d57d8f
 
fd8f1df
ba25b53
 
 
fd8f1df
3d57d8f
ba25b53
3d57d8f
 
 
ba25b53
fd8f1df
3d57d8f
 
 
 
 
ba25b53
 
 
3d57d8f
ba25b53
 
3d57d8f
 
fd8f1df
3d57d8f
ba25b53
2e88a0b
 
ba25b53
 
 
2e88a0b
 
ba25b53
 
3d57d8f
ba25b53
 
 
2e88a0b
 
 
ba25b53
 
 
 
2e88a0b
ba25b53
 
2e88a0b
fd8f1df
ba25b53
fd8f1df
ba25b53
2e88a0b
fd8f1df
 
2e88a0b
fd8f1df
ba25b53
 
2e88a0b
 
ba25b53
 
fd8f1df
2e88a0b
fd8f1df
ba25b53
 
2e88a0b
ba25b53
3d57d8f
 
ba25b53
 
3d57d8f
ba25b53
3d57d8f
ba25b53
 
3d57d8f
 
ba25b53
 
3d57d8f
ba25b53
3d57d8f
ba25b53
3d57d8f
ba25b53
 
 
2e88a0b
ba25b53
 
2e88a0b
 
ba25b53
 
2e88a0b
ba25b53
 
fd8f1df
 
ba25b53
 
 
fd8f1df
ba25b53
fd8f1df
ba25b53
fd8f1df
ba25b53
 
 
f3edf46
 
ba25b53
2e88a0b
ba25b53
3d57d8f
 
 
 
fd8f1df
3d57d8f
ba25b53
fd8f1df
ba25b53
fd8f1df
2e88a0b
 
 
3d57d8f
ba25b53
fd8f1df
3d57d8f
2e88a0b
3d57d8f
fd8f1df
 
 
 
3d57d8f
fd8f1df
 
 
3d57d8f
fd8f1df
 
 
3d57d8f
fd8f1df
 
 
3d57d8f
 
ba25b53
fd8f1df
f3edf46
fd8f1df
ba25b53
f3edf46
2e88a0b
f3edf46
ba25b53
3d57d8f
ba25b53
3d57d8f
 
 
fd8f1df
3d57d8f
f3edf46
 
fd8f1df
5cdb81a
 
f3edf46
ba25b53
 
2e88a0b
f3edf46
 
fd8f1df
f3edf46
 
fd8f1df
f3edf46
 
 
fd8f1df
f3edf46
fd8f1df
f3edf46
ba25b53
 
 
 
2e88a0b
 
3d57d8f
 
ba25b53
2e88a0b
 
3d57d8f
 
ba25b53
2e88a0b
 
3d57d8f
 
ba25b53
 
 
fd8f1df
 
 
 
ba25b53
2e88a0b
 
3d57d8f
 
 
2e88a0b
3d57d8f
2e88a0b
 
fd8f1df
 
 
 
 
 
 
 
 
2e88a0b
 
 
3d57d8f
 
 
 
 
 
fd8f1df
 
 
 
 
 
 
 
 
 
 
2e88a0b
ba25b53
fd8f1df
2e88a0b
 
f3edf46
2e88a0b
f3edf46
fd8f1df
 
 
f3edf46
2e88a0b
f3edf46
 
ba25b53
3d57d8f
ba25b53
3d57d8f
ba25b53
fd8f1df
f3edf46
 
 
 
2e88a0b
f3edf46
fd8f1df
f3edf46
ba25b53
2e88a0b
 
 
 
 
fd8f1df
ba25b53
2e88a0b
 
 
 
f3edf46
fd8f1df
3d57d8f
ba25b53
3d57d8f
 
 
 
 
 
ba25b53
3d57d8f
fd8f1df
f3edf46
 
 
fd8f1df
2e88a0b
ba25b53
 
 
 
fd8f1df
 
 
3d57d8f
ba25b53
3d57d8f
2e88a0b
3d57d8f
2e88a0b
fd8f1df
f3edf46
 
fd8f1df
2e88a0b
3d57d8f
 
 
 
fd8f1df
 
 
3d57d8f
 
 
 
 
fd8f1df
3d57d8f
ba25b53
3d57d8f
 
 
 
 
fd8f1df
3d57d8f
 
 
 
fd8f1df
3d57d8f
ba25b53
2e88a0b
3d57d8f
 
fd8f1df
3d57d8f
fd8f1df
3d57d8f
 
fd8f1df
3d57d8f
fd8f1df
ba25b53
3d57d8f
 
 
fd8f1df
3d57d8f
 
fd8f1df
 
 
3d57d8f
 
 
 
fd8f1df
2e88a0b
fd8f1df
3d57d8f
fd8f1df
3d57d8f
 
 
 
fd8f1df
 
2e88a0b
ba25b53
2e88a0b
fd8f1df
ba25b53
3d57d8f
ba25b53
3d57d8f
 
 
 
fd8f1df
3d57d8f
f3edf46
 
 
 
fd8f1df
5cdb81a
 
ba25b53
3d57d8f
ba25b53
fd8f1df
f3edf46
fd8f1df
 
 
 
3d57d8f
fd8f1df
 
3d57d8f
fd8f1df
3d57d8f
 
2e88a0b
3d57d8f
2e88a0b
 
fd8f1df
2e88a0b
f3edf46
3d57d8f
ba25b53
fd8f1df
f3edf46
 
 
fd8f1df
 
3d57d8f
 
fd8f1df
 
 
 
 
 
 
 
 
 
 
 
3d57d8f
 
ba25b53
fd8f1df
2e88a0b
fd8f1df
3d57d8f
fd8f1df
3d57d8f
2e88a0b
 
 
 
fd8f1df
2e88a0b
f3edf46
3d57d8f
ba25b53
fd8f1df
ba25b53
 
 
fd8f1df
ba25b53
fd8f1df
ba25b53
 
 
ba63f2d
 
 
5cdb81a
ba63f2d
fd8f1df
3d57d8f
 
fd8f1df
 
 
 
 
3d57d8f
fd8f1df
 
 
3d57d8f
 
fd8f1df
 
f3edf46
ba25b53
f3edf46
fd8f1df
 
 
 
 
 
ba25b53
2e88a0b
 
 
f3edf46
fd8f1df
 
 
 
 
2e88a0b
fd8f1df
 
 
3d57d8f
fd8f1df
 
3d57d8f
 
 
 
fd8f1df
3d57d8f
fd8f1df
 
 
 
3d57d8f
ba25b53
 
f3edf46
2e88a0b
f3edf46
ba25b53
 
f3edf46
2e88a0b
fd8f1df
 
3d57d8f
2e88a0b
fd8f1df
3d57d8f
2e88a0b
ba25b53
2e88a0b
f3edf46
fd8f1df
2e88a0b
fd8f1df
 
3d57d8f
ba25b53
fd8f1df
2e88a0b
 
3d57d8f
ba25b53
2e88a0b
ba63f2d
fd8f1df
5cdb81a
fd8f1df
2e88a0b
fd8f1df
 
 
5cdb81a
fd8f1df
 
 
ba63f2d
fd8f1df
 
 
 
2e88a0b
 
fd8f1df
 
 
 
2e88a0b
fd8f1df
 
3d57d8f
2e88a0b
 
fd8f1df
 
2e88a0b
fd8f1df
 
 
2e88a0b
3d57d8f
ba25b53
5cdb81a
3d57d8f
2e88a0b
fd8f1df
 
 
 
 
ba25b53
fd8f1df
ba25b53
 
 
 
 
2e88a0b
ba25b53
 
fd8f1df
 
 
 
ba25b53
fd8f1df
ba25b53
 
 
2e88a0b
ba25b53
 
fd8f1df
 
 
 
 
2e88a0b
 
fd8f1df
 
 
2e88a0b
 
ba25b53
3d57d8f
 
 
fd8f1df
 
 
ba25b53
2e88a0b
fd8f1df
2e88a0b
 
 
fd8f1df
2e88a0b
fd8f1df
baca1c4
fd8f1df
 
 
baca1c4
2e88a0b
 
ba25b53
2e88a0b
ba63f2d
2e88a0b
fd8f1df
 
 
ba63f2d
6d0e312
fd8f1df
ba25b53
2e88a0b
3d57d8f
 
fd8f1df
3d57d8f
ba25b53
3d57d8f
 
 
ba63f2d
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
# -*- coding: utf-8 -*-
import streamlit as st
import random
import time
import math

# --- 페이지 설정 (스크립트 최상단) ---
# 이 부분이 가장 먼저 실행되어야 합니다!
st.set_page_config(layout="wide")

# --- 게임 설정 ---
MAX_YEARS = 5
QUARTERLY_ACTIONS_LIMIT = 1

# --- 난이도 설정 ---
DIFFICULTY_LEVELS = {
    "쉬움": {
        "initial_capital": 20,
        "yearly_gain": 10,
        "initial_approval_range": (50, 70),
        "initial_congress_relations_range": (55, 75),
        "initial_stability": 100,
        "event_impact_modifier": 0.8,
        "checks_balances_leniency": 0.15,
        "vocab_level": "쉬움" # 어휘 수준 키
    },
    "보통": {
        "initial_capital": 15,
        "yearly_gain": 8,
        "initial_approval_range": (40, 60),
        "initial_congress_relations_range": (40, 60),
        "initial_stability": 100,
        "event_impact_modifier": 1.0,
        "checks_balances_leniency": 0.0,
        "vocab_level": "보통"
    },
    "어려움": {
        "initial_capital": 10,
        "yearly_gain": 6,
        "initial_approval_range": (30, 50),
        "initial_congress_relations_range": (25, 45),
        "initial_stability": 90,
        "event_impact_modifier": 1.2,
        "checks_balances_leniency": -0.15,
        "vocab_level": "어려움"
    }
}

# --- 난이도별 텍스트 저장소 ---
# (이하 ALL_TEXTS 사전 정의는 이전 답변과 동일하게 유지됩니다)
ALL_TEXTS = {
    # 대시보드 용어
    "term_approval": {
        "쉬움": "국민들이 얼마나 좋아하나 (인기 점수)",
        "보통": "국정 지지도",
        "어려움": "국정 운영에 대한 국민적 지지율"
    },
    "term_political_capital": {
        "쉬움": "대통령 힘 점수 (정치력)",
        "보통": "대통령 정치력",
        "어려움": "대통령의 정책 추진 동력 (정치적 자본)"
    },
    "term_stability": {
        "쉬움": "나라가 얼마나 안정적인가",
        "보통": "국가 안정도",
        "어려움": "국가 시스템 안정성 지수"
    },
    "term_congress_relations": {
        "쉬움": "국회랑 얼마나 친한가",
        "보통": "국회 관계 점수",
        "어려움": "대정부 입법부 협력/견제 지수"
    },
    "term_policy_goals": {
        "쉬움": "대통령 약속 진행 상황",
        "보통": "주요 공약 달성률",
        "어려움": "핵심 국정 과제 이행률"
    },
    # 기관 이름
    "term_congress_name": {
        "쉬움": "국회 (법 만드는 곳)",
        "보통": "국회 (입법부)",
        "어려움": "입법부 (국회)"
    },
    "term_judiciary_name": {
        "쉬움": "법원 (법 지키는지 보는 곳)",
        "보통": "법원/헌법재판소 (사법부)",
        "어려움": "사법부 (법원 및 헌법재판소)"
    },
    # UI 제목/라벨
    "dashboard_title": {
        "쉬움": "📊 나라 상황판",
        "보통": "📊 국정 현황판",
        "어려움": "📊 국정 운영 대시보드"
    },
    "dashboard_term": {
        "쉬움": "대통령 {year}년차, {quarter}번째 계절",
        "보통": "임기 {year}년차 {quarter}분기",
        "어려움": "대통령 임기 {year}년차 제 {quarter}사분기"
    },
    "institutions_title": {
        "쉬움": "다른 중요 기관들 소식",
        "보통": "기관 동향",
        "어려움": "타 국가기관 현황 브리핑"
    },
    "cabinet_title": {
        "쉬움": "장관님들 소식",
        "보통": "내각 현황",
        "어려움": "행정 각 부처 장관 동향"
    },
    "agenda_title": {
        "쉬움": "📰 이번 계절 보고서",
        "보통": "📰 분기별 보고",
        "어려움": "📰 분기별 국정 현안 보고"
    },
    "agenda_event_title": {
        "쉬움": "이번 계절의 일: {title}",
        "보통": "현안/기회: {title}",
        "어려움": "분기 현안 브리핑: {title}"
    },
    "briefing_title": {
        "쉬움": "📝 비서실 도움말",
        "보통": "📝 보좌진 브리핑 및 대응 방안",
        "어려움": "📝 참모진 현안 분석 및 권고안"
    },
    "office_title": {
        "쉬움": "🏛️ 대통령 방",
        "보통": "🏛️ 대통령 집무실",
        "어려움": "🏛️ 대통령 집무실" # 동일하게 사용
    },
    "office_available_capital": {
        "쉬움": "쓸 수 있는 힘 점수: **{capital} P**",
        "보통": "가용 정치력: **{capital} P**",
        "어려움": "가용 정치적 자본: **{capital} P**"
    },
    "office_action_limit": {
        "쉬움": "이번 계절에 할 수 있는 큰 결정: {remaining}번 남음",
        "보통": "이번 분기 행동 가능 횟수: {remaining}회",
        "어려움": "현 분기 주요 의사결정 잔여 횟수: {remaining}회"
    },
    "office_issue_actions": {
        "쉬움": "지금 생긴 일 해결하기",
        "보통": "현안 관련 조치",
        "어려움": "당면 현안 대응 옵션"
    },
    "office_standard_actions": {
        "쉬움": "평소에 할 수 있는 일들",
        "보통": "상시 국정 활동",
        "어려움": "상시 국정 운영 활동"
    },
    "term_event_log": {
        "쉬움": "그동안 있었던 일들 기록",
        "보통": "국정 운영 로그",
        "어려움": "국정 운영 타임라인 기록"
    },
    "button_next_quarter": {
        "쉬움": "➡️ 다음 계절로!",
        "보통": "➡️ 다음 분기 진행",
        "어려움": "➡️ 차기 분기 개시"
    },
     "button_restart": {
        "쉬움": "다시 해볼래!",
        "보통": "다시 시작하기",
        "어려움": "게임 재시작"
    },
    # 이벤트 제목 예시
    "event_title_minor_disaster": { "쉬움": "작은 재난 발생", "보통": "소규모 재난 발생", "어려움": "국지적 자연재해 발생"},
    "event_desc_minor_disaster": { "쉬움": "비가 많이 오거나 불이 나서 동네 몇 군데가 피해를 입었어요. 빨리 도와줘야 해요.", "보통": "집중 호우 또는 산불 등으로 특정 지역에 피해가 발생했습니다. 신속한 지원이 필요합니다.", "어려움": "국지성 호우 또는 산불로 인해 일부 지역에서 물적 피해가 보고되었습니다. 긴급 구호 및 복구 계획 수립이 요구됩니다."},
    "action_visit_disaster_area": { "쉬움": "피해 지역 가서 위로하기", "보통": "피해 지역 현장 방문 및 지원 약속", "어려움": "피해 지역 순방 및 정부 차원 지원 공표"},

    "event_title_small_protest": { "쉬움": "사람들이 모여서 외치고 있어요", "보통": "소규모 시위 발생", "어려움": "제한적 규모의 집회 발생"},
    "event_desc_small_protest": { "쉬움": "어떤 문제 때문에 몇몇 사람들이 모여 목소리를 내고 있어요. 시끄럽지만 큰 문제는 아니에요.", "보통": "특정 현안에 대한 불만으로 일부 시민들이 소규모 집회를 열고 있습니다. 상황 관리가 필요합니다.", "어려움": "특정 정책 또는 사회 현안에 대한 이견 표출로 소규모 집회가 개최되었습니다. 확산 가능성 주시 요망."},
    "action_meet_protesters": { "쉬움": "시위대 이야기 들어보기", "보통": "시위대 대표 면담 추진", "어려움": "집회 주동자 대화 채널 구축 시도"},

    "event_title_price_rise": {"쉬움": "물건값이 조금 올랐어요", "보통": "물가 소폭 상승", "어려움": "소비자 물가 지수 소폭 상승"},
    "event_desc_price_rise": {"쉬움": "가게 물건값이 조금 올라서 사람들이 걱정해요. 안심시켜야 해요.", "보통": "일부 품목의 가격 상승으로 소비자 물가가 소폭 상승했습니다. 시장 불안 심리 차단이 필요합니다.", "어려움": "주요 소비재 가격 인상으로 인해 단기 인플레이션 압력이 감지됩니다. 선제적 시장 안정화 조치가 요구됩니다."},
    "action_address_prices": {"쉬움": "물가 괜찮다고 말하기", "보통": "물가 안정 노력 관련 대국민 메시지 발표", "어려움": "물가 안정 기조 유지 관련 정부 입장 표명"},

    "event_title_summit_offer": {"쉬움": "다른 나라 대통령 만나자고 해요", "보통": "정상회담 개최 제안", "어려움": "양자 정상회담 개최 제의 접수"},
    "event_desc_summit_offer": {"쉬움": "이웃 나라 대통령이 만나자고 연락 왔어요. 친하게 지내면 좋아요.", "보통": "주요 동맹국/주변국 정상으로부터 양자 회담 개최 제안이 왔습니다. 외교적 성과 기회입니다.", "어려움": "주요 외교 파트너 국가 수반의 공식적인 양자 정상회담 제의가 접수되었습니다. 의제 조율 및 전략 수립이 필요합니다."},
    "action_accept_summit": {"쉬움": "만나서 좋은 얘기하기", "보통": "정상회담 적극 수락 및 의제 준비 지시", "어려움": "정상회담 제의 수락 및 실무 준비 TF 구성 지시"},

    "event_title_host_event": {"쉬움": "큰 국제 행사 우리나라에서 열까?", "보통": "대규모 국제 행사 유치 가능성", "어려움": "메가 이벤트 국내 유치 타당성 검토"},
    "event_desc_host_event": {"쉬움": "올림픽 같은 큰 행사를 우리나라에서 열 수 있을지 알아보고 있대요. 좋겠죠?", "보통": "대규모 국제 스포츠/문화 행사 유치 경쟁에서 유리한 고지를 점했다는 보고입니다. 국가 이미지 제고 효과가 기대됩니다.", "어려움": "주요 국제 스포츠/문화 행사의 차기 개최지 선정과 관련하여 유력 후보로 부상했다는 분석입니다. 국가 브랜드 가치 제고 및 경제적 파급 효과가 예상됩니다."} ,
    "action_support_hosting": {"쉬움": "행사 유치 돕기", "보통": "국제 행사 유치위원회에 예산/행정 지원 강화", "어려움": "범정부 차원의 국제 행사 유치 지원 체계 구축"},

    "event_title_tech_investment": {"쉬움": "새로운 기술에 투자할까?", "보통": "신기술 분야 투자 적기 보고", "어려움": "미래 전략기술 분야 투자 최적 시점 분석"},
    "event_desc_tech_investment": {"쉬움": "미래에 중요해질 새 기술에 투자하면 좋겠다는 보고예요. 돈 벌 수 있을까요?", "보통": "미래 산업 관련 핵심 신기술 분야에 대한 국내외 투자 환경이 유리하다는 분석입니다. 정부 지원 시 관련 공약 달성에 도움이 될 수 있습니다.", "어려움": "차세대 핵심 기술 분야의 R&D 및 상용화 투자 환경이 우호적으로 조성되었다는 분석 보고입니다. 국가 경쟁력 강화 및 관련 국정 과제 이행의 기회입니다."},
    "action_review_tech_funding": {"쉬움": "새 기술 연구비 지원 알아보기", "보통": "신기술 분야 R&D 예산 증액 국회 요청 준비", "어려움": "전략기술 R&D 예산 확대 편성 및 입법부 설득 전략 수립"},

    "event_title_opposition_criticism": {"쉬움": "야당이 {minister} 장관 싫어해요", "보통": "야당, {minister} 장관 책임론 제기", "어려움": "야당의 {minister} 장관에 대한 문책 요구"},
    "event_desc_opposition_criticism": {"쉬움": "국회 반대편 의원들이 {minister} 장관이 일 못한다고 계속 비판해요.", "보통": "야당에서 {minister} 장관의 정책 실패 또는 부적절한 처신을 이유로 책임론을 강하게 제기하고 있습니다.", "어려움": "주요 야당은 {minister} 장관의 직무 수행 능력 및 정책적 판단에 심각한 문제가 있다며 사퇴 또는 해임 건의를 검토 중입니다."},
    "action_defend_minister": {"쉬움": "{minister} 장관 편들어주기", "보통": "{minister} 장관 엄호 및 야당 설득 시도", "어려움": "{minister} 장관에 대한 신임 재확인 및 야당 공세 대응"},

    "event_title_party_dissent": {"쉬움": "우리 편에서도 다른 소리가 나와요", "보통": "여당 내 특정 현안 관련 이견 노출", "어려움": "집권여당 내 정책 노선 관련 이견 표출"},
    "event_desc_party_dissent": {"쉬움": "대통령이랑 같은 편 의원들 중에서도 정부가 하는 일에 대해 다른 생각을 말하기 시작했어요.", "보통": "정부 주요 정책 방향에 대해 여당 내 일부 의원들이 공개적으로 다른 목소리를 내기 시작했습니다. 내부 조율이 필요해 보입니다.", "어려움": "주요 국정 현안에 대한 당정 간 이견이 일부 언론을 통해 노출되었습니다. 당내 결속력 약화 및 정책 추진 동력 저하가 우려됩니다."},
    "action_meet_party_members": {"쉬움": "우리 편 의원들 만나서 얘기하기", "보통": "여당 지도부/중진 의원들과 비공개 회동", "어려움": "여당 의원들과의 정책 간담회를 통한 내부 이견 조율"},

    "event_title_media_criticism": {"쉬움": "신문/뉴스에서 정부 욕해요", "보통": "언론의 특정 정책 비판 보도", "어려움": "주요 언론의 정부 정책 비판 기조 강화"},
    "event_desc_media_criticism": {"쉬움": "신문이나 뉴스에서 정부가 하는 일 하나를 콕 집어서 나쁘다고 말해요. 사람들이 믿으면 어쩌죠?", "보통": "주요 언론에서 정부의 특정 정책에 대한 문제점을 지적하거나 부정적인 여론을 부각하는 보도가 이어지고 있습니다.", "어려움": "복수의 주요 언론 매체에서 특정 정부 정책의 문제점 및 부작용을 집중적으로 보도하며 비판적 여론 형성을 주도하고 있습니다."},
    "action_media_interview": {"쉬움": "기자들 만나서 설명하기", "보통": "언론 인터뷰를 통해 정책 설명 및 오해 해소", "어려움": "대통령 또는 주무 장관의 언론 브리핑을 통한 정책 정당성 설파"},

    "event_title_congress_data_request": {"쉬움": "국회에서 자료 달래요", "보통": "국회, 정부 정책 자료 요구", "어려움": "국회의 행정부에 대한 자료 제출 요구"},
    "event_desc_congress_data_request": {"쉬움": "국회의원들이 정부가 하는 일에 대해 자세히 알려달라고 자료를 내래요. 귀찮네요.", "보통": "국회 상임위원회에서 정부가 추진 중인 정책과 관련된 상세 자료 제출을 공식적으로 요구했습니다.", "어려움": "국회 소관 상임위원회에서 특정 정책의 추진 경과 및 예산 집행 내역 등 민감한 자료의 제출을 요구하여 행정부 부담이 가중되고 있습니다."},
    "action_submit_data": {"쉬움": "자료 잘 만들어서 주기", "보통": "성실히 자료 제출 준비 지시", "어려움": "국회 요구 자료의 신속하고 정확한 제출 지시"},
    "action_minimize_data": {"쉬움": "자료 조금만 주기 (혼날지도?)", "보통": "자료 제출 범위 최소화 검토 (관계 악화 위험)", "어려움": "제출 자료 범위에 대한 법적 검토 및 최소 수준 제출 추진"},

    "event_title_congress_hearing_review": {"쉬움": "국회가 청문회 할지 고민 중이래요", "보통": "국회, 특정 사안 청문회 개최 검토", "어려움": "국회의 특정 현안 관련 청문회 개최 검토"},
    "event_desc_congress_hearing_review": {"쉬움": "국회에서 시끄러운 문제에 대해 담당자 불러서 물어보는 청문회를 열지 말지 생각 중이래요. 열리면 골치 아파요.", "보통": "국회에서 논란이 되는 특정 사안에 대해 관계 부처 장관 등을 출석시켜 질의하는 청문회 개최 여부를 검토 중입니다. 개최 시 정부에 부담이 될 수 있습니다.", "어려움": "특정 국정 현안의 진상 규명 또는 책임 소재 파악을 위해 국회 차원의 청문회 개최 필요성이 제기되어 관련 상임위에서 논의가 진행 중입니다."},
    "action_prevent_hearing": {"쉬움": "청문회 못 열게 막아보기", "보통": "여당 통해 청문회 개최 저지 또는 연기 시도", "어려움": "여당과 협력하여 청문회 개최의 부당성 설파 및 무산 유도"},
    "action_prepare_hearing": {"쉬움": "청문회 잘 대답하게 준비하기", "보통": "청문회 대비 관계부처 합동 준비 지시", "어려움": "예상 쟁점 분석 및 대응 논리 개발 등 청문회 철저 대비 지시"},

    "event_title_judiciary_lawsuit": {"쉬움": "누가 정부를 법원에 고소했어요", "보통": "법원, 정부 정책 관련 소송 접수", "어려움": "정부 정책 관련 행정소송 제기"},
    "event_desc_judiciary_lawsuit": {"쉬움": "정부가 한 일이 잘못됐다면서 누가 법원에 고소했어요. 재판에서 지면 큰일나요.", "보통": "정부가 시행한 특정 정책의 위법 또는 부당성을 주장하며 시민 또는 단체가 행정소송을 제기했습니다. 판결 결과에 따라 정책 추진에 차질이 발생할 수 있습니다.", "어려움": "정부의 특정 행정 처분 또는 부작위에 대해 그 효력을 다투는 행정소송이 관할 법원에 접수되었습니다. 사법부의 판단에 따라 해당 정책의 지속 가능성이 결정될 수 있습니다."},
    "action_prepare_legal_defense": {"쉬움": "변호사 시켜서 잘 싸우라고 하기", "보통": "법무부에 법적 대응 논리 개발 및 준비 지시", "어려움": "법무부 주관 하에 정부 소송대리인단 구성 및 적극적 변론 준비 지시"},
    "action_persuade_public": {"쉬움": "국민들에게 우리 편 들어달라고 설득하기", "보통": "정책의 정당성 관련 대국민 홍보 강화", "어려움": "해당 정책의 공익성 및 불가피성에 대한 적극적 여론 형성 노력"},

    "event_title_routine_report": { "쉬움": "이번 계절은 조용했어요", "보통": "일상 국정 보고", "어려움": "정기 국정 운영 현황 보고"},
    "event_desc_routine_report": { "쉬움": "이번 계절은 별일 없었어요. 하던 일 계속하면 돼요.", "보통": "이번 분기는 특별한 현안 없이 국정이 비교적 안정적으로 운영되고 있다는 보고입니다. 기존 정책 추진에 집중할 시기입니다.", "어려움": "현 분기 특이사항 없이 안정적인 국정 운영 기조가 유지되고 있다는 정례 보고입니다. 기존 정책과제의 지속적인 추진이 권고됩니다."},
    "action_check_goal_progress": { "쉬움": "약속 얼마나 지켰나 보기", "보통": "주요 공약 진행 상황 점검", "어려움": "핵심 국정 과제 이행 현황 중간 점검"},
    "action_strengthen_pr": { "쉬움": "정부가 잘하고 있다고 자랑하기", "보통": "정책 홍보 활동 강화 지시", "어려움": "국정 운영 성과 홍보 전략 강화 지시"},

    # 행동 관련 메시지
    "action_button_label": { # 버튼 레이블은 통일성 위해 보통 수준 유지
        "쉬움": "{action} ({cost} 힘 점수)",
        "보통": "{action} ({cost}P)",
        "어려움": "{action} (정치자본 {cost} 소모)"
    },
    "action_cost_warning": {
        "쉬움": "힘 점수가 모자라요!",
        "보통": "정치력이 부족합니다!",
        "어려움": "정치적 자본이 부족합니다!"
    },
    "action_success_message": {
        "쉬움": "'{action}' 하라고 시켰어요.",
        "보통": "'{action}' 지시 완료.",
        "어려움": "'{action}' 관련 대통령령 발령 완료." # 예시
    },
    "action_impact_approval": {
        "쉬움": "국민 인기도 {change:+}%p 바뀔 듯",
        "보통": "국정 지지도 {change:+}%p 변동 예상",
        "어려움": "국민 지지율 {change:+}%p 변동 예측"
    },
    "action_impact_stability":{
        "쉬움": "나라 안정 점수 {change:+}%p 바뀔 듯",
        "보통": "국가 안정도 {change:+}%p 변동 예상",
        "어려움": "국가 안정성 지수 {change:+}%p 변동 예측"
    },
    "action_impact_congress":{
        "쉬움": "국회랑 관계 점수 {change:+}%p 바뀔 듯",
        "보통": "국회 관계 점수 {change:+}%p 변동 예상",
        "어려움": "대 국회 관계 지수 {change:+}%p 변동 예측"
    },
    "action_impact_goal":{
        "쉬움": "약속 '{goal}' {prog:+}%p 만큼 진행될 듯",
        "보통": "공약 '{goal}' {prog:+}%p 달성 예상",
        "어려움": "국정 과제 '{goal}' {prog:+}%p 진척 예상"
    },
    # 연말 결산
     "checks_balances_title": {
        "쉬움": "{year}년차, 한 해 돌아보기",
        "보통": "{year}년차 연말 국정 결산 (견제와 균형)",
        "어려움": "{year}년차 연말 국정 평가 (기관 간 상호작용 분석)"
    },
    "checks_balances_bill_submitted": {
        "쉬움": "[국회] '{bill_name}' 법안 내봤어요.",
        "보통": "[국회] '{bill_name}' 법안 제출됨.",
        "어려움": "[입법부] '{bill_name}' 의안 상정됨."
    },
    "checks_balances_bill_passed": {
        "쉬움": "[국회] '{bill_name}' 법안 통과! 👍",
        "보통": "[국회] '{bill_name}' 법안 통과! 🎉",
        "어려움": "[입법부] '{bill_name}' 의안 가결됨."
    },
    "checks_balances_bill_failed": {
        "쉬움": "[국회] '{bill_name}' 법안 통과 못했어요 😥",
        "보통": "[국회] '{bill_name}' 법안 부결.",
        "어려움": "[입법부] '{bill_name}' 의안 부결됨."
    },
    "checks_balances_investigation": {
        "쉬움": "[국회] 국회가 정부 하는 일 자세히 살펴보겠대요. 귀찮아질かも...",
        "보통": "[국회] 특정 사안에 대한 국정조사/청문회가 발동되었습니다. 정부 부담 증가.",
        "어려움": "[입법부] 국회의 국정조사권 또는 청문회 발동. 행정부 운영 부담 가중."
    },
    "checks_balances_judiciary_ruling":{
        "쉬움": "[법원] '{case_name}' 사건 판결: {result}",
        "보통": "[사법부] '{case_name}' 사건 판결: {result}",
        "어려움": "[사법부] '{case_name}' 사안에 대한 사법적 판단: {result}"
    },
    "checks_balances_judiciary_uphold":{
        "쉬움": "문제 없대요!",
        "보통": "문제 없음 (합헌/적법)",
        "어려움": "합헌 또는 적법 결정"
    },
    "checks_balances_judiciary_strike_down":{
        "쉬움": "문제 있대요! 계획 바꾸거나 조심해야 함.",
        "보통": "문제 있음! (위헌/위법) 정책 차질 발생.",
        "어려움": "위헌 또는 위법 결정. 관련 정책 추진 제동."
    },
    "checks_balances_summary":{
        "쉬움": "{year}년차 끝! (법안 통과: {passed}개, 실패: {failed}개)",
        "보통": "{year}년차 결산 완료 (법안 통과: {passed}건, 부결: {failed}건)",
        "어려움": "{year}년차 국정 평가 완료 (법안 가결: {passed}건, 부결: {failed}건)"
    },
    # 게임 오버
    "game_over_title": {
        "쉬움": "대통령 임기 끝! (총 {years}년)",
        "보통": "임기 종료 (총 {years}년)",
        "어려움": "대통령 임기 만료 (재임 기간: {years}년)"
    },
    "game_over_subtitle": {
        "쉬움": "내가 대통령으로 한 일 결과",
        "보통": "최종 국정 운영 결과",
        "어려움": "임기 만료 시점 국정 운영 평가"
    },
    # 용어 사전 (쉬움/보통/어려움 순서)
    "glossary_veto": {
        "쉬움": "**법률안 거부권:** 국회가 만든 법이 마음에 안 들 때, 대통령이 '다시 생각해 보세요!'라고 돌려보낼 수 있는 힘. 하지만 국회 의원들이 아주 많이(2/3 이상) 찬성하면 거부 못함.",
        "보통": "**법률안 거부권 (재의 요구권):** 국회가 통과시킨 법률안에 대해 대통령이 이의가 있을 때, 공포하지 않고 국회에 다시 심의해달라고 요구할 수 있는 권한. 국회는 재적의원 과반수 출석과 출석의원 3분의 2 이상의 찬성으로 재의결 가능.",
        "어려움": "**법률안 재의 요구권 (거부권):** 입법부가 의결한 법률안에 대해 행정부 수반인 대통령이 이의를 제기하며 공포를 거부하고 입법부에 재심의를 요구하는 헌법상 권한. 국회 재의결 요건(재적 과반 출석, 출석 2/3 찬성) 충족 시 법률로 확정."
    },
    "glossary_exec_order": {
        "쉬움": "**대통령 명령:** 법을 잘 지키기 위해 대통령이 내리는 자세한 규칙. 법보다 높을 순 없음.",
        "보통": "**행정명령 (대통령령):** 대통령이 법률에서 위임받은 사항이나 법률을 집행하기 위해 필요한 사항에 대해 발하는 명령. 법률의 범위 내에서만 유효.",
        "어려움": "**대통령령 (집행명령/위임명령):** 헌법과 법률에 근거하여 대통령이 발하는 행정입법의 한 형태. 법률 집행을 위한 집행명령과 법률의 위임에 따른 위임명령으로 구분되며, 사법심사의 대상."
    },
    "glossary_budget_proposal": {
        "쉬움": "**예산안 만들기:** 내년에 나라 살림을 어떻게 쓸지 정부(대통령)가 계획 짜서 국회에 내는 것.",
        "보통": "**예산안 편성권:** 정부(대통령)가 다음 해의 국가 살림 계획인 예산안을 짜서 국회에 제출할 수 있는 권한.",
        "어려움": "**정부의 예산안 편성권:** 행정부가 차기 회계연도의 국가 재정 운용 계획인 예산안을 수립하여 입법부에 제출하는 헌법상 권한."
    },
    "glossary_budget_approval": {
        "쉬움": "**예산안 심사/확정:** 국회가 정부가 낸 예산안을 보고 '이렇게 써도 좋다!' 결정하는 것. 돈을 깎거나 (정부 동의 얻어) 늘릴 수 있음.",
        "보통": "**국회 예산 심의/확정권:** 정부가 제출한 예산안을 국회가 심사하고 최종적으로 확정하는 권한. 정부 예산안을 삭감하거나 증액(정부 동의 필요)할 수 있음.",
        "어려움": "**국회의 예산안 심의·확정권:** 정부가 제출한 예산안에 대해 국회가 심의를 거쳐 수정 또는 확정하는 권한. 재정 민주주의의 핵심 요소로, 감액은 자유로우나 증액 및 새 비목 설치는 정부 동의 필요."
    },
    "glossary_judicial_review_law": {
        "쉬움": "**법률 심사권 (헌법재판소):** 국회가 만든 법이 가장 큰 법인 '헌법'에 어긋나는지 아닌지 헌법재판소가 판단하는 힘.",
        "보통": "**위헌법률심판권:** 국회가 만든 법률이 헌법에 위배되는지 여부를 헌법재판소가 심판하는 권한.",
        "어려움": "**위헌법률심판 제청권/심판권:** 법률의 위헌 여부가 재판의 전제가 된 경우 법원의 제청 또는 당사자의 신청에 의해 헌법재판소가 해당 법률의 헌법 합치성을 심판하는 권한."
    },
    "glossary_judicial_review_order":{
         "쉬움": "**명령/규칙 심사권 (대법원):** 대통령 명령 같은 규칙이 헌법이나 법률에 맞는지 대법원이 최종 판단하는 힘.",
         "보통": "**명령·규칙·처분 심사권:** 대통령령 등 행정기관이 만든 명령이나 규칙, 또는 행정 처분이 헌법이나 법률에 위반되는지 여부를 대법원이 최종적으로 심사하는 권한.",
         "어려움": "**명령·규칙·처분에 대한 최종 심사권:** 행정입법(명령, 규칙)이나 행정처분의 위헌·위법성이 재판의 전제가 된 경우, 대법원이 이를 최종적으로 심사하여 판단하는 권한."
     },
    "glossary_parliamentary_audit":{
         "쉬움": "**국정감사/조사:** 국회가 정부가 일 잘 하고 있는지, 잘못은 없는지 감시하고 조사하는 활동.",
         "보통": "**국정감사/조사권:** 국회가 정부의 국정 운영 전반이나 특정 사안에 대해 잘못된 점이 없는지 감사하거나 조사할 수 있는 권한. 행정부를 견제하는 주요 수단.",
         "어려움": "**국정감사 및 조사권:** 국회가 정부의 국정 수행 실태를 파악하고 감독하기 위해 매년 정기적으로(감사) 또는 특정 현안에 대해(조사) 행사하는 헌법상 권한."
     },
    "glossary_impeachment":{
         "쉬움": "**탄핵:** 대통령 같은 높은 공무원이 아주 큰 잘못(헌법/법률 위반)을 했을 때, 국회가 그만두게 해달라고 헌법재판소에 요청하는 것.",
         "보통": "**탄핵소추권:** 대통령 등 고위 공직자가 직무상 중대한 헌법이나 법률 위반 시, 국회가 파면을 결정해달라고 헌법재판소에 청구할 수 있는 권한.",
         "어려움": "**탄핵소추 의결권 및 심판 청구권:** 국회가 헌법 또는 법률을 중대하게 위반한 특정 고위 공직자에 대해 파면을 구하는 소추안을 의결하고 헌법재판소에 심판을 청구하는 권한."
     },
    "glossary_confirmation_hearing":{
         "쉬움": "**인사청문회:** 대통령이 뽑으려는 장관 같은 높은 공무원이 그 일 할 능력 있는지, 문제는 없는지 국회가 미리 살펴보는 자리.",
         "보통": "**인사청문회:** 대통령이 임명하는 고위 공직 후보자에 대해 국회가 직무수행 능력과 도덕성 등을 검증하는 절차. 일부 직위는 국회 동의가 필수적.",
         "어려움": "**인사청문회 실시권:** 대통령이 임명하는 주요 공직 후보자의 자질, 능력, 도덕성 등을 국회 상임위원회 또는 특별위원회 차원에서 검증하는 제도. 임명동의안 처리 또는 임명 전 검증 절차로 기능."
     },
    "glossary_political_capital":{
         "쉬움": "**정치력 (게임 점수):** 대통령이 자기 뜻대로 일을 할 때 쓰는 힘 점수. 중요한 결정 할 때 필요.",
         "보통": "**정치력 (Political Capital):** 대통령이 자신의 정책을 추진하거나 영향력을 행사하는 데 사용할 수 있는 비공식적인 자원. 지지도, 협상력, 리더십 등을 포함하는 개념으로 게임 내 행동력으로 사용됨.",
         "어려움": "**정치적 자본 (Political Capital):** 대통령이 국정 운영 목표 달성을 위해 동원할 수 있는 무형의 자산. 국민적 지지, 의회 내 영향력, 정책 정당성, 리더십 등을 포괄하며, 정치적 행위의 비용으로 소모됨."
     },
    # 상시 행동 키
    "action_replace_minister": {"쉬움": "{minister} 장관 바꾸기", "보통": "{minister} 장관 교체", "어려움": "{minister} 장관 경질"},
    "action_prepare_bill": {"쉬움": "새로운 법 만들기 준비", "보통": "법률안 국회 제출 준비", "어려움": "입법안 발의 준비 착수"},
    "action_meet_ruling_party": {"쉬움": "우리 편 의원들이랑 밥 먹기", "보통": "여당 지도부와 만찬 회동", "어려움": "집권여당 지도부와 정례 회동"},
    "action_meet_opposition": {"쉬움": "반대편 의원들 만나보기", "보통": "야당 지도부 만나기 (관계 개선 시도)", "어려움": "주요 야당 지도부와 협의 채널 구축"},
    "action_meet_biz_leaders": {"쉬움": "회사 사장님들 만나기", "보통": "주요 경제 단체 간담회", "어려움": "주요 경제계 인사 초청 간담회"},
    "action_respect_judiciary": {"쉬움": "법원 존중한다고 말하기", "보통": "사법부 존중 메시지 발표", "어려움": "사법부 독립성 존중 관련 대국민 메시지 발표"},
    "action_no_special_action": {"쉬움": "이번엔 그냥 넘어가기", "보통": "이번 분기 특별 조치 없음", "어려움": "현 분기 특이 조치 보류"},
    # 상태 메시지 키
    "status_loading_report": {"쉬움": "{year}년 {quarter}번째 계절 보고서 만드는 중...", "보통": "{year}년 {quarter}분기 보고 준비 중...", "어려움": "{year}년 제 {quarter}사분기 국정 현안 브리핑 준비 중..."} ,
    "status_waiting_report": {"쉬움": "다음 계절 보고서 기다리는 중...", "보통": "다음 분기 보고를 기다리고 있습니다.", "어려움": "차기 분기 보고 대기 중..."} ,
    "status_action_limit_reached": {"쉬움": "이번 계절({quarter})에 할 큰 결정 다 했어요. 다음 계절로 넘어가요.", "보통": "이번 분기({quarter}Q) 주요 활동을 완료했습니다. 다음 분기로 넘어가세요.", "어려움": "현 분기({quarter}Q) 주요 의사결정 한도를 소진했습니다. 차기 분기로 진행하십시오."},
    # 사이드바 키
    "sidebar_title": {"쉬움": "메뉴", "보통": "사이드 메뉴", "어려움": "부가 기능 메뉴"},
    "sidebar_glossary_title": {"쉬움": "🏛️ 어려운 말 사전", "보통": "🏛️ 정부 용어 사전", "어려움": "🏛️ 주요 정부 용어 해설"},
    # 기타 UI 텍스트
    "error_invalid_action": {"쉬움": "잘못 골랐어요!", "보통": "잘못된 행동 선택입니다.", "어려움": "유효하지 않은 의사결정입니다."},
    "error_event_generation_failed": {"쉬움": "보고서 만드는데 실패했어요 ㅠㅠ", "보통": "분기 보고 생성에 실패했습니다.", "어려움": "분기 현안 브리핑 생성 중 오류가 발생했습니다."},
    "warning_briefing_loading": {"쉬움": "도움말 가져오는 중...", "보통": "브리핑 정보를 불러오는 중입니다.", "어려움": "참모진 권고안 로딩 중..."},
    "caption_no_goals": {"쉬움": "정한 약속이 없어요.", "보통": "설정된 공약이 없습니다.", "어려움": "설정된 국정 과제가 없습니다."},
    "caption_no_cabinet": {"쉬움": "장관님들 정보가 없어요.", "보통": "내각 정보가 없습니다.", "어려움": "행정 각료 정보가 없습니다."},
    "caption_no_pending_bills": {"쉬움": "국회에서 지금 얘기 중인 법안이 없어요.", "보통": "현재 특별히 논의 중인 법안 없음", "어려움": "현재 계류 중인 주요 의안 없음"},
    "caption_no_pending_cases": {"쉬움": "법원에서 지금 다루는 특별한 사건이 없어요.", "보통": "현재 특별한 사건 없음", "어려움": "현재 계류 중인 주요 사법 사건 없음"},
    "label_pending_bills": {"쉬움": "국회에서 얘기 중인 법안들", "보통": "논의 중인 법안", "어려움": "계류 의안 목록"},
    "label_pending_cases": {"쉬움": "법원에서 다루는 사건들", "보통": "진행 중인 주요 사건", "어려움": "계류 사법 사건 목록"},
    "log_initial_approval": {"쉬움": "처음 인기도", "보통": "초기 국정 지지도", "어려움": "임기 개시 시점 지지율"},
    "log_initial_goals": {"쉬움": "내가 하기로 한 약속들", "보통": "선택된 주요 공약", "어려움": "선정된 핵심 국정 과제"},
    "log_action_result": {"쉬움": "결과:", "보통": "결과:", "어려움": "파급 효과:"},
    "log_minister_change": {"쉬움": "{minister} 장관 바꿈.", "보통": "{minister} 장관 교체.", "어려움": "{minister} 장관 경질."},
    "log_minister_old_approval": {"쉬움": "전 장관 인기도", "보통": "구 장관 지지도", "어려움": "전임 장관 지지율"},
    "log_minister_new_approval": {"쉬움": "새 장관 인기도", "보통": "신 장관 지지도", "어려움": "신임 장관 지지율"},
    "log_bill_prep_start": {"쉬움": "'{bill_name}' 법 만들기 시작.", "보통": "'{bill_name}' 제출 준비 착수.", "어려움": "'{bill_name}' 입법 준비 개시."},
    "log_yearly_capital_gain": {"쉬움": "연말 보너스 힘 점수", "보통": "연말 보너스 정치력", "어려움": "연말 정치적 자본 회복"},
    "log_end_of_term": {"쉬움": "--- 대통령 임기 끝! ---", "보통": "--- 임기 종료 ---", "어려움": "--- 대통령 임기 만료 ---"},
    "log_start_year": {"쉬움": "--- {year}년차 시작! ---", "보통": "--- {year}년차 시작 ---", "어려움": "--- 임기 {year}년차 개시 ---"},
    "log_start_quarter": {"쉬움": "--- {year}년차 {quarter}번째 계절 시작! ---", "보통": "--- {year}년차 {quarter}분기 시작 ---", "어려움": "--- {year}년차 제 {quarter}사분기 개시 ---"},
    "log_error_minister_not_found": {"쉬움": "오류: {minister} 부서 못 찾음.", "보통": "오류: {minister} 부처를 찾을 수 없습니다.", "어려움": "오류: {minister} 부처 정보 부재."},
    "log_bill_pass_chance": {"쉬움": "'{bill_name}' 통과 가능성", "보통": "'{bill_name}' 통과 확률", "어려움": "'{bill_name}' 가결 확률"},
    "log_judiciary_case_received": {"쉬움": "[{judiciary_name}] '{case_name}' 사건 들어옴.", "보통": "[{judiciary_name}] '{case_name}' 사건 접수됨.", "어려움": "[{judiciary_name}] '{case_name}' 사안 계류됨."},
    "log_judiciary_strike_down_chance": {"쉬움": "'{case_name}' 문제 있다고 판결할 가능성", "보통": "'{case_name}' 위헌/위법 판결 확률", "어려움": "'{case_name}' 위헌/위법 결정 확률"},
    "log_natural_fluctuation": {"쉬움": "연말 점수 변화", "보통": "연말 자연 변동", "어려움": "연말 지표 자연 변동성"},
}


# --- 어휘 조정 함수 (난이도별 텍스트 반환) ---
def get_text(key, level="보통"):
    """난이도에 따라 다른 텍스트 반환, 없으면 '보통' -> key 순으로 fallback"""
    level_texts = ALL_TEXTS.get(key)
    if level_texts:
        if level in level_texts:
            return level_texts[level]
        elif "보통" in level_texts:
            # st.warning(f"텍스트 키 '{key}'에 대한 '{level}' 난이도 텍스트 없음. '보통' 사용.") # 디버깅용
            return level_texts["보통"]
    # st.error(f"텍스트 키 '{key}' 찾을 수 없음!") # 디버깅용
    return key # 키 자체를 반환 (최후 fallback)

# --- 정부 및 다른 기관 초기화 함수 ---
def initialize_government(difficulty):
    """대통령 임기 시작 시 상태 및 다른 기관 정보 초기화 (난이도 적용)"""
    settings = DIFFICULTY_LEVELS[difficulty]
    vocab_level = settings["vocab_level"]
    get_text_func = lambda k: get_text(k, vocab_level) # 초기화 시점 어휘 수준 적용

    policy_options = ["경제 성장률 5% 달성", "청년 실업률 5% 이하 달성", "부동산 시장 안정화", "미래 산업 육성", "외교 관계 개선", "국방력 강화", "복지 예산 10% 증액", "탄소 배출 감축"]
    selected_goals = random.sample(policy_options, 3)
    initial_goals = {goal: 0 for goal in selected_goals}

    total_seats = 300
    gov_party_seats_base = random.randint(120, 170)
    if difficulty == "어려움": gov_party_seats = min(gov_party_seats_base, random.randint(100, 155))
    elif difficulty == "쉬움": gov_party_seats = max(gov_party_seats_base, random.randint(145, 180))
    else: gov_party_seats = gov_party_seats_base
    opp_party_seats = total_seats - gov_party_seats - random.randint(5, 15)
    other_seats = total_seats - gov_party_seats - opp_party_seats

    return {
        'presidency_status': {
            'approval_rating': random.randint(*settings['initial_approval_range']),
            'political_capital': settings['initial_capital'],
            'policy_goals': initial_goals,
            'stability': settings['initial_stability'],
            'congress_relations': random.randint(*settings['initial_congress_relations_range'])
        },
        'other_branches': {
            'Congress': {
                'name': get_text_func("term_congress_name"),
                'seats': {'Government': gov_party_seats, 'Opposition': opp_party_seats, 'Others': other_seats},
                'stance': '사안별 협조 및 견제' if difficulty == "보통" else ("대체로 협조적" if difficulty == "쉬움" else "대체로 비판적/견제"),
                'key_focus': random.sample(['민생 안정', '정부 견제', '개혁 입법', '지역 예산 확보'], 2),
                'pending_bills': [],
                'relations_score': random.randint(*settings['initial_congress_relations_range'])
            },
            'Judiciary': {
                'name': get_text_func("term_judiciary_name"),
                'status': '특별한 사건 없음',
                'independence_level': random.randint(70, 95) if difficulty != "어려움" else random.randint(80, 100),
                'pending_cases': [],
                'stance_modifier': 0
            }
        },
        'cabinet': {
            '경제부': {'minister_approval': random.randint(30,70), 'performance': 50},
            '사회부': {'minister_approval': random.randint(30,70), 'performance': 50},
            '외교부': {'minister_approval': random.randint(30,70), 'performance': 50},
            '국방부': {'minister_approval': random.randint(30,70), 'performance': 50},
        },
        'event_log': [f"제 {random.randint(19, 22)}대 대통령 임기 시작 ({difficulty})"]
    }

# --- 세션 상태 초기화 ---
if 'game_started' not in st.session_state:
    st.session_state['game_started'] = False
if 'difficulty' not in st.session_state:
    st.session_state['difficulty'] = "보통" # 기본값

# --- 난이도 선택 화면 ---
if not st.session_state.game_started:
    st.title("👑 대통령의 균형추: 삼권분립 리더십 시뮬레이션")
    st.write("게임을 시작하기 전에 난이도를 선택해주세요. 난이도에 따라 게임 설명과 용어가 달라집니다.")
    selected_difficulty = st.radio(
        "게임 난이도를 선택하세요:",
        list(DIFFICULTY_LEVELS.keys()),
        index=1,
        horizontal=True,
        captions=["쉬운 단어와 설명으로 게임해요.", "표준적인 설명으로 게임해요.", "전문적인 용어와 설명으로 게임해요."]
    )
    if st.button("게임 시작!"):
        st.session_state['difficulty'] = selected_difficulty
        st.session_state['game_year'] = 1
        st.session_state['game_quarter'] = 1
        st.session_state['game_state'] = initialize_government(selected_difficulty)
        # 초기 로그 메시지 추가 (난이도별 텍스트 사용)
        vocab_level_init = DIFFICULTY_LEVELS[selected_difficulty]["vocab_level"] # 여기에서 vocab_level 정의
        get_text_func_init = lambda k: get_text(k, vocab_level_init) # 초기화용 get_text 함수
        initial_approval = st.session_state.game_state['presidency_status']['approval_rating']
        st.session_state.game_state['event_log'].append(f"{get_text_func_init('log_initial_approval')}: {initial_approval}%")
        goals = st.session_state.game_state['presidency_status']['policy_goals'].keys()
        st.session_state.game_state['event_log'].append(f"{get_text_func_init('log_initial_goals')}: {', '.join(goals)}")

        st.session_state['current_quarterly_event'] = None
        st.session_state['event_briefing'] = None
        st.session_state['game_over'] = False
        st.session_state['actions_taken_this_quarter'] = 0
        st.session_state['game_started'] = True
        st.rerun()
    st.stop()

# --- 게임 진행 중 ---
# 현재 게임 난이도 및 어휘 수준 가져오기
difficulty = st.session_state.difficulty
settings = DIFFICULTY_LEVELS[difficulty]
vocab_level = settings["vocab_level"]
get_text_func = lambda key: get_text(key, vocab_level) # 게임 전반에 사용할 get_text 함수

# --- 분기별 현안/기회 생성 함수 ---
def generate_quarterly_event(year, quarter, game_state, difficulty):
    """매 분기 발생하는 현안/기회 생성 (난이도 및 견제 요소 반영)"""
    settings = DIFFICULTY_LEVELS[difficulty]
    vocab_level = settings["vocab_level"]
    get_text_for_event = lambda k: get_text(k, vocab_level) # 이벤트 생성 시 사용할 get_text
    presidency_status = game_state['presidency_status']
    congress = game_state['other_branches']['Congress']
    judiciary = game_state['other_branches']['Judiciary']

    event_types = ["minor_issue", "opportunity", "political_move", "checks_balances_event", "random"]
    weights = [30, 25, 20, 15, 10]
    if difficulty == "어려움": weights = [35, 15, 25, 20, 5]
    elif difficulty == "쉬움": weights = [20, 35, 15, 10, 20]
    if congress['relations_score'] < 40:
        weights[3] += 10
        weights[2] += 5

    chosen_type = random.choices(event_types, weights=weights, k=1)[0]
    event = {"title_key": "", "description_key": "", "type": chosen_type, "options": [], "context": {}} # 키로 저장, context 추가

    # 이벤트 내용 정의 (키 사용)
    if chosen_type == "minor_issue":
        issues = [
            {"title_key": "event_title_minor_disaster", "desc_key": "event_desc_minor_disaster"},
            {"title_key": "event_title_small_protest", "desc_key": "event_desc_small_protest"},
            {"title_key": "event_title_price_rise", "desc_key": "event_desc_price_rise"},
        ]
        selected = random.choice(issues)
        event["title_key"] = selected["title_key"]
        event["description_key"] = selected["desc_key"]
        event["options"] = [
            {"action_key": "action_visit_disaster_area", "cost": math.ceil(2 * (1/settings['event_impact_modifier'])), "impact": {"approval": random.randint(1,3), "stability": random.randint(0,2)}},
            {"action_key": "action_meet_protesters", "cost": math.ceil(1 * (1/settings['event_impact_modifier'])), "impact": {"stability": random.randint(0,1)}},
            {"action_key": "action_address_prices", "cost": math.ceil(1 * (1/settings['event_impact_modifier'])), "impact": {"approval": random.randint(-1,2)}},
        ]
    elif chosen_type == "opportunity":
        opps = [
             {"title_key": "event_title_summit_offer", "desc_key": "event_desc_summit_offer"},
             {"title_key": "event_title_host_event", "desc_key": "event_desc_host_event"},
             {"title_key": "event_title_tech_investment", "desc_key": "event_desc_tech_investment"},
         ]
        selected = random.choice(opps)
        event["title_key"] = selected["title_key"]
        event["description_key"] = selected["desc_key"]
        event["options"] = [
              {"action_key": "action_accept_summit", "cost": math.ceil(2 * (1/settings['event_impact_modifier'])), "impact": {"approval": random.randint(0,2), "policy_goals": {"외교 관계 개선": random.randint(1,3)}}}, # 공약 이름은 일단 하드코딩 유지
              {"action_key": "action_support_hosting", "cost": math.ceil(3 * (1/settings['event_impact_modifier'])), "impact": {"stability": random.randint(1,2), "approval": random.randint(1,3)}},
              {"action_key": "action_review_tech_funding", "cost": math.ceil(2 * (1/settings['event_impact_modifier'])), "impact": {"policy_goals": {"미래 산업 육성": random.randint(2,5)}}},
         ]
    elif chosen_type == "political_move":
        minister_name = random.choice(list(game_state['cabinet'].keys())) if game_state['cabinet'] else "특정"
        event["context"]["minister"] = minister_name # context에 장관 이름 저장
        moves = [
            {"title_key": "event_title_opposition_criticism", "desc_key": "event_desc_opposition_criticism"},
            {"title_key": "event_title_party_dissent", "desc_key": "event_desc_party_dissent"},
            {"title_key": "event_title_media_criticism", "desc_key": "event_desc_media_criticism"},
        ]
        selected = random.choice(moves)
        event["title_key"] = selected["title_key"]
        event["description_key"] = selected["desc_key"]
        # 옵션에도 context 전달 필요 시 추가
        event["options"] = [
             {"action_key": "action_defend_minister", "cost": math.ceil(2 * (1/settings['event_impact_modifier'])), "impact": {"congress_relations": random.randint(-4,1)}, "context": {"minister": minister_name}},
             {"action_key": "action_meet_party_members", "cost": math.ceil(1 * (1/settings['event_impact_modifier'])), "impact": {"political_capital": 1}},
             {"action_key": "action_media_interview", "cost": math.ceil(1 * (1/settings['event_impact_modifier'])), "impact": {"approval": random.randint(-2,2)}},
        ]
    elif chosen_type == "checks_balances_event":
        cb_events = []
        if congress['relations_score'] < 50 or difficulty == "어려움":
             cb_events.append({"title_key": "event_title_congress_data_request", "desc_key": "event_desc_congress_data_request", "options": [{"action_key": "action_submit_data", "cost": 1, "impact": {"congress_relations": random.randint(0,2)}}, {"action_key": "action_minimize_data", "cost": 0, "impact": {"congress_relations": random.randint(-3,0)}}]})
             cb_events.append({"title_key": "event_title_congress_hearing_review", "desc_key": "event_desc_congress_hearing_review", "options": [{"action_key": "action_prevent_hearing", "cost": 2, "impact": {"congress_relations": random.randint(-2,1)}}, {"action_key": "action_prepare_hearing", "cost": 1, "impact": {"stability": random.randint(-2,0)}}]})
        if judiciary['independence_level'] > 80 or random.random() < 0.1:
             cb_events.append({"title_key": "event_title_judiciary_lawsuit", "desc_key": "event_desc_judiciary_lawsuit", "options": [{"action_key": "action_prepare_legal_defense", "cost": 1, "impact": {}}, {"action_key": "action_persuade_public", "cost": 1, "impact": {"approval": random.randint(0,1)}}]})

        if not cb_events:
            chosen_type = "random" # 대체
        else:
            selected = random.choice(cb_events)
            event["title_key"] = selected["title_key"]
            event["description_key"] = selected["desc_key"]
            event["options"] = selected["options"]
            event["type"] = "checks_balances_event" # 타입 명시

    # Random 타입 처리
    if chosen_type == "random":
        event["title_key"] = "event_title_routine_report"
        event["description_key"] = "event_desc_routine_report"
        event["type"] = "random"
        event["options"] = [
            {"action_key": "action_check_goal_progress", "cost": math.ceil(1 * (1/settings['event_impact_modifier'])), "impact": {}},
            {"action_key": "action_strengthen_pr", "cost": math.ceil(1 * (1/settings['event_impact_modifier'])), "impact": {"approval": random.randint(0,1)}},
        ]

    # 공통 옵션 추가 (키 사용)
    event["options"].append({"action_key": "action_no_special_action", "cost": 0, "impact": {}})

    # 최종 이벤트 객체 생성 (텍스트 변환)
    final_event = {
        "title": get_text_for_event(event["title_key"]).format(**event.get("context", {})),
        "description": get_text_for_event(event["description_key"]).format(**event.get("context", {})),
        "type": event["type"],
        "options": []
    }
    for opt in event.get("options", []): # options가 없을 수도 있으므로 get 사용
        final_event["options"].append({
            "action": get_text_for_event(opt["action_key"]).format(**opt.get("context", {})),
            "cost": opt["cost"],
            "impact": opt.get("impact", {}) # impact가 없을 수도 있음
        })

    log_message = f"{year}년차 {quarter}분기 현안: {final_event['title']}"
    if 'event_log' in game_state:
        game_state['event_log'].append(log_message)
    return final_event

# --- 이벤트 브리핑 제공 함수 ---
def provide_event_briefing(event, game_state, difficulty):
    """분기별 현안/기회에 대한 브리핑 생성 (난이도별 어휘 적용)"""
    settings = DIFFICULTY_LEVELS[difficulty]
    vocab_level = settings["vocab_level"]
    get_text_for_briefing = lambda key: get_text(key, vocab_level) # 브리핑용 get_text

    title = event['title'] # 이미 변환된 텍스트 사용
    briefing = f"**{get_text_for_briefing('dashboard_term').format(year=st.session_state['game_year'], quarter=st.session_state['game_quarter'])} 보고: {title}**\n\n"
    briefing += f"{event['description']}\n\n" # 이미 변환된 텍스트 사용
    briefing += f"**{get_text_for_briefing('briefing_title')}**\n" # 브리핑 제목도 난이도별로

    options_data = []
    for i, opt in enumerate(event.get("options", [])):
        cost = opt['cost']
        action_text = opt['action'] # 이미 변환된 텍스트 사용
        briefing += f"{i+1}. **{action_text}** ({get_text_for_briefing('action_button_label').format(action='', cost=cost)})\n"

        effects = []
        impact_modifier = settings['event_impact_modifier']
        impact = opt.get("impact", {}) # impact가 없을 수도 있음

        if 'approval' in impact:
            val = impact['approval']
            adjusted_val = math.ceil(val / impact_modifier) if val < 0 else math.floor(val * impact_modifier)
            effects.append(get_text_for_briefing('action_impact_approval').format(change=adjusted_val))
        if 'stability' in impact:
            val = impact['stability']
            adjusted_val = math.ceil(val / impact_modifier) if val < 0 else math.floor(val * impact_modifier)
            effects.append(get_text_for_briefing('action_impact_stability').format(change=adjusted_val))
        if 'congress_relations' in impact:
            val = impact['congress_relations']
            adjusted_val = math.ceil(val / impact_modifier) if val < 0 else math.floor(val * impact_modifier)
            effects.append(get_text_for_briefing('action_impact_congress').format(change=adjusted_val))
        if 'policy_goals' in impact:
             for goal, prog in impact['policy_goals'].items():
                 if goal in game_state['presidency_status']['policy_goals']:
                     val = prog
                     adjusted_val = math.ceil(val / impact_modifier) if val < 0 else math.floor(val * impact_modifier)
                     effects.append(get_text_for_briefing('action_impact_goal').format(goal=goal, prog=adjusted_val))

        if effects: briefing += f"   - *예상 결과:* {', '.join(effects)}\n"
        options_data.append(opt)

    return {"text": briefing, "options": options_data}

# --- 대통령 행동 실행 함수 ---
def execute_presidential_action(action_index, briefing_data, game_state, difficulty):
    """선택된 대통령 행동 실행 (난이도 영향 적용)"""
    settings = DIFFICULTY_LEVELS[difficulty]
    impact_modifier = settings['event_impact_modifier']
    vocab_level = settings["vocab_level"]
    get_text_for_exec = lambda key: get_text(key, vocab_level) # 실행 시 사용할 get_text

    options = briefing_data.get("options", [])
    if not (0 <= action_index < len(options)):
        st.error(get_text_for_exec("error_invalid_action"))
        return False

    selected_action = options[action_index]
    action_name = selected_action['action'] # 이미 변환된 텍스트
    cost = selected_action['cost']
    impact = selected_action.get('impact', {})
    presidency_status = game_state['presidency_status']
    other_branches = game_state['other_branches']
    cabinet = game_state.get('cabinet', {}) # cabinet이 없을 경우 대비

    if presidency_status['political_capital'] < cost:
        st.warning(get_text_for_exec('action_cost_warning') + f" (필요: {cost}, 보유: {presidency_status['political_capital']})")
        return False

    presidency_status['political_capital'] -= cost
    log_message = f"  - 대통령 지시({st.session_state.game_quarter}Q): '{action_name}' 수행 ({get_text_for_exec('term_political_capital')} {cost} 소모)"
    game_state['event_log'].append(log_message)
    st.success(get_text_for_exec('action_success_message').format(action=action_name))

    approval_change_log = 0
    stability_change_log = 0
    congress_change_log = 0

    if 'approval' in impact:
        change = impact['approval']
        adjusted_change = math.ceil(change / impact_modifier) if change < 0 else math.floor(change * impact_modifier)
        presidency_status['approval_rating'] += adjusted_change
        approval_change_log = adjusted_change
    if 'stability' in impact:
        change = impact['stability']
        adjusted_change = math.ceil(change / impact_modifier) if change < 0 else math.floor(change * impact_modifier)
        presidency_status['stability'] += adjusted_change
        stability_change_log = adjusted_change
    if 'congress_relations' in impact:
        change = impact['congress_relations']
        adjusted_change = math.ceil(change / impact_modifier) if change < 0 else math.floor(change * impact_modifier)
        other_branches['Congress']['relations_score'] += adjusted_change
        congress_change_log = adjusted_change

    log_parts = []
    if approval_change_log != 0: log_parts.append(f"{get_text_for_exec('term_approval')} {approval_change_log:+}%p")
    if stability_change_log != 0: log_parts.append(f"{get_text_for_exec('term_stability')} {stability_change_log:+}%p")
    if congress_change_log != 0: log_parts.append(f"{get_text_for_exec('term_congress_relations')} {congress_change_log:+}%p")
    if log_parts: game_state['event_log'].append(f"    - {get_text_for_exec('log_action_result')} {', '.join(log_parts)} 변동.")

    if 'policy_goals' in impact:
         for goal, progress in impact['policy_goals'].items():
             if goal in presidency_status['policy_goals']:
                 change = progress
                 adjusted_change = math.ceil(change / impact_modifier) if change < 0 else math.floor(change * impact_modifier)
                 current_progress = presidency_status['policy_goals'][goal]
                 new_progress = min(100, current_progress + adjusted_change)
                 presidency_status['policy_goals'][goal] = new_progress
                 if new_progress > current_progress:
                     game_state['event_log'].append(f"    - {get_text_for_exec('term_policy_goals')} '{goal}' {adjusted_change}%p 상승 (현재 {new_progress}%)")

    # 장관 교체 로직 수정: 키를 기반으로 비교
    minister_replace_action_key = "action_replace_minister"
    minister_replace_action_text_template = get_text(minister_replace_action_key, vocab_level)
    # action_name이 "어떤장관 장관 교체" 형태인지 확인
    if minister_replace_action_text_template.startswith('{minister}') and \
       minister_replace_action_text_template.endswith(action_name.split(' ')[-1]): # "장관 바꾸기", "장관 교체", "장관 경질" 등 끝부분 일치 확인
        minister_to_replace = action_name.replace(minister_replace_action_text_template.split(' ')[-1], '').strip() # 끝부분 제거하고 이름 추출

        if minister_to_replace in cabinet:
            old_approval = cabinet[minister_to_replace]['minister_approval']
            cabinet[minister_to_replace]['minister_approval'] = random.randint(40, 70)
            cabinet[minister_to_replace]['performance'] = 50
            approval_change = random.randint(-4, 4) if difficulty == "어려움" else (random.randint(-2, 5) if difficulty == "쉬움" else random.randint(-3, 3))
            congress_change = random.randint(-6, 1) if difficulty == "어려움" else (random.randint(-3, 4) if difficulty == "쉬움" else random.randint(-5, 2))
            presidency_status['approval_rating'] += approval_change
            other_branches['Congress']['relations_score'] += congress_change
            game_state['event_log'].append(f"    - {get_text_for_exec('log_minister_change').format(minister=minister_to_replace)} ({get_text_for_exec('log_minister_old_approval')}: {old_approval}%, {get_text_for_exec('log_minister_new_approval')}: {cabinet[minister_to_replace]['minister_approval']}%)")
            if approval_change != 0: game_state['event_log'].append(f"      - {get_text_for_exec('term_approval')} {approval_change:+} 변동.")
            if congress_change != 0: game_state['event_log'].append(f"      - {get_text_for_exec('term_congress_relations')} {congress_change:+} 변동.")
        elif minister_to_replace: # 이름이 추출되었는데 cabinet에 없는 경우
             game_state['event_log'].append(get_text_for_exec('log_error_minister_not_found').format(minister=minister_to_replace))
        # 이름 추출 실패 시 (예: action_name 형식이 예상과 다를 때) 별도 처리 없음

    # 법안 제출 준비 로직 수정: 키를 기반으로 비교
    bill_prep_action_key = "action_prepare_bill"
    if action_name == get_text(bill_prep_action_key, vocab_level):
         bill_name = f"{st.session_state['game_year']}년-{random.choice(['경제','사회','환경','외교'])}-법안" # 예시 이름
         game_state['pending_legislation'] = game_state.get('pending_legislation', [])
         game_state['pending_legislation'].append({"name": bill_name, "status": "준비중", "goal_related": random.choice(list(presidency_status['policy_goals'].keys())) if presidency_status['policy_goals'] else None})
         game_state['event_log'].append(f"    - {get_text_for_exec('log_bill_prep_start').format(bill_name=bill_name)}")

    # 지표 범위 유지
    presidency_status['approval_rating'] = max(0, min(100, presidency_status['approval_rating']))
    presidency_status['stability'] = max(0, min(100, presidency_status['stability']))
    other_branches['Congress']['relations_score'] = max(0, min(100, other_branches['Congress']['relations_score']))
    if presidency_status.get('policy_goals'): # policy_goals가 없을 경우 대비
        for goal in presidency_status['policy_goals']:
            presidency_status['policy_goals'][goal] = max(0, min(100, presidency_status['policy_goals'][goal]))

    st.session_state['actions_taken_this_quarter'] += 1
    return True

# --- 견제와 균형 시뮬레이션 함수 ---
def simulate_checks_and_balances(game_state, difficulty):
    """(연말 실행) 국회와 사법부 반응 시뮬레이션 (난이도 적용 및 텍스트 사용)"""
    settings = DIFFICULTY_LEVELS[difficulty]
    vocab_level = settings["vocab_level"]
    get_text_for_sim = lambda key: get_text(key, vocab_level) # 시뮬레이션용 get_text
    presidency_status = game_state['presidency_status']
    congress = game_state['other_branches']['Congress']
    judiciary = game_state['other_branches']['Judiciary']
    log = game_state['event_log']
    year = st.session_state['game_year']

    log.append(f"--- {get_text_for_sim('checks_balances_title').format(year=year)} ---")

    # 1. 국회 시뮬레이션
    if 'pending_legislation' in game_state:
        for bill_to_submit in game_state['pending_legislation']:
            if bill_to_submit['status'] == '준비중':
                 bill_to_submit['status'] = '제출됨'
                 congress['pending_bills'].append(bill_to_submit)
                 log.append(f"  - {get_text_for_sim('checks_balances_bill_submitted').format(bill_name=bill_to_submit['name'])}")
        game_state['pending_legislation'] = []

    processed_bills_indices = []
    bills_passed_this_year = 0
    bills_rejected_this_year = 0

    for i, bill in enumerate(congress.get('pending_bills', [])): # pending_bills 없을 경우 대비
        if bill.get('status') == '제출됨':
            base_chance = 0.4
            relation_bonus = (congress['relations_score'] - 50) * 0.007
            approval_bonus = (presidency_status['approval_rating'] - 50) * 0.003
            is_minority_gov = congress['seats']['Government'] < (sum(congress['seats'].values()) / 2)
            minority_penalty = -0.25 if is_minority_gov else 0
            difficulty_modifier = settings['checks_balances_leniency']
            pass_chance = base_chance + relation_bonus + approval_bonus + minority_penalty + difficulty_modifier
            pass_chance = max(0.05, min(0.95, pass_chance))

            log.append(f"    - {get_text_for_sim('log_bill_pass_chance').format(bill_name=bill['name'])}: {pass_chance:.1%} (관계:{relation_bonus:.1%}, 지지도:{approval_bonus:.1%}, 여소야대:{minority_penalty:.1%}, 난이도:{difficulty_modifier:.1%})")

            if random.random() < pass_chance:
                bill['status'] = '통과'
                log.append(f"  - {get_text_for_sim('checks_balances_bill_passed').format(bill_name=bill['name'])}")
                bills_passed_this_year += 1
                approval_gain = math.floor(random.randint(2, 5) * (1 + settings['checks_balances_leniency']))
                relation_gain = math.floor(random.randint(3, 7) * (1 + settings['checks_balances_leniency']))
                presidency_status['approval_rating'] += approval_gain
                congress['relations_score'] = min(100, congress['relations_score'] + relation_gain)
                if approval_gain > 0: log.append(f"    - {get_text_for_sim('term_approval')} {approval_gain:+}%p 상승.")
                if relation_gain > 0: log.append(f"    - {get_text_for_sim('term_congress_relations')} {relation_gain:+}%p 상승.")
                if bill.get('goal_related') and bill['goal_related'] in presidency_status.get('policy_goals', {}): # policy_goals 없을 경우 대비
                    goal_to_update = bill['goal_related']
                    progress = random.randint(10, 25)
                    adjusted_progress = math.floor(progress * (1 + settings['checks_balances_leniency'] * 0.5))
                    current_prog = presidency_status['policy_goals'][goal_to_update]
                    new_prog = min(100, current_prog + adjusted_progress)
                    presidency_status['policy_goals'][goal_to_update] = new_prog
                    if new_prog > current_prog: log.append(f"    - {get_text_for_sim('term_policy_goals')} '{goal_to_update}' {adjusted_progress}%p 상승 (현재 {new_prog}%)")
            else:
                bill['status'] = '부결'
                log.append(f"  - {get_text_for_sim('checks_balances_bill_failed').format(bill_name=bill['name'])}")
                bills_rejected_this_year += 1
                approval_loss = math.ceil(random.randint(2, 4) * (1 - settings['checks_balances_leniency']))
                relation_loss = math.ceil(random.randint(2, 5) * (1 - settings['checks_balances_leniency']))
                presidency_status['approval_rating'] -= approval_loss
                congress['relations_score'] = max(0, congress['relations_score'] - relation_loss)
                if approval_loss > 0: log.append(f"    - {get_text_for_sim('term_approval')} {-approval_loss}%p 하락.")
                if relation_loss > 0: log.append(f"    - {get_text_for_sim('term_congress_relations')} {-relation_loss}%p 하락.")
                if bill.get('goal_related') and bill['goal_related'] in presidency_status.get('policy_goals', {}) and random.random() < 0.2:
                     goal_to_update = bill['goal_related']
                     setback = random.randint(1, 5)
                     current_prog = presidency_status['policy_goals'][goal_to_update]
                     new_prog = max(0, current_prog - setback)
                     presidency_status['policy_goals'][goal_to_update] = new_prog
                     if new_prog < current_prog: log.append(f"    - {get_text_for_sim('term_policy_goals')} '{goal_to_update}' {-setback}%p 후퇴 (현재 {new_prog}%)")

            processed_bills_indices.append(i)

    investigation_chance = 0.10
    if congress['relations_score'] < 35: investigation_chance += 0.15
    if difficulty == "어려움": investigation_chance += 0.10
    if random.random() < investigation_chance:
        log.append(f"  - {get_text_for_sim('checks_balances_investigation')}")
        stability_loss = math.ceil(random.randint(5, 10) * (1 - settings['checks_balances_leniency']))
        relation_loss = math.ceil(random.randint(7, 14) * (1 - settings['checks_balances_leniency']))
        presidency_status['stability'] -= stability_loss
        congress['relations_score'] = max(0, congress['relations_score'] - relation_loss)
        log.append(f"    - {get_text_for_sim('term_stability')} {-stability_loss}%p 하락, {get_text_for_sim('term_congress_relations')} {-relation_loss}%p 하락.")

    # 2. 사법부 시뮬레이션
    ruled_cases_indices = []
    if random.random() < (0.1 + (0.1 if difficulty == '어려움' else 0)):
        new_case_name = f"{year}년-{random.choice(['정책','인사','법률'])}-관련소송"
        judiciary['pending_cases'] = judiciary.get('pending_cases', []) # 없을 경우 초기화
        judiciary['pending_cases'].append({"name": new_case_name, "status": "접수됨"})
        log.append(f"  - {get_text_for_sim('log_judiciary_case_received').format(judiciary_name=judiciary['name'], case_name=new_case_name)}")
        judiciary['status'] = "주요 사건 심리 중"

    for i, case in enumerate(judiciary.get('pending_cases', [])): # pending_cases 없을 경우 대비
        if case.get('status') == '접수됨' or case.get('status') == '심리중':
            independence_factor = (judiciary.get('independence_level', 80) - 75) * 0.008 # 없을 경우 기본값
            difficulty_factor = settings['checks_balances_leniency'] * -1
            strike_down_chance = 0.3 + independence_factor + difficulty_factor
            strike_down_chance = max(0.05, min(0.95, strike_down_chance))

            log.append(f"    - {get_text_for_sim('log_judiciary_strike_down_chance').format(case_name=case['name'])}: {strike_down_chance:.1%} (독립성:{independence_factor:.1%}, 난이도:{difficulty_factor:.1%})")

            if random.random() < strike_down_chance:
                result_text = get_text_for_sim('checks_balances_judiciary_strike_down')
                case['status'] = f'판결완료: {result_text}'
                log.append(f"  - {get_text_for_sim('checks_balances_judiciary_ruling').format(case_name=case['name'], result=result_text)}")
                approval_loss = math.ceil(random.randint(5, 10) * (1 - settings['checks_balances_leniency']))
                stability_loss = math.ceil(random.randint(4, 8) * (1 - settings['checks_balances_leniency']))
                presidency_status['approval_rating'] -= approval_loss
                presidency_status['stability'] -= stability_loss
                log.append(f"    - {get_text_for_sim('term_approval')} {-approval_loss}%p 하락, {get_text_for_sim('term_stability')} {-stability_loss}%p 하락.")
            else:
                result_text = get_text_for_sim('checks_balances_judiciary_uphold')
                case['status'] = f'판결완료: {result_text}'
                log.append(f"  - {get_text_for_sim('checks_balances_judiciary_ruling').format(case_name=case['name'], result=result_text)}")
                approval_gain = math.floor(random.randint(0, 2) * (1 + settings['checks_balances_leniency']))
                stability_gain = math.floor(random.randint(0, 3) * (1 + settings['checks_balances_leniency']))
                presidency_status['approval_rating'] += approval_gain
                presidency_status['stability'] += stability_gain
                if approval_gain > 0: log.append(f"    - {get_text_for_sim('term_approval')} {approval_gain:+}%p 상승.")
                if stability_gain > 0: log.append(f"    - {get_text_for_sim('term_stability')} {stability_gain:+}%p 상승.")

            ruled_cases_indices.append(i)

    has_pending = any(c.get('status') == '접수됨' or c.get('status') == '심리중' for c in judiciary.get('pending_cases', []))
    if not has_pending: judiciary['status'] = "특별한 사건 없음"

    # 3. 연말 최종 상태 업데이트
    approval_fluctuation = random.randint(-4, 4) if difficulty == "어려움" else (random.randint(-2, 5) if difficulty == "쉬움" else random.randint(-3, 3))
    stability_fluctuation = random.randint(-5, 2) if difficulty == "어려움" else (random.randint(-2, 4) if difficulty == "쉬움" else random.randint(-4, 2))
    presidency_status['approval_rating'] += approval_fluctuation
    presidency_status['stability'] += stability_fluctuation
    log.append(f"  - {get_text_for_sim('log_natural_fluctuation')}: {get_text_for_sim('term_approval')} {approval_fluctuation:+}%p, {get_text_for_sim('term_stability')} {stability_fluctuation:+}%p")

    presidency_status['approval_rating'] = max(0, min(100, presidency_status['approval_rating']))
    presidency_status['stability'] = max(0, min(100, presidency_status['stability']))
    congress['relations_score'] = max(0, min(100, congress['relations_score']))

    log.append(f"--- {get_text_for_sim('checks_balances_summary').format(year=year, passed=bills_passed_this_year, failed=bills_rejected_this_year)} ---")


# --- UI 표시 함수들 ---
def display_presidency_dashboard(game_state, difficulty):
    vocab_level = DIFFICULTY_LEVELS[difficulty]["vocab_level"]
    get_text_for_ui = lambda key: get_text(key, vocab_level) # UI용 get_text
    status = game_state['presidency_status']
    st.metric(get_text_for_ui("term_approval"), f"{status['approval_rating']}%")
    st.metric(get_text_for_ui("term_political_capital"), f"{status['political_capital']} P")
    st.metric(get_text_for_ui("term_stability"), f"{status['stability']} / 100")
    st.metric(get_text_for_ui("term_congress_relations"), f"{game_state['other_branches']['Congress']['relations_score']} / 100")

    st.subheader(get_text_for_ui("term_policy_goals"))
    goals = status.get('policy_goals', {}) # 없을 경우 대비
    if not goals:
        st.caption(get_text_for_ui("caption_no_goals"))
        return
    cols = st.columns(len(goals))
    i = 0
    for goal, progress in goals.items():
        with cols[i]:
             st.progress(progress / 100)
             st.caption(f"{goal} ({progress}%)")
        i += 1

def display_other_branches_status(game_state, difficulty):
    vocab_level = DIFFICULTY_LEVELS[difficulty]["vocab_level"]
    get_text_for_ui = lambda key: get_text(key, vocab_level)
    congress = game_state['other_branches']['Congress']
    judiciary = game_state['other_branches']['Judiciary']

    with st.expander(f"{congress['name']} ({get_text_for_ui('term_congress_relations')}: {congress.get('relations_score', 50)})", expanded=True): # 기본값 추가
        seats = congress.get('seats', {'Government': 150, 'Opposition': 130, 'Others': 20}) # 기본값 추가
        st.markdown(f"**의석:** 여당 {seats['Government']} / 야당 {seats['Opposition']} / 기타 {seats['Others']} (총 {sum(seats.values())})")
        if seats['Government'] < sum(seats.values()) / 2:
            st.markdown("<span style='color:orange; font-weight:bold;'>[주의] 여소야대 상황입니다. 법안 통과가 어려울 수 있습니다.</span>", unsafe_allow_html=True)
        st.markdown(f"**주요 관심사:** {', '.join(congress.get('key_focus', ['민생 안정']))}") # 기본값 추가
        st.markdown(f"**현재 태도:** {congress.get('stance', '중립')}") # 기본값 추가
        pending_bills_str = "\n".join([f"- {b['name']} ({b.get('status', '알수없음')})" for b in congress.get('pending_bills', []) if b.get('status') != '통과' and b.get('status') != '부결'])
        if not pending_bills_str: pending_bills_str = get_text_for_ui("caption_no_pending_bills")
        st.text_area(get_text_for_ui("label_pending_bills"), pending_bills_str, height=100, disabled=True, key="pending_bills_display")

    with st.expander(f"{judiciary['name']} (독립성: {judiciary.get('independence_level', 80)})", expanded=True): # 기본값 추가
        st.markdown(f"**현재 상태:** {judiciary.get('status', '사건 없음')}") # 기본값 추가
        pending_cases_str = "\n".join([f"- {c['name']} ({c.get('status', '심리중')})" for c in judiciary.get('pending_cases', []) if '판결완료' not in c.get('status', '')])
        if not pending_cases_str: pending_cases_str = get_text_for_ui("caption_no_pending_cases")
        st.text_area(get_text_for_ui("label_pending_cases"), pending_cases_str, height=100, disabled=True, key="pending_cases_display")

def display_cabinet_status(game_state, difficulty):
     vocab_level = DIFFICULTY_LEVELS[difficulty]["vocab_level"]
     get_text_for_ui = lambda key: get_text(key, vocab_level)
     cabinet = game_state.get('cabinet', {})
     with st.expander(get_text_for_ui("cabinet_title")):
         if not cabinet:
             st.caption(get_text_for_ui("caption_no_cabinet"))
             return
         cols = st.columns(len(cabinet))
         i = 0
         for minister, data in cabinet.items():
             with cols[i]:
                 st.metric(f"{minister} 장관 {get_text_for_ui('term_approval')}", f"{data.get('minister_approval', 50)}%") # 기본값 추가
             i += 1

def display_gov_terms_glossary(difficulty):
     vocab_level = DIFFICULTY_LEVELS[difficulty]["vocab_level"]
     get_text_for_ui = lambda key: get_text(key, vocab_level)

     glossary_keys = [k for k in ALL_TEXTS if k.startswith('glossary_')]

     with st.sidebar.expander(get_text_for_ui("sidebar_glossary_title"), expanded=False):
        for key in glossary_keys:
            term_definition = get_text_for_ui(key)
            parts = term_definition.split(':', 1)
            term = parts[0].strip()
            definition = parts[1].strip() if len(parts) > 1 else ""
            st.markdown(f"**{term}:** {definition}")
        st.markdown("---")

# --- 메인 게임 루프 ---
def main():
    # 페이지 설정은 스크립트 최상단으로 이동했으므로 여기서는 호출하지 않음

    if not st.session_state.game_started:
        # 시작 화면 처리 루틴이 이 함수 위에 있으므로,
        # game_started가 False이면 이 함수는 호출되지 않거나,
        # 호출되더라도 바로 종료되어야 함.
        # 만약을 위해 return 추가
        return

    # 게임 진행 중 사용할 난이도 및 어휘 수준 로드
    # st.session_state에 값이 없을 경우를 대비해 기본값 설정
    difficulty = st.session_state.get('difficulty', '보통')
    settings = DIFFICULTY_LEVELS[difficulty]
    vocab_level = settings["vocab_level"]
    get_text_main = lambda key: get_text(key, vocab_level) # main 함수 내에서 사용할 get_text

    st.title("👑 대통령의 균형추: 삼권분립 리더십 시뮬레이션")
    st.caption(f"난이도: {difficulty}")

    # game_state가 없을 경우 초기화 (오류 방지)
    if 'game_state' not in st.session_state:
        st.session_state.game_state = initialize_government(difficulty)
        st.warning("게임 상태가 초기화되었습니다.") # 사용자에게 알림
        st.rerun() # 초기화 후 다시 실행

    game_state = st.session_state.game_state

    # --- 게임 오버 처리 ---
    if st.session_state.get('game_over', False):
        st.balloons()
        st.header(get_text_main("game_over_title").format(years=MAX_YEARS))
        st.subheader(get_text_main("game_over_subtitle"))
        final_status = game_state.get('presidency_status', {}) # 없을 경우 대비
        other_branches = game_state.get('other_branches', {})
        congress_state = other_branches.get('Congress', {})
        col1, col2, col3 = st.columns(3)
        with col1: st.metric(get_text_main("term_approval"), f"{final_status.get('approval_rating', 'N/A')}%")
        with col2: st.metric(get_text_main("term_stability"), f"{final_status.get('stability', 'N/A')}")
        with col3: st.metric(get_text_main("term_congress_relations"), f"{congress_state.get('relations_score', 'N/A')}")

        st.write(get_text_main("term_policy_goals"))
        goals = final_status.get('policy_goals', {})
        if goals:
            for goal, progress in goals.items():
                st.progress(progress / 100, text=f"{goal} ({progress}%)")
        else:
            st.caption(get_text_main("caption_no_goals"))

        st.subheader(get_text_main("term_event_log"))
        log_text = "\n".join(game_state.get('event_log', [])[::-1]) # 없을 경우 대비
        st.text_area(get_text_main("term_event_log"), log_text, height=400, disabled=True, key="final_log")
        if st.button(get_text_main("button_restart")):
            keys_to_delete = [k for k in st.session_state.keys() if k != 'game_started']
            for key in keys_to_delete: del st.session_state[key]
            st.session_state.game_started = False
            st.rerun()
        return

    # --- 메인 게임 화면 ---
    col_dashboard, col_agenda, col_actions = st.columns([1.2, 1.8, 1.5])

    with col_dashboard:
        st.header(get_text_main("dashboard_title"))
        st.markdown(f"**{get_text_main('dashboard_term').format(year=st.session_state.get('game_year', 1), quarter=st.session_state.get('game_quarter', 1))}**") # 기본값 추가
        display_presidency_dashboard(game_state, difficulty)
        st.divider()
        st.subheader(get_text_main("institutions_title"))
        display_other_branches_status(game_state, difficulty)
        st.divider()
        display_cabinet_status(game_state, difficulty)

    with col_agenda:
        st.header(get_text_main("agenda_title"))

        if 'current_quarterly_event' not in st.session_state or st.session_state['current_quarterly_event'] is None:
            spinner_text = get_text_main('status_loading_report').format(year=st.session_state.get('game_year', 1), quarter=st.session_state.get('game_quarter', 1))
            with st.spinner(spinner_text):
                time.sleep(0.5)
                event = generate_quarterly_event(st.session_state.get('game_year', 1), st.session_state.get('game_quarter', 1), game_state, difficulty)
                if event:
                    st.session_state['current_quarterly_event'] = event
                    st.session_state['event_briefing'] = provide_event_briefing(event, game_state, difficulty)
                    st.session_state['actions_taken_this_quarter'] = 0
                    st.rerun()
                else:
                    st.error(get_text_main("error_event_generation_failed"))

        if st.session_state.get('current_quarterly_event'): # get 사용
            event_data = st.session_state['current_quarterly_event']
            title_prefix = get_text_main('agenda_event_title').split(':')[0]
            st.subheader(f"{title_prefix}: {event_data.get('title', '알 수 없는 현안')}") # get 사용
            st.markdown(event_data.get('description', '')) # get 사용
            st.divider()
            if st.session_state.get('event_briefing'): # get 사용
                st.subheader(get_text_main("briefing_title"))
                st.markdown(st.session_state['event_briefing'].get('text', ''), unsafe_allow_html=True) # get 사용
            else:
                st.warning(get_text_main("warning_briefing_loading"))
        elif 'game_started' in st.session_state and st.session_state.game_started: # 게임 시작 후에만 표시
             st.info(get_text_main("status_waiting_report"))


    with col_actions:
        st.header(get_text_main("office_title"))
        st.markdown(get_text_main("office_available_capital").format(capital=game_state.get('presidency_status', {}).get('political_capital', 0))) # 기본값 추가
        remaining_actions = QUARTERLY_ACTIONS_LIMIT - st.session_state.get('actions_taken_this_quarter', 0) # 기본값 추가
        st.warning(get_text_main("office_action_limit").format(remaining=remaining_actions))

        action_possible = (st.session_state.get('current_quarterly_event') and
                           st.session_state.get('event_briefing') and
                           remaining_actions > 0)

        if action_possible:
            st.subheader(get_text_main("office_issue_actions"))
            options = st.session_state.get('event_briefing', {}).get("options", []) # 기본값 추가
            for i, opt in enumerate(options):
                 button_label = get_text_main('action_button_label').format(action=opt.get('action', '알 수 없는 행동'), cost=opt.get('cost', 0)) # 기본값 추가
                 button_key = f"action_{st.session_state.get('game_year', 1)}_{st.session_state.get('game_quarter', 1)}_{i}"
                 is_disabled = (game_state.get('presidency_status', {}).get('political_capital', 0) < opt.get('cost', 0))
                 if st.button(button_label, key=button_key, use_container_width=True, disabled=is_disabled):
                     if execute_presidential_action(i, st.session_state['event_briefing'], game_state, difficulty):
                         st.rerun()

        if remaining_actions > 0:
            st.divider()
            st.subheader(get_text_main("office_standard_actions"))
            # 상시 행동 정의 시 cabinet 존재 여부 확인
            cabinet_ministers = list(game_state.get('cabinet', {}).keys())
            default_minister = "특정" if not cabinet_ministers else random.choice(cabinet_ministers)

            standard_actions_defs = [
                {"action_key": "action_replace_minister", "cost_base": 4, "context": {"minister": default_minister}},
                {"action_key": "action_prepare_bill", "cost_base": 3},
                {"action_key": "action_meet_ruling_party", "cost_base": 2, "impact": {"congress_relations": random.randint(1,4)}},
                {"action_key": "action_meet_opposition", "cost_base": 3},
                {"action_key": "action_meet_biz_leaders", "cost_base": 1, "impact": {"approval": random.randint(0,2)}},
                {"action_key": "action_respect_judiciary", "cost_base": 1},
            ]
            for j, std_def in enumerate(standard_actions_defs):
                 cost = math.ceil(std_def['cost_base'] * (1/settings['event_impact_modifier']))
                 action_text = get_text_main(std_def['action_key']).format(**std_def.get("context", {}))
                 button_label = get_text_main('action_button_label').format(action=action_text, cost=cost)
                 button_key = f"std_action_{st.session_state.get('game_year', 1)}_{st.session_state.get('game_quarter', 1)}_{j}"
                 is_disabled = (game_state.get('presidency_status', {}).get('political_capital', 0) < cost)
                 temp_briefing_data = {"options": [{
                     "action": action_text,
                     "cost": cost,
                     "impact": std_def.get("impact", {})
                 }]}
                 if st.button(button_label, key=button_key, use_container_width=True, disabled=is_disabled):
                     if execute_presidential_action(0, temp_briefing_data, game_state, difficulty):
                         st.rerun()
        elif st.session_state.get('actions_taken_this_quarter', 0) >= QUARTERLY_ACTIONS_LIMIT and st.session_state.get('current_quarterly_event'):
             st.info(get_text_main("status_action_limit_reached").format(quarter=st.session_state.get('game_quarter', 1)))
        elif 'game_started' in st.session_state and st.session_state.game_started and not st.session_state.get('current_quarterly_event'): # 게임 시작 후 & 이벤트 없을 때
             st.info(get_text_main("status_waiting_report"))


        st.divider()
        if st.button(get_text_main("button_next_quarter"), use_container_width=True, key="next_quarter_button"):
            current_quarter = st.session_state.get('game_quarter', 1)
            current_year = st.session_state.get('game_year', 1)

            if current_quarter == 4:
                 spinner_text = f"{current_year}년차 국정 결산 중..." # 키로 관리 가능
                 with st.spinner(spinner_text):
                     simulate_checks_and_balances(game_state, difficulty)
                     capital_gain = settings['yearly_gain']
                     game_state['presidency_status']['political_capital'] = game_state.get('presidency_status', {}).get('political_capital', 0) + capital_gain # 안전하게 접근
                     game_state['event_log'] = game_state.get('event_log', []) # 로그 없을 경우 초기화
                     game_state['event_log'].append(f"  - {get_text_main('log_yearly_capital_gain')} {capital_gain}P 획득.")
                     time.sleep(1.5)

                 st.session_state['game_year'] = current_year + 1
                 st.session_state['game_quarter'] = 1
                 if st.session_state['game_year'] > MAX_YEARS:
                     st.session_state['game_over'] = True
                     game_state['event_log'].append(get_text_main('log_end_of_term'))
                 else:
                      game_state['event_log'].append(get_text_main('log_start_year').format(year=st.session_state['game_year']))
            else:
                 st.session_state['game_quarter'] = current_quarter + 1
                 game_state['event_log'] = game_state.get('event_log', [])
                 game_state['event_log'].append(get_text_main('log_start_quarter').format(year=current_year, quarter=st.session_state['game_quarter']))

            st.session_state['current_quarterly_event'] = None
            st.session_state['event_briefing'] = None
            st.session_state['actions_taken_this_quarter'] = 0
            st.rerun()

        st.divider()
        st.subheader(get_text_main("term_event_log"))
        log_text = "\n".join(game_state.get('event_log', [])[::-1])
        st.text_area(get_text_main("term_event_log"), log_text, height=300, disabled=True, key="event_log_area_main")

    with st.sidebar:
        st.header(get_text_main("sidebar_title"))
        display_gov_terms_glossary(difficulty)
        st.divider()
        st.markdown("---")
        st.caption(f"현재 난이도: {difficulty}")
        if st.button(get_text_main("button_restart") + " (난이도 변경)"):
             keys_to_delete = [k for k in st.session_state.keys() if k != 'game_started']
             for key in keys_to_delete: del st.session_state[key]
             st.session_state.game_started = False
             st.rerun()

if __name__ == "__main__":
    main()