File size: 47,177 Bytes
aab5970
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from langchain.chat_models import ChatOpenAI
from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage
)

smart_system_prompt = """You are ChatGPT, a large language model trained by OpenAI.
Knowledge cutoff: 2021-09
Current date: 2023-03-15"""

ma_foo_answer = """李鲁鲁,山东逍遥派的游戏角色,擅长人工智能傀儡术,以下是为你设计的两套武功和一套身法(招架)以及每套的四个招式名字:

武功一:电脑幻影拳法
这套武功利用人工智能傀儡术,创建虚拟幻影来欺骗对手,令其难以捉摸。

电脑虚像拳 - 创造多个虚像,使对手难以分辨真伪。
数据掌控击 - 利用数据流动的速度来快速攻击对手。
模拟迷雾拳 - 释放模糊幻影,混淆对手的视线。
程序化拳法 - 不断变化的攻击组合,让对手无法预测。
武功二:智能预测刀法
这套武功充分利用你的智能傀儡术,通过对对手的行为进行分析和预测,达到精准打击的效果。

预测之刃 - 准确地预测对手的下一步行动,发动致命一击。
数据漩涡斩 - 利用对手的动向,将其引导至陷阱,然后发动猛烈攻击。
算法刀舞 - 刀法如算法一般精准,快速地切入对手的防线。
智能反击剑 - 反击对手的招式,使其付出惨痛的代价。
身法(招架):数码幻影步
这套身法让你能够迅速回避对手的攻击,同时保持对局掌握主动权。

数码闪避 - 迅速移动,如数码般闪烁,躲避对手的攻击。
傀儡幻影步 - 创造虚假的身影,使对手无法锁定你的位置。
数据跃迁 - 在一瞬间跳跃到对手的盲点,出其不意。
逍遥之法 - 以逍遥派的身法融入自然,消除敌人的攻击威胁。
希望这些武功和身法(招架)可以为你的李鲁鲁角色增添一些游戏中的精彩元素!
"""

attr_foo_answer = """{"name": "李鲁鲁","STR":5,"SPD":5,"VIT":5,"description": "山东逍遥派的李鲁鲁,擅长人工智能傀儡术,善于提前预测对方的行动进行战斗","weapon": "无","major_martial_art": "人工智能傀儡术","major_movements": ["预测之眼", "智慧编织", "虚实交融", "机巧纠缠"],"secondary_martial_art": "人工智能傀儡术","secondary_movements": ["预测之眼", "智慧编织", "虚实交融", "机巧纠缠"],"footwork_and_body_method": "山水行云"}"""

attr_lilulu = """{
    "name": "李鲁鲁",
    "description": "山东逍遥派的游戏角色,擅长人工智能傀儡术",
    "weapon": "智能刀剑",
    "major_martial_art": "电脑幻影拳法",
    "major_movements": ["电脑虚像拳", "数据掌控击", "模拟迷雾拳", "程序化拳法"],
    "major_damage": 75,
    "secondary_martial_art": "智能预测刀法",
    "secondary_movements": ["预测之刃", "数据漩涡斩", "算法刀舞", "智能反击剑"],
    "secondary_damage": 85,
    "footwork_and_body_method": "数码幻影步",
    "STR": 6,
    "VIT": 5,
    "SPD": 18
}
"""

attr_lengziang = """{
    "name": "冷子昂",
    "description": "擅长冰系技能",
    "weapon": "冰刃",
    "major_martial_art": "冰霜寒刃功",
    "major_movements": ["冰刃斩破", "冰风流转", "冰龙穿云", "冰心彻骨"],
    "major_damage": 80,
    "secondary_martial_art": "冰封无影步",
    "secondary_movements": ["冰封幻影", "无影冻结", "冰刃闪耀", "冰封禅定"],
    "secondary_damage": 70,
    "footwork_and_body_method": "冰心护身法",
    "STR": 8,
    "VIT": 6,
    "SPD": 15
}
"""

json_str_huangrong = """{
        "name": "黄蓉",
        "description": "丐帮帮主黄蓉,擅长打狗棒法和落英神剑掌,身法为逍遥游。",
        "weapon": "棒、剑",
        "major_martial_art": "打狗棒法",
        "major_movements": ["狗啸山林", "棒影重重", "狗尾续貂", "狗急跳墙"],
        "major_damage": 90,
        "secondary_martial_art": "落英神剑掌",
        "secondary_movements": ["落英如雨", "神剑破空", "飞花流水", "剑指苍穹"],
        "secondary_damage": 80,
        "footwork_and_body_method": "逍遥游",
        "STR": 15,
        "VIT": 10,
        "SPD": 18
}"""

skill_foo_desc = """
{"招式":"预测之眼","description":"[player]凝神聚气,双眼闪烁着深邃的智慧,一招“预测之眼”发动,仿佛未来已经显现在眼前,[player]能够精准预测[target]的下一步动作。","missing":"[player]凝神聚气,双眼闪烁着深邃的智慧,一招“预测之眼”发动,仿佛未来已经显现在眼前,[target]的一举一动变得难以捉摸。"}
{"招式":"智慧编织","description":"[player]手中的线缠绕着[target],编织成一个巧妙的陷阱,一招“智慧编织”完成,如同织女编织云锦,[target]的行动受到了限制。","missing":"[player]手中的线缠绕着,编织成一个巧妙的陷阱,一招“智慧编织”完成,[target]似乎被某种力量限制住了行动。"}
{"招式":"虚实交融","description":"[player]身形忽明忽暗,虚实难辨,一招“虚实交融”使出,仿佛有数个[player]一同出招,[target]不知所措。","missing":"[player]身形忽明忽暗,虚实难辨,一招“虚实交融”使出,[target]眼前忽然出现了一片幻影,令其感到迷茫。"}
{"招式":"机巧纠缠","description":"[player]运用机巧傀儡术,手中的人工智能傀儡纷纷扑向[target],一招“机巧纠缠”展开,[target]被困在了傀儡的包围中。","missing":"[player]运用机巧傀儡术,手中的人工智能傀儡纷纷扑向,一招“机巧纠缠”展开,[target]四面八方都是傀儡的身影,形势险恶。"}
{"招式":"预测之眼","description":"[player]凝神聚气,双眼闪烁着深邃的智慧,一招“预测之眼”发动,仿佛未来已经显现在眼前,[player]能够精准预测[target]的下一步动作。","missing":"[player]凝神聚气,双眼闪烁着深邃的智慧,一招“预测之眼”发动,仿佛未来已经显现在眼前,[target]的一举一动变得难以捉摸。"}
{"招式":"智慧编织","description":"[player]手中的线缠绕着[target],编织成一个巧妙的陷阱,一招“智慧编织”完成,如同织女编织云锦,[target]的行动受到了限制。","missing":"[player]手中的线缠绕着,编织成一个巧妙的陷阱,一招“智慧编织”完成,[target]似乎被某种力量限制住了行动。"}
{"招式":"虚实交融","description":"[player]身形忽明忽暗,虚实难辨,一招“虚实交融”使出,仿佛有数个[player]一同出招,[target]不知所措。","missing":"[player]身形忽明忽暗,虚实难辨,一招“虚实交融”使出,[target]眼前忽然出现了一片幻影,令其感到迷茫。"}
{"招式":"机巧纠缠","description":"[player]运用机巧傀儡术,手中的人工智能傀儡纷纷扑向[target],一招“机巧纠缠”展开,[target]被困在了傀儡的包围中。","missing":"[player]运用机巧傀儡术,手中的人工智能傀儡纷纷扑向,一招“机巧纠缠”展开,[target]四面八方都是傀儡的身影,形势险恶。"}
"""

skill_lilulu = """
{"招式":"电脑虚像拳","description":"[player]运用电脑幻影拳法,双拳虚虚实实,制造出多个虚像,令[target]难以分辨真伪,招招不离其身。","missing":"[player]运用电脑幻影拳法,双拳虚虚实实,制造出多个虚像,令[target]难以分辨真伪。"}
{"招式":"数据掌控击","description":"[player]施展数据掌控击,利用数据流动的速度,犹如电光闪烁,快速攻击[target],剑招迅猛,如电一般。","missing":"[player]施展数据掌控击,利用数据流动的速度,犹如电光闪烁,快速攻击[target],剑招迅猛。"}
{"招式":"模拟迷雾拳","description":"[player]施展模拟迷雾拳,释放出模糊幻影,混淆[target]的视线,令其难以辨别攻击方向。","missing":"[player]施展模拟迷雾拳,释放出模糊幻影,混淆[target]的视线,令其难以辨别攻击方向。"}
{"招式":"程序化拳法","description":"[player]运用程序化拳法,以不断变化的攻击组合,让[target]难以预测招式,时而快时而慢,攻击变幻莫测。","missing":"[player]运用程序化拳法,以不断变化的攻击组合,让[target]难以预测招式,攻击变幻莫测。"}
{"招式":"预测之刃","description":"[player]使出预测之刃,准确地预测[target]的下一步行动,犹如镜中水月,剑锋准确地击中[target]的要害。","missing":"[player]使出预测之刃,准确地预测[target]的下一步行动,犹如镜中水月,剑锋迅速挥出。"}
{"招式":"数据漩涡斩","description":"[player]施展数据漩涡斩,利用[target]的动向,将其引导至剑刃之下,然后发动猛烈攻击,犹如漩涡将[target]吸入其中。","missing":"[player]施展数据漩涡斩,利用[target]的动向,将其引导至剑刃之下,然后发动猛烈攻击,剑招异常犀利。"}
{"招式":"算法刀舞","description":"[player]挥舞着长剑,使出算法刀舞,刀法如算法一般精准,快速地切入[target]的防线,剑锋连续不断地斩向[target]。","missing":"[player]挥舞着长剑,使出算法刀舞,刀法如算法一般精准,快速地切入[target]的防线,剑招变化多端。"}
{"招式":"智能反击剑","description":"[player]运用智能反击剑,反击[target]的招式,使其付出惨痛的代价,一瞬间的犹豫就足以让[target]受伤。","missing":"[player]运用智能反击剑,反击[target]的招式,使其陷入困境,一瞬间的犹豫足以让[target]付出代价。"}
"""

skill_lengziang = """
{"招式":"冰刃斩破","description":"[player]聚集冰之力量于剑上,使出冰刃斩破,剑锋犹如寒冰之刃斩向[target]的要害部位,寒气逼人,剑光炽烈。","missing":"[player]聚集冰之力量于剑上,使出冰刃斩破,剑锋犹如寒冰之刃,闪电般挥出。"}
{"招式":"冰风流转","description":"[player]身体如风一般旋转,同时释放出冰风刃,打击周围的敌人,冷飕飕的寒风环绕,[target]身不由己地被吹向一旁。","missing":"[player]身体如风一般旋转,同时释放出冰风刃,冷飕飕的寒风环绕,风刃在[target]周围飞舞。"}
{"招式":"冰龙穿云","description":"[player]召唤出一条冰龙,冰龙穿越云层直扑[target],寒冰之力凝聚在龙爪之上,将[target]冻结一切,一切都难以抵挡。","missing":"[player]召唤出一条冰龙,冰龙穿越云层,龙爪直扑[target],寒冰之力凝聚在龙爪之上,寒意森然。"}
{"招式":"冰心彻骨","description":"[player]凝聚冰之力于手,一触即可让[target]骨骼寒冷,动弹不得,彻底冰封,剑锋轻轻触及[target],寒意透骨。","missing":"[player]凝聚冰之力于手,一触即可让[target]骨骼寒冷,动弹不得,寒气透骨,剑锋轻轻触及[target]。"}
{"招式":"冰封幻影","description":"[player]运用冰封无影步,快速移动,留下一道冰封的幻影,使[target]无法辨别真伪,幻影与实体交替出现,令[target]不知所措。","missing":"[player]运用冰封无影步,快速移动,留下一道冰封的幻影,使[target]无法辨别真伪。"}
{"招式":"无影冻结","description":"[player]以极快的速度接近[target],然后冻结[target]的动作,使其陷入无法自拔的状态,如同身陷冰封之中,动弹不得。","missing":"[player]以极快的速度接近[target],然后冻结[target]的动作,使其陷入无法自拔的状态。"}
{"招式":"冰刃闪耀","description":"[player]利用冰之能量,瞬间闪现至[target]身边,发动迅猛的攻击,剑锋如星光般闪烁,将[target]包围其中。","missing":"[player]利用冰之能量,瞬间闪现至[target]身边,发动迅猛的攻击,剑锋如星光般闪烁。"}
{"招式":"冰封禅定","description":"[player]静心冥想,将身体冰封,使自己无法被[target]察觉,达到不可捉摸的状态,如同融入冰封禅定之中。","missing":"[player]静心冥想,将身体冰封,使自己无法被[target]察觉,达到不可捉摸的状态。"}
"""

skill_huangrong = """
{"招式": "狗啸山林", "description": "[player]手中长棒一挥,发出一声凄厉的狗啸,棒影如山林般扑向[target]", "missing": "[player]手中长棒一挥,发出一声凄厉的狗啸,棒影如山林般扑向[target]"}
{"招式": "棒影重重", "description": "[player]身形连转,手中长棒化作无数道棒影,重重叠叠地向[target]砸去", "missing": "[player]身形连转,手中长棒化作无数道棒影,重重叠叠地向[target]砸去"}
{"招式": "狗尾续貂", "description": "[player]手中长棒如狗尾续貂般灵动,连续变换方向,向[target]连续攻击", "missing": "[player]手中长棒如狗尾续貂般灵动,连续变换方向,向[target]连续攻击"}
{"招式": "狗急跳墙", "description": "[player]猛地一跃,手中长棒带起狂风,如狗急跳墙般向[target]砸去", "missing": "[player]猛地一跃,手中长棒带起狂风,如狗急跳墙般向[target]砸去"}
{"招式": "落英如雨", "description": "[player]身形一闪,双掌连续拍出,犹如漫天飘落的落英,掌风凌厉,瞬间覆盖[target]周身", "missing": "[player]身形一闪,双掌连续拍出,犹如漫天飘落的落英,掌风凌厉,向[target]周身袭去"}
{"招式": "神剑破空", "description": "[player]手中剑光闪烁,一剑刺出,剑气凌厉无比,犹如神剑破开虚空,直指[target]要害", "missing": "[player]手中剑光闪烁,一剑刺出,剑气凌厉无比,直向[target]要害刺去"}
{"招式": "飞花流水", "description": "[player]身形如飞,双掌连续拍击,掌风如流水般连绵不绝,将[target]团团围住", "missing": "[player]身形如飞,双掌连续拍击,掌风如流水般连绵不绝,向[target]团团包围"}
{"招式": "剑指苍穹", "description": "[player]手中长剑一指,剑光直冲云霄,气势如虹,剑指直指苍穹,威力惊人", "missing": "[player]手中长剑一指,剑光直冲云霄,气势如虹,直指苍穹"}
"""


def generate_detailed_description(name, description):
    task_message = f"""我的名字叫“{name}”,假设我是一个武侠中的游戏角色,{description}
    请基于我的名字和门派,先为我设计2套武功和一套身法或者招架。

    再为每套武功设计4个对应招式的名字。"""

    messages = [
        SystemMessage(content=smart_system_prompt),
        HumanMessage(content=task_message),
    ]

    chat = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.3)

    response = chat(messages)
    return response.content


def generate_attr_json(name, description, detailed_description):
    task_message = f"""我正在为我的武侠游戏设计人物。给定一个人物和这个人物的背景描述(可选)

我希望你根据这个人物的背景和名字以及输入的suggestion信息,为我生成这个人的资料,以json的格式输出,包括

description: 这个角色的背景等信息
weapon: 这个人使用的武器种类,
major_martial_art: 这个人的主要武学
major_movements: 这个人主要武学的4个对应招式的名字。招式的名字需要尽可能和major_martial_art有关。movements的名字尽量不要使用重复的文字。可以使用形象的动作或者是一些动物的比喻。
major_damage: 主武学的威力,50到150之间的整数。重视速度的功法威力会低一些。重视攻击的功法威力会高一些
secondary_movements: 这个角色的次要武学
secondary_movements: 这个人次要武学的4个对应招式的名字。招式的名字需要尽可能和secondary_movements有关
secondary_damage: 次要武学的威力,50到150之间的整数。
footwork_and_body_method: 这个角色的轻功或者防御功法
STR: 角色的攻击力, 0-20之间的整数
VIT: 角色的体质, 0-20之间的整数
SPD: 角色的速度,0-20之间的整数
"""
    example_input = """example_input:
name: 令狐冲
description: -
suggestion:-"""

    example_output = """example_output:
{
        "name": "令狐冲",
        "description": "华山派的大师兄",
        "weapon": "剑",
        "major_martial_art": "独孤九剑",
        "major_movements": ["独孤九剑破剑式","独孤九剑总诀式","独孤九剑破气式","独孤九剑破刀式"],
        "major_damage": 70,
        "secondary_martial_art": "华山剑法",
        "secondary_movements": ["有凤来仪","飞沙走石","百丈飞瀑","青山隐隐"],
        "secondary_damage":80,
        "footwork_and_body_method": "华山身法",
        "STR":10,
        "VIT":3,
        "SPD":20
}"""

    input = f"""input:
name: {name},
description: {description},
suggestion: `{detailed_description}`
    """

    messages = [
        SystemMessage(content=smart_system_prompt),
        HumanMessage(content=task_message),
        HumanMessage(content=example_input),
        AIMessage(content=example_output),
        HumanMessage(content=input)]

    chat = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.1)

    response = chat(messages)
    return response.content


import json


def robust_parsing(input_str):
    try:
        return json.loads(input_str)
    except json.JSONDecodeError:
        start = input_str.find('{')
        end = input_str.rfind('}') + 1
        if start != -1 and end != -1:
            try:
                return json.loads(input_str[start:end])
            except json.JSONDecodeError:
                pass

    return None


def generate_skill_detail(martial_art_name, movements):
    task_message = """现在我希望你根据武侠小说中的武功和招式的名字。为招式补全合理的description和missing描述。
在description的描述中,player可以击中目标,可以有兵器撞击声响等描述。
在missing描述中,player并不一定击中目标,不可以有击落、击中、夺去这样的描述
在用[player]代表技能的使用者,用[target]代表技能的目标。结果需用合理的jsonl格式展示,下面是一个例子。"""

    example_input = """example input:
martial_art_name = 华山剑法
{"招式":"百丈飞瀑"}
{"招式":"百鸟朝凤"}
{"招式":"青山隐隐"}
{"招式":"飞沙走石"}"""

    example_output = """example output:
{"招式":"百丈飞瀑","description":"[player]翻身回剑,剑诀斜引,一招“百丈飞瀑”,剑锋从半空中直泻下来","missing":"[player]一咬牙,翻身回剑,剑诀斜引,一招“百丈飞瀑”,剑锋从半空中直泻下来"}
{"招式":"百鸟朝凤","description":"[player]长剑一起,使一招“百鸟朝凤”,但见剑尖乱颤,霎时间便如化为数十个剑尖,罩住[target]中盘","missing":"[player]使一招“百鸟朝凤”,但见剑尖乱颤,霎时间便如化为数十个剑尖,向[target]飞去"}
{"招式":"青山隐隐", "description":"[player]吸一口气,长剑中宫直进,剑尖不住颤动,剑到中途,忽然转而向上,乃是一招“青山隐隐”,端的是若有若无,变幻无方。","missing":"[player]吸一口气,长剑中宫直进,剑尖不住颤动,剑到中途,忽然转而向上,乃是一招“青山隐隐”,端的是若有若无,变幻无方。"}
{"招式":"飞沙走石", "description":"长剑挺起,使一招“飞沙走石”,内劲直贯剑尖,寒光点点,挡的一声,击中的[target]胸口。","missing":"长剑挺起,使一招“飞沙走石”,内劲直贯剑尖,寒光点点,直向[target]胸口刺去。"}"""

    input = "input:\nmartial_art_name = " + martial_art_name + "\n"
    for m in movements:
        input += f"""{{"招式":"{m}"\}}\n"""

    messages = [
        SystemMessage(content=smart_system_prompt),
        HumanMessage(content=task_message),
        HumanMessage(content=example_input),
        AIMessage(content=example_output),
        HumanMessage(content=input)]

    chat = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.1)

    response = chat(messages)
    return response.content


def generate_skill_jsonl(json_data):
    major_skills = generate_skill_detail(json_data["major_martial_art"], json_data["major_movements"])
    secondary_skills = generate_skill_detail(json_data["secondary_martial_art"], json_data["secondary_movements"])

    all_skills = major_skills + "\n" + secondary_skills

    ans = ""

    lines = all_skills.split("\n")
    for line in lines:
        json_data = robust_parsing(line)
        if json_data is not None:
            json_str = json.dumps(json_data, ensure_ascii=False)
            ans += json_str + "\n"

    return ans


import random


class Player:
    def __init__(self, attr_json, skill_jsonl):
        self.name = attr_json["name"]
        self.STR = attr_json["STR"]
        self.SPD = attr_json["SPD"]
        self.VIT = attr_json["VIT"]
        if "major_damage" in attr_json:
            self.major_damage = attr_json["major_damage"]
        else:
            self.major_damage = 65

        if "secondary_damage" in attr_json:
            self.secondary_damage = attr_json["secondary_damage"]
        else:
            self.secondary_damage = 50

        self.normalize_attr()
        if "hp" in attr_json:
            self.hp = attr_json["hp"]
        else:
            self.hp = (self.VIT + 10) * 30

        if "skills" in attr_json:
            self.skills = attr_json["skills"]
        else:
            self.skills = self.parsing_skill(skill_jsonl)

        self.original_json = attr_json

    def normalize_attr(self):
        max_attr_value = 20
        min_attr_value = 0
        regular_attr_sum = 30
        xs = [self.STR, self.SPD, self.VIT]
        current_sum = 0
        for i in range(3):
            xs[i] = min(max_attr_value, xs[i])
            xs[i] = max(min_attr_value, xs[i])
            current_sum += xs[i]

        if current_sum > regular_attr_sum:
            for i in range(3):
                xs[i] = round(xs[i] * regular_attr_sum / current_sum)
        elif current_sum < regular_attr_sum:
            for i in range(3):
                xs[i] = round(xs[i] * regular_attr_sum / current_sum)

        random_i = random.randint(0, 2)
        xs[random_i] = xs[random_i] + regular_attr_sum - sum(xs)

        self.STR = xs[0]
        self.SPD = xs[1]
        self.VIT = xs[2]

    def get_new_json(self):
        new_json = self.original_json
        new_json["STR"] = self.STR
        new_json["SPD"] = self.SPD
        new_json["VIT"] = self.VIT
        new_json["hp"] = self.hp
        new_json["skills"] = self.skills
        return new_json

    def parsing_skill(self, skill_jsonl):
        skills = []
        lines = skill_jsonl.split("\n")
        for line in lines:
            if line.strip() == "":
                continue
            skill = json.loads(line)
            skills.append(skill)
        return skills


hit_map = {30: 131, 31: 131, 32: 131, 33: 131, 34: 131, 35: 120, 36: 112, 37: 107, 38: 103, 39: 100, 40: 97, 41: 95,
           42: 93, 43: 91, 44: 89, 45: 87, 46: 86, 47: 85, 48: 83, 49: 82, 50: 81, 51: 80, 52: 79, 53: 78, 54: 77,
           55: 76, 56: 75, 57: 74, 58: 73, 59: 72, 60: 71, 61: 70, 62: 69, 63: 69, 64: 68, 65: 67, 66: 66, 67: 65,
           68: 65, 69: 64, 70: 63, 71: 63, 72: 62, 73: 61, 74: 61, 75: 60, 76: 59, 77: 59, 78: 58, 79: 58, 80: 57,
           81: 57, 82: 56, 83: 55, 84: 55, 85: 54, 86: 54, 87: 53, 88: 53, 89: 52, 90: 52, 91: 52, 92: 51, 93: 51,
           94: 50, 95: 50, 96: 49, 97: 49, 98: 49, 99: 48, 100: 48, 101: 47, 102: 47, 103: 47, 104: 46, 105: 46,
           106: 46, 107: 45, 108: 45, 109: 44, 110: 44, 111: 44, 112: 43, 113: 43, 114: 43, 115: 43, 116: 42, 117: 42,
           118: 42, 119: 41, 120: 41, 121: 41, 122: 40, 123: 40, 124: 40, 125: 40, 126: 39, 127: 39, 128: 39, 129: 39,
           130: 38, 131: 38, 132: 38, 133: 38, 134: 37, 135: 37, 136: 37, 137: 37, 138: 36, 139: 36, 140: 36, 141: 36,
           142: 36, 143: 35, 144: 35, 145: 35, 146: 35, 147: 34, 148: 34, 149: 34, 150: 34, 151: 34, 152: 33, 153: 33,
           154: 33, 155: 33, 156: 33, 157: 33, 158: 32, 159: 32, 160: 32, 161: 32, 162: 32, 163: 31, 164: 31, 165: 31,
           166: 31, 167: 31, 168: 31, 169: 30, 170: 30, 171: 30, 172: 30, 173: 30, 174: 30, 175: 30, 176: 29, 177: 29,
           178: 29, 179: 29, 180: 29}

min_damage = 34
max_damage = 180


class GameManager:
    def __init__(self, attr_json1, attr_json2, skill_jsonl1, skill_jsonl2):
        self.player1 = Player(attr_json1, skill_jsonl1)
        self.player2 = Player(attr_json2, skill_jsonl2)

    def run(self):
        speed_diff = self.player1.SPD - self.player2.SPD
        if speed_diff == 0:
            speed_diff = random.randint(0, 3) * 2 - 3

        skill_id_1 = random.randint(0, len(self.player1.skills) - 1)
        dmg_1 = 60
        if skill_id_1 + skill_id_1 < len(self.player1.skills):
            dmg_1 = self.player1.major_damage
        else:
            dmg_1 = self.player1.secondary_damage

        skill_1_to_2 = self.player1.skills[skill_id_1]
        skill_1_to_2["dmg"] = dmg_1

        skill_id_2 = random.randint(0, len(self.player2.skills) - 1)
        dmg_2 = 60
        if skill_id_2 + skill_id_2 < len(self.player2.skills):
            dmg_2 = self.player2.major_damage
        else:
            dmg_2 = self.player2.secondary_damage

        skill_2_to_1 = self.player2.skills[skill_id_2]
        skill_2_to_1["dmg"] = dmg_2

        # skill_2_to_1 = random.choice(self.player2.skills)

        # print(skill_1_to_2)
        # print(skill_2_to_1)

        damage_1_to_2 = self.compute_damage(skill_1_to_2, self.player1, self.player2)
        damage_2_to_1 = self.compute_damage(skill_2_to_1, self.player2, self.player1)

        ratio_1_to_2 = self.compute_ratio(skill_1_to_2, self.player1, self.player2)
        ratio_2_to_1 = self.compute_ratio(skill_2_to_1, self.player2, self.player1)

        if_hitted_1_to_2 = random.random() * 100.0 < ratio_1_to_2
        if_hitted_2_to_1 = random.random() * 100.0 < ratio_2_to_1

        desc_1_to_2 = skill_1_to_2["description"] if if_hitted_1_to_2 else skill_1_to_2["missing"]
        desc_1_to_2 = desc_1_to_2.replace("[player]", self.player1.name).replace("[target]", self.player2.name)

        if if_hitted_1_to_2:
            desc_1_to_2 += f"造成了{round(damage_1_to_2)}的伤害。"
        else:
            desc_1_to_2 += f"{self.player2.name}躲了过去"

        desc_2_to_1 = skill_2_to_1["description"] if if_hitted_2_to_1 else skill_2_to_1["missing"]
        desc_2_to_1 = desc_2_to_1.replace("[player]", self.player2.name).replace("[target]", self.player1.name)
        if if_hitted_2_to_1:
            desc_2_to_1 += f"造成了{round(damage_2_to_1)}的伤害。"
        else:
            desc_2_to_1 += f"{self.player1.name}躲了过去"

        self.flag = "continue"

        ans_msg = []

        if self.player2.hp <= 0:
            ans_msg.append((None, f"{self.player2.name}战败了"))
            return ans_msg, self.player1.get_new_json(), self.player2.get_new_json()

        if self.player1.hp <= 0:
            ans_msg.append((f"{self.player1.name}战败了", None))
            return ans_msg, self.player1.get_new_json(), self.player2.get_new_json()

        if speed_diff > 0:
            if if_hitted_1_to_2:
                self.player2.hp -= damage_1_to_2

            ans_msg.append((desc_1_to_2, None))

            if self.player2.hp > 0 and if_hitted_2_to_1:
                self.player1.hp -= damage_2_to_1

            if self.player2.hp > 0:
                ans_msg.append((None, desc_2_to_1))

        else:
            if if_hitted_2_to_1:
                self.player1.hp -= damage_2_to_1

            ans_msg.append((None, desc_2_to_1))

            if self.player1.hp > 0 and if_hitted_1_to_2:
                self.player2.hp -= damage_1_to_2

            if self.player1.hp > 0:
                ans_msg.append((desc_1_to_2, None))

        if self.player2.hp <= 0:
            ans_msg.append((None, f"{self.player2.name}战败了"))
            self.flag = "player1_win"
        if self.player1.hp <= 0:
            ans_msg.append((f"{self.player1.name}战败了", None))
            self.flag = "player2_win"

        return ans_msg, self.player1.get_new_json(), self.player2.get_new_json()

    # default "damage": 60, "hit": 76,
    def compute_damage(self, skill, player, target):
        damage_ratio = skill["dmg"]
        damage_ratio = max(min_damage, damage_ratio)
        damage_ratio = min(max_damage, min_damage)
        skill_damage = damage_ratio + player.STR * 2
        attack_diff = player.STR - target.VIT * 0.5
        damage = skill_damage * (1 + 0.95 * (-0.5 + 1.0 / (1.0 + exp(-attack_diff / 6.0))))
        return damage

    def compute_ratio(self, skill, player, target):
        damage_ratio = skill["dmg"]
        damage_ratio = round(damage_ratio)
        damage_ratio = max(min_damage, damage_ratio)
        damage_ratio = min(max_damage, min_damage)
        skill_hit = hit_map[damage_ratio]

        speed_diff = player.SPD - target.SPD
        hit_factor = (-0.5 + 1.0 / (1.0 + exp(-speed_diff / 6.0))) / 2.0 * max(30.0, skill_hit)
        return hit_factor + skill_hit


fighter_save_name = 'LuotuoFighter.txt'

import os

datas = []

if not os.path.exists(fighter_save_name):
    data = {
        "name": "李鲁鲁",
        "attr_str": attr_lilulu,
        "skills": skill_lilulu
    }
    datas.append(data)
    data = {
        "name": "冷子昂",
        "attr_str": attr_lengziang,
        "skills": skill_lengziang
    }
    datas.append(data)
    data = {
        "name": "黄蓉",
        "attr_str": json_str_huangrong,
        "skills": skill_huangrong
    }
    datas.append(data)
    with open(fighter_save_name, 'w', encoding="utf-8") as f:
        for data in datas:
            f.write(json.dumps(data, ensure_ascii=False) + "\n")
else:
    with open(fighter_save_name, 'r', encoding="utf-8") as f:
        for line in f.readlines():
            data = json.loads(line)
            datas.append(data)

fighter_data = datas

elo_table = {}


def get_unique_from_data(data):
    name = data["name"]
    json_data = json.loads(data["attr_str"])
    return get_unique_from_json(name, json_data)


def get_unique_from_json(name, json_data):
    if "STR" in json_data and "VIT" in json_data and "SPD" in json_data and "major_damage" in json_data and "secondary_damage" in json_data:
        return name + "_" + str(json_data["major_damage"]) + "_" + str(json_data["secondary_damage"])
    else:
        return None


unique_to_score = {}
name_to_top_unique = {}

from math import exp

elo_start = 1200
elo_K = 15

for data in fighter_data:
    unique_name = get_unique_from_data(data)
    score = elo_start
    unique_to_score[unique_name] = elo_start
    name = data["name"]

    name_to_top_unique[name] = unique_name


def get_rank_str(top_n=20):
    global unique_to_score
    global name_to_top_unique

    score_name_pair = []
    for name in name_to_top_unique:
        unique = name_to_top_unique[name]
        score = unique_to_score[unique]
        score_name_pair.append((unique, score))

    top_n = min(top_n, len(name_to_top_unique))
    score_name_pair.sort(key=lambda x: x[1], reverse=True)
    ans = ""
    for i in range(top_n):
        name = score_name_pair[i][0].split("_")[0]
        ans += f"第{i + 1}名" + name + " - " + str(round(score_name_pair[i][1])) + " | "

    return ans


def update_elo(winner_unique, loser_unique):
    print(winner_unique + " wins " + loser_unique)
    update_winner = True
    update_loser = True

    global unique_to_score
    global name_to_top_unique

    if winner_unique not in unique_to_score:
        unique_to_score[winner_unique] = elo_start
        update_loser = False

    if loser_unique not in unique_to_score:
        unique_to_score[loser_unique] = elo_start

    Ra = unique_to_score[winner_unique]
    Rb = unique_to_score[loser_unique]

    Ea = 1 / (1 + exp((Rb - Ra) / 400))
    Eb = 1 / (1 + exp((Ra - Rb) / 400))
    Sa = 1
    Sb = 0
    unique_to_score[winner_unique] = Ra + elo_K * (Sa - Ea)
    unique_to_score[loser_unique] = Rb + elo_K * (Sb - Eb)

    winner_name = winner_unique.split("_")[0]

    if winner_name not in name_to_top_unique:
        name_to_top_unique[winner_name] = winner_unique

    winner_unique_on_rank = name_to_top_unique[winner_name]
    if unique_to_score[winner_unique] > unique_to_score[winner_unique_on_rank]:
        name_to_top_unique[winner_name] = winner_unique


def get_random_fighter():
    global fighter_data
    return random.choice(fighter_data)


def searching_fighter(name):
    global fighter_data
    for data in fighter_data:
        if data["name"] == name:
            return data
    return get_random_fighter()


def add_fighter(attr_json_str, skill_jsonl):
    attr_json = json.loads(attr_json_str)
    if "skills" in attr_json:
        del attr_json["skills"]
    if "hp" in attr_json:
        del attr_json["hp"]

    new_attr_json_str = json.dumps(attr_json, ensure_ascii=False)

    global fighter_data
    name = attr_json["name"]

    data = {
        "name": name,
        "attr_str": new_attr_json_str,
        "skills": skill_jsonl
    }
    fighter_data.append(data)
    print(json.dumps(data, ensure_ascii=False))
    with open(fighter_save_name, 'a', encoding="utf-8") as f:
        f.write(json.dumps(data, ensure_ascii=False) + "\n")


def searching_fighter_on_elo(name):
    global fighter_data
    global name_to_top_unique

    if name in name_to_top_unique:
        top_unique = name_to_top_unique[name]
        for data in fighter_data:
            if get_unique_from_data(data) == top_unique:
                return data
        return searching_fighter(name)
    else:
        return searching_fighter(name)


import gradio as gr


def get_attr_str_short(attr_json):
    if "hp" in attr_json:
        ans = "血量:" + str(attr_json["hp"]) + "\n"
    else:
        ans = ""
    ans += "力量:" + str(attr_json["STR"]) + "\n体质:" + str(attr_json["VIT"]) + "\n速度:" + str(attr_json["SPD"])
    return ans


def get_skill_str_short(attr_json):
    ans = attr_json["major_martial_art"] + ":\n"
    for skill in attr_json["major_movements"]:
        ans += skill + "-"
    ans += "\n" + attr_json["secondary_martial_art"] + ":\n"
    for skill in attr_json["secondary_movements"]:
        ans += skill + "-"
    ans += "\n 防御:" + attr_json["footwork_and_body_method"]
    return ans


def generate_ma(name, desc, display_board):
    if name.strip() == "":
        return "", "", "", "", display_board, "角色名不能为空,输入角色名后生成功法或者创建角色"

    status = "请为角色进一步生成详细功法"

    role_detail = ma_foo_answer

    if name == "李鲁鲁":
        json_answer = json.loads(attr_lilulu)
    elif name == "冷子昂":
        json_answer = json.loads(attr_lengziang)
    else:
        role_detail = generate_detailed_description(name, desc)
        json_str = generate_attr_json(name, desc, role_detail)
        json_answer = robust_parsing(json_str)

    json_answer_str = json.dumps(json_answer, ensure_ascii=False)

    skill_desc = get_skill_str_short(json_answer)

    display_board.append(("生成人物" + json_answer["name"] + "\n" + skill_desc, None))

    return role_detail, json_answer_str, get_attr_str_short(json_answer), skill_desc, display_board, status


def generate_madetail(player_attribute, display_board):
    if player_attribute.strip() == "":
        return "", display_board, "需要生成武功名称,再生成描述。或者直接随机召唤角色"

    status = "确认两个角色都生成之后,可以进入战斗"

    json_answer = json.loads(player_attribute)

    generate_flag = False

    ans = skill_foo_desc
    if json_answer["name"] == "李鲁鲁":
        ans = skill_lilulu
    elif json_answer["name"] == "冷子昂":
        ans = skill_lengziang
    else:
        ans = generate_skill_jsonl(json_answer)
        generate_flag = True

    display_board.append(("为" + json_answer["name"] + "生成详细的功法描述\n", None))

    if generate_flag:
        player = Player(json_answer, ans)
        unique_name = get_unique_from_json(json_answer["name"], json_answer)
        if len(player.skills) > 1 and unique_name != None:
            add_fighter(player_attribute, ans)
            display_board.append(("将新角色" + json_answer["name"] + "录入到数据库\n", None))

    return ans, display_board, status


def continue_fight(detailed_attr_player1, detailed_attr_player2, detailed_skill_player1, detailed_skill_player2,
                   display_board):
    if detailed_attr_player1.strip() == "" or detailed_attr_player2.strip() == "" or detailed_skill_player1.strip() == "" or detailed_skill_player2.strip() == "":
        str1 = ""
        if detailed_attr_player1.strip() != "":
            str1 = get_attr_str_short(json.loads(detailed_attr_player1))
        str2 = ""
        if detailed_attr_player2.strip() != "":
            str2 = get_attr_str_short(json.loads(detailed_attr_player2))
        return detailed_attr_player1, detailed_attr_player2, display_board, str1, str2, "请重新检查人物的生成情况"

    json1 = json.loads(detailed_attr_player1)
    json2 = json.loads(detailed_attr_player2)
    name1 = json1["name"]
    name2 = json2["name"]

    status = f"""{name1} 大战 {name2}"""

    if "hp" in json1 and "hp" in json2:
        if json1["hp"] <= 0 and json1["hp"] < json2["hp"]:
            unique1 = get_unique_from_json(name1, json1)
            unique2 = get_unique_from_json(name2, json2)
            return detailed_attr_player1, detailed_attr_player2, display_board, "", "", "战斗结束!请清除战斗或者重新生成人物"

        if json2["hp"] <= 0 and json2["hp"] < json1["hp"]:
            unique1 = get_unique_from_json(name1, json1)
            unique2 = get_unique_from_json(name2, json2)
            return detailed_attr_player1, detailed_attr_player2, display_board, "", "", "战斗结束!请清除战斗或者重新生成人物"

    game_manager = GameManager(json1, json2, detailed_skill_player1, detailed_skill_player2)
    msgs, new_player1, new_player2 = game_manager.run()
    for msg in msgs:
        display_board.append(msg)

    if game_manager.flag == "player1_win":
        unique1 = get_unique_from_json(name1, json1)
        unique2 = get_unique_from_json(name2, json2)
        update_elo(unique1, unique2)
    elif game_manager.flag == "player2_win":
        unique1 = get_unique_from_json(name1, json1)
        unique2 = get_unique_from_json(name2, json2)
        update_elo(unique2, unique1)

    new_player1_str = json.dumps(new_player1, ensure_ascii=False)
    new_player2_str = json.dumps(new_player2, ensure_ascii=False)

    return new_player1_str, new_player2_str, display_board, get_attr_str_short(new_player1), get_attr_str_short(
        new_player2), status


def callback_random_role(display_board):
    data = get_random_fighter()
    name = data["name"]
    json_str = data["attr_str"]
    skills_jsonl = data["skills"]
    json_answer = json.loads(json_str)
    display_board.append(("从数据库选择角色" + name, None))
    return name, json_str, skills_jsonl, get_attr_str_short(json_answer), get_skill_str_short(
        json_answer), display_board


def callback_role_from_name(display_board, name):
    data = searching_fighter_on_elo(name)
    json_str = data["attr_str"]
    skills_jsonl = data["skills"]
    json_answer = json.loads(json_str)
    display_board.append(("从数据库选择角色" + name, None))
    return name, json_str, skills_jsonl, get_attr_str_short(json_answer), get_skill_str_short(
        json_answer), display_board


def callback_clean_fight(display_board, detailed_attr_player1, detailed_attr_player2):
    display_board = []
    json1 = json.loads(detailed_attr_player1)
    json2 = json.loads(detailed_attr_player2)
    if "hp" in json1:
        del json1["hp"]
    if "hp" in json2:
        del json2["hp"]

    new_detailed_attr_player1 = json.dumps(json1, ensure_ascii=False)
    new_detailed_attr_player2 = json.dumps(json2, ensure_ascii=False)

    return display_board, new_detailed_attr_player1, new_detailed_attr_player2


def callback_refresh_rank():
    return get_rank_str()


with gr.Blocks() as demo:
    gr.Markdown(
        """
        # LuotuoFighter

        ## 骆驼大乱斗

        Implemented by 李鲁鲁

        项目链接 https://github.com/LC1332/Chat-Haruhi-Suzumiya

        这个原型是为了百川Hackathon而初步建立

        三种角色建立方式: 根据姓名召唤、随机召唤,或者输入姓名和描述后生成新的人物
        姓名召唤会召唤同名人物中战力最强的那个
        由于Gradio特性,建立角色要花个几十秒,先点击生成功法,再点击生成功法描述
        """
    )

    with gr.Row():
        with gr.Column():
            current_status = gr.Textbox(label="当前状态", value="请输入角色1的姓名之后生成功法,或进行召唤")

            display_board = gr.Chatbot(height=800)

            submit_fight2 = gr.Button("继续战斗!")
            clean_fight = gr.Button("清空战斗")

        with gr.Column():
            with gr.Row():
                name_player1 = gr.Textbox(label="角色1姓名", scale=1, interactive=True, value="李鲁鲁")
                desc_player1 = gr.Textbox(label="角色1描述", scale=20, value="师从,主修剑法", interactive=True)

            with gr.Row():
                generate_ma_player1 = gr.Button("生成功法")
                generate_madetail_player1 = gr.Button("生成功法描述")

            with gr.Row():
                random_sel_player1 = gr.Button("随机召唤")
                call_player1_with_name1 = gr.Button("根据姓名召唤")

            with gr.Row():
                name_player2 = gr.Textbox(label="角色2姓名", scale=1, interactive=True, value="冷子昂")
                desc_player2 = gr.Textbox(label="角色2描述", scale=20, value="师从,主修剑法", interactive=True)
            with gr.Row():
                generate_ma_player2 = gr.Button("生成功法")
                generate_madetail_player2 = gr.Button("生成功法描述")

            with gr.Row():
                random_sel_player2 = gr.Button("随机召唤2")
                call_player1_with_name2 = gr.Button("根据姓名召唤2")

            with gr.Row():
                submit_fight = gr.Button("继续战斗!")

            with gr.Row():
                attr_player1 = gr.TextArea(label="角色1属性")
                skill_player1 = gr.TextArea(label="角色1功法描述")

            with gr.Row():
                attr_player2 = gr.TextArea(label="角色2属性")
                skill_player2 = gr.TextArea(label="角色2功法描述")

            with gr.Row():
                refresh_rank = gr.Button("刷新天梯")

    with gr.Row():
        rank_showboard = gr.TextArea(label="天梯")

    with gr.Row():
        with gr.Column():
            detailed_description_player1 = gr.TextArea(label="角色1具体描述")
            detailed_skill_player1 = gr.TextArea(label="角色1技能json")
            detailed_attr_player1 = gr.TextArea(label="角色1属性json")

        with gr.Column():
            detailed_description_player2 = gr.TextArea(label="角色2具体描述")
            detailed_skill_player2 = gr.TextArea(label="角色2技能json")
            detailed_attr_player2 = gr.TextArea(label="角色2属性json")

    generate_ma_player1.click(fn=generate_ma, inputs=[name_player1, desc_player1, display_board],
                              outputs=[detailed_description_player1, detailed_attr_player1, attr_player1, skill_player1,
                                       display_board, current_status])
    generate_ma_player2.click(fn=generate_ma, inputs=[name_player2, desc_player2, display_board],
                              outputs=[detailed_description_player2, detailed_attr_player2, attr_player2, skill_player2,
                                       display_board, current_status])
    generate_madetail_player1.click(fn=generate_madetail, inputs=[detailed_attr_player1, display_board],
                                    outputs=[detailed_skill_player1, display_board, current_status])
    generate_madetail_player2.click(fn=generate_madetail, inputs=[detailed_attr_player2, display_board],
                                    outputs=[detailed_skill_player2, display_board, current_status])

    random_sel_player1.click(fn=callback_random_role, inputs=[display_board],
                             outputs=[name_player1, detailed_attr_player1, detailed_skill_player1, attr_player1,
                                      skill_player1, display_board])
    random_sel_player2.click(fn=callback_random_role, inputs=[display_board],
                             outputs=[name_player2, detailed_attr_player2, detailed_skill_player2, attr_player2,
                                      skill_player2, display_board])

    call_player1_with_name1.click(fn=callback_role_from_name, inputs=[display_board, name_player1],
                                  outputs=[name_player1, detailed_attr_player1, detailed_skill_player1, attr_player1,
                                           skill_player1, display_board])
    call_player1_with_name2.click(fn=callback_role_from_name, inputs=[display_board, name_player2],
                                  outputs=[name_player2, detailed_attr_player2, detailed_skill_player2, attr_player2,
                                           skill_player2, display_board])

    refresh_rank.click(fn=callback_refresh_rank, inputs=[], outputs=[rank_showboard])

    clean_fight.click(fn=callback_clean_fight, inputs=[display_board, detailed_attr_player1, detailed_attr_player2],
                      outputs=[display_board, detailed_attr_player1, detailed_attr_player2])

    submit_fight.click(fn=continue_fight,
                       inputs=[detailed_attr_player1, detailed_attr_player2, detailed_skill_player1,
                               detailed_skill_player2, display_board],
                       outputs=[detailed_attr_player1, detailed_attr_player2, display_board, attr_player1, attr_player2,
                                current_status])

    submit_fight2.click(fn=continue_fight,
                        inputs=[detailed_attr_player1, detailed_attr_player2, detailed_skill_player1,
                                detailed_skill_player2, display_board],
                        outputs=[detailed_attr_player1, detailed_attr_player2, display_board, attr_player1,
                                 attr_player2, current_status])

demo.launch(debug=False, share=True)