-
Notifications
You must be signed in to change notification settings - Fork 3
/
newkf.cpp
5522 lines (5349 loc) · 179 KB
/
newkf.cpp
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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <vector>
#include <queue>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
uint64_t crc64r(const void* ptr, size_t size, uint64_t crc = 0xFFFFFFFFFFFFFFFFULL)
{
static uint64_t sCrcTable[256];
static bool init = false;
if (!init)
{
for (int i = 0; i < 256; ++i)
{
uint64_t n = i;
for (int j = 0; j < 8; ++j)
{
n = (n >> 1) ^ (n & 1 ? 0x95AC9329AC4BC9B5ULL : 0ULL);
}
sCrcTable[i] = n;
}
init = true;
}
const unsigned char* buffer = reinterpret_cast<const unsigned char*>(ptr);
for (size_t i = 0; i < size; ++i)
{
crc = sCrcTable[(crc ^ buffer[i]) & 0xFFU] ^ (crc >> 8);
}
return crc;
}
enum
{
ROLE_NPC = 0,
ROLE_MU = 0, // 铁皮木人
ROLE_ZHU, // 嗜血的迅捷蛛
ROLE_DENG, // 魔灯之灵
ROLE_SHOU, // 戆戆的食铁兽
ROLE_MU2, // 铁皮木人(新版)
ROLE_ZHU2, // 迅捷魔蛛(新版)
ROLE_DENG2, // 魔灯之灵(新版)
ROLE_SHOU2, // 食铁兽(新版)
ROLE_YU2, // 六眼飞鱼(新版)
ROLE_HAO2, // 晶刺豪猪(新版)
ROLE_LIU, // 六边形战士
ROLE_SHI, // 史莱姆
NPC_COUNT_OLD = 4,
NPC_COUNT_OLD2 = 10,
NPC_COUNT = 12,
ROLE_PC = 20,
ROLE_MO = 20, // 默
ROLE_LIN, // 琳
ROLE_AI, // 艾
ROLE_MENG, // 梦
ROLE_WEI, // 薇
ROLE_YI, // 伊
ROLE_MING, // 冥
ROLE_MIN, // 命
ROLE_WU, // 舞
ROLE_XI, // 希
ROLE_XIA, // 霞
ROLE_YA, // 雅
PC_COUNT = 12,
ATTR_STR = 0, // 力量
ATTR_AGI, // 敏捷
ATTR_INT, // 智力
ATTR_VIT, // 体魄
ATTR_SPR, // 精神
ATTR_MND, // 意志
ATTR_COUNT,
GEAR_NONE = 0,
GEAR_SWORD, // 探险者之剑
GEAR_BOW, // 探险者短弓
GEAR_STAFF, // 探险者短杖
GEAR_BLADE, // 狂信者的荣誉之刃
GEAR_ASSBOW, // 反叛者的刺杀弓
GEAR_DAGGER, // 幽梦匕首
GEAR_WAND, // 光辉法杖
GEAR_SHIELD, // 荆棘盾剑
GEAR_CLAYMORE, // 陨铁重剑
GEAR_SPEAR, // 饮血魔剑
GEAR_COLORFUL, // 彩金长剑
GEAR_LIMPIDWAND,// 清澄长杖
GEAR_GLOVES, // 探险者手环
GEAR_BRACELET, // 命师的传承手环
GEAR_VULTURE, // 秃鹫手环
GEAR_RING, // 海星戒指
GEAR_DEVOUR, // 噬魔戒指
GEAR_REFRACT, // 折光戒指
GEAR_PLATE, // 探险者铁甲
GEAR_LEATHER, // 探险者皮甲
GEAR_CLOTH, // 探险者布甲
GEAR_CLOAK, // 旅法师的灵光袍
GEAR_THORN, // 战线支撑者的荆棘重甲
GEAR_WOOD, // 复苏战衣
GEAR_CAPE, // 挑战斗篷
GEAR_SCARF, // 探险者耳环
GEAR_TIARA, // 占星师的耳饰
GEAR_RIBBON, // 萌爪耳钉
GEAR_HUNT, // 猎魔耳环
GEAR_FIERCE, // 凶神耳环
GEAR_COUNT,
AURA_SHI = 0x00000001, // 启程之誓
AURA_XIN = 0x00000002, // 启程之心
// AURA_FENG = 0x00000004, // 启程之风
// AURA_TIAO = 0x00000008, // 等级挑战
// AURA_YA = 0x00000010, // 等级压制
AURA_BI = 0x00000004, // 破壁之心
AURA_MO = 0x00000008, // 破魔之心
AURA_DUN = 0x00000010, // 复合护盾
AURA_XUE = 0x00000020, // 鲜血渴望
AURA_XIAO = 0x00000040, // 削骨之痛
AURA_SHENG = 0x00000080, // 圣盾祝福
AURA_E = 0x00000100, // 恶意抽奖
AURA_SHANG = 0x00000200, // 伤口恶化
AURA_SHEN = 0x00000400, // 精神创伤
AURA_CI = 0x00000800, // 铁甲尖刺
AURA_REN = 0x00001000, // 忍无可忍
AURA_RE = 0x00002000, // 热血战魂
AURA_DIAN = 0x00004000, // 点到为止
AURA_WU = 0x00008000, // 午时已到
AURA_ZHI = 0x00010000, // 纸薄命硬
AURA_SHAN = 0x00020000, // 不动如山
AURA_FEI = 0x00040000, // 沸血之志
AURA_BO = 0x00080000, // 波澜不惊
AURA_JU = 0x00100000, // 飓风之力
AURA_HONG = 0x00200000, // 红蓝双刺
AURA_JUE = 0x00400000, // 荧光护盾
AURA_HOU = 0x00800000, // 后发制人
AURA_DUNH = 0x01000000, // 钝化锋芒
AURA_ZI = 0x02000000, // 自信回头
AURA_ZOU = 0x04000000, // 致命节奏
AURA_PIAO = 0x08000000, // 往返车票
AURA_PEN = 0x10000000, // 天降花盆
AURA_DI = 0x20000000, // 绝对底线(野怪专用)
AURA_COUNT = 30,
FLAG_STAT = 1 << AURA_COUNT,
MYST_BLADE = 0x000001, // 暴击时附带(物理攻击力*50%)的绝对伤害
MYST_ASSBOW = 0x000002, // 攻击附带(对方当前护盾值*30%)的物理伤害
MYST_DAGGER = 0x000004, // 星火宝石的效果翻倍 血精宝石的伤害提升(星火*15%)
MYST_WAND = 0x000008, // 魔力压制增加40%技能伤害,第一击必释放技能
MYST_SHIELD = 0x000010, // 削弱对方40%的回血和回盾效果
MYST_CLAYMORE = 0x000020, // 暴击率100%
MYST_SPEAR = 0x000040, // 攻击附带(对方当前生命值*30%)的魔法伤害
MYST_COLORFUL = 0x000080, // 彩金对剑无视对方情况同时附带物理和魔法伤害
MYST_LIMPIDWAND = 0x000100, // 澄空之心额外获得(15%对方魔法防御)的魔法附加穿透。
MYST_BRACELET = 0x000200, // 20%几率特殊暴击,魔法伤害增加100%
MYST_VULTURE = 0x000400, // 额外增加20%对护盾的实际吸血给生命值
MYST_RING = 0x000800, // 舞增加(锦上添花伤害的20%)的普通伤害
MYST_DEVOUR = 0x001000, // 命运链接获得的护盾回复的50%添加到生命回复
MYST_REFRACT = 0x002000, // 攻击满血满盾的对手会恢复先兆感知
MYST_CLOAK = 0x004000, // 护盾最大值+50%
MYST_THORN = 0x008000, // 增加25%固定伤害反弹
MYST_WOOD = 0x010000, // 被攻击时回复(5%自身最大生命值)
MYST_CAPE = 0x020000, // 被攻击回合时攻击方50%的物理伤害转换为魔法伤害
MYST_TIARA = 0x040000, // 星芒之盾的护盾最大值提升至45%,减速效果提升至4%
MYST_RIBBON = 0x080000, // 锁定元气无限为低于30%血量判定。
MYST_HUNT = 0x100000, // 圣银弩箭30%物理攻击转换为绝对伤害
MYST_FIERCE = 0x200000, // 同时拥有白天和夜晚的技能效果
PREF_SHANG = 0, // 诅咒=伤口恶化+精神创伤
PREF_BO, // 法神=破魔之心+波澜不惊
PREF_FEI, // 战神=破壁之心+沸血之志
PREF_HOU, // 隐忍=忍无可忍+后发制人
PREF_JU, // 疯狂=热血战魂+飓风之力
PREF_HONG, // 刺痛=削骨之痛+红蓝双刺
PREF_DIAN, // 坚韧=圣盾祝福+点到为止
PREF_CI, // 尖刺=鲜血渴望+铁甲尖刺
PREF_JUE, // 防盾=复合护盾+荧光护盾
PREF_COUNT,
WISH_HP_POT = 0, // 生命药水 生命低于??%时回复0.5%*W的生命值 最大100
WISH_SLD_POT, // 护盾药水 护盾低于??%时回复0.5%*W的护盾值 最大100
WISH_SHI_BUF, // 启程之誓强化 效果增加5%*W倍 最大100
WISH_XIN_BUF, // 启程之心强化 效果增加5%*W倍 最大100
WISH_FENG_BUF, // 启程之风强化 效果增加5%*W倍 最大100
WISH_PATKA, // 附加物伤增加5*W 最大3000
WISH_MATKA, // 附加魔伤增加5*W 最大3000
WISH_HPM, // 附加生命增加12*W 最大3000
WISH_SLDM, // 附加护盾增加20*W 最大3000
WISH_SPDA, // 附加攻速增加W 最大500
WISH_PBRCA, // 物理附加穿透增加W 最大500
WISH_MBRCA, // 魔法附加穿透增加W 最大500
WISH_PDEFA, // 物理附加防御增加W 最大500
WISH_MDEFA, // 魔法附加防御增加W 最大500
WISH_COUNT,
AMUL_STR = 0, // 力量
AMUL_AGI, // 敏捷
AMUL_INT, // 智力
AMUL_VIT, // 体魄
AMUL_SPR, // 精神
AMUL_MND, // 意志
AMUL_PATK, // 物理攻击
AMUL_MATK, // 魔法攻击
AMUL_SPD, // 攻击速度
AMUL_REC, // 回复效果
AMUL_HP, // 最大生命
AMUL_SLD, // 最大护盾
AMUL_LCH, // 生命偷取
AMUL_RFL, // 伤害反弹
AMUL_CRT, // 暴击几率
AMUL_SKL, // 技能几率
AMUL_PDEF, // 物理防御
AMUL_MDEF, // 魔法防御
AMUL_AAA, // 全属性
AMUL_CRTR, // 暴击抵抗
AMUL_SKLR, // 技能抵抗
AMUL_COUNT,
};
struct BStat
{
int role; // 角色类型
int lvl; // 等级
double hp; // 当前生命
double hpM; // 最大生命
int hpRecP; // 百分比生命回复
double hpRecA; // 附加生命回复
int hpRecRR; // 生命回复减少率(百分比)
double pAtkB; // 基础物理攻击
double pAtkA; // 附加物理攻击
double mAtkB; // 基础魔法攻击
double mAtkA; // 附加魔法攻击
double aAtk; // 绝对攻击
double spdB; // 基础攻击速度
double spdA; // 附加攻击速度
int spdRR; // 减速倍率(百分比)
double spdC; // 速度计数
double pBrcP; // 百分比物理穿透
double pBrcA; // 附加物理穿透
double mBrcP; // 百分比魔法穿透
double mBrcA; // 附加魔法穿透
double sRateB; // 技能释放基数
double sRateP; // 技能释放率
double sRateR; // 技能释放率倍率
double cRateB; // 暴击释放基数
double cRateP; // 暴击释放率
double cBrcP; // 百分比暴击穿透
double lchP; // 百分比生命偷取
double pDefB; // 基础物理防御
double pDefA; // 附加物理防御
double mDefB; // 基础魔法防御
double mDefA; // 附加魔法防御
double pRdc; // 物理减伤
double mRdc; // 魔法减伤
double sld; // 当前护盾
double sldM; // 最大护盾
int sldRecP; // 百分比护盾回复
double sldRecA; // 附加护盾回复
int sldRecRR; // 护盾回复减少率(百分比)
double rflP; // 百分比伤害反弹
int cDef; // 基础暴击抵抗
int sDef; // 基础技能防御
int psvSkl; // 被动技能组合(光环、flag)
int myst; // 神秘属性组合
int sklC; // 角色技能计数(星火、星芒、神秘法杖的初次技能、闪避充能、成长值、蛛网)
int houC; // 后发制人计数
uint16_t wish[WISH_COUNT]; // 许愿池点数
uint8_t amul[AMUL_COUNT]; // 护身符点数
bool hpPot; // 生命药水是否已使用
bool sldPot; // 护盾药水是否已使用
bool ziFlag; // 自信回头是否已发动
bool minFlag; // 先兆感知是否存在
bool piaoFlag; // 往返车票的复活是否已发动
int growth; // 成长值
int pAtkR; // 物理攻击增加率(百分比)
int mAtkR; // 魔法攻击增加率(百分比)
int hpMR; // 最大生命值增加率(百分比)
int sldMR; // 最大护盾值增加率(百分比)
int tStr; // 力量加点
int tAgi; // 敏捷加点
int tInt; // 智力加点
int tVit; // 体魄加点
int tSpr; // 精神加点
int tMnd; // 意志加点
int mode; // 雅状态 0白天1黑夜2凶神
int atkLvl; // 进攻等级
int defLvl; // 防御等级
double hpS; // 回合开始时最大生命
double sldS; // 回合开始时最大护盾
std::string alias;
};
struct Gear
{
int type;
int lvl;
int percent[4];
bool isMyst;
};
struct NonPlayer
{
int role;
int lvl;
int prefixCount;
int prefix;
};
struct Player
{
int role;
int lvl;
int kfLvl;
int sklSlot;
int quality;
int growth;
int mode;
int attr[ATTR_COUNT];
int auraSkl;
Gear gear[4];
uint16_t wish[WISH_COUNT];
uint8_t amul[AMUL_COUNT];
int type;
double weight;
std::string alias;
BStat* pBStat;
};
const char* const npcName[NPC_COUNT] = { "MU", "ZHU", "DENG", "SHOU", "MU2", "ZHU2", "DENG2", "SHOU2", "YU2", "HAO2", "LIU", "SHI" };
const char* const pcName[PC_COUNT] = { "MO", "LIN", "AI", "MENG", "WEI", "YI", "MING", "MIN", "WU", "XI", "XIA", "YA" };
const char* const gearName[GEAR_COUNT] = {
"NONE", "SWORD", "BOW", "STAFF", "BLADE", "ASSBOW", "DAGGER", "WAND", "SHIELD",
"CLAYMORE", "SPEAR", "COLORFUL", "LIMPIDWAND", "GLOVES", "BRACELET", "VULTURE", "RING", "DEVOUR", "REFRACT",
"PLATE", "LEATHER", "CLOTH", "CLOAK", "THORN", "WOOD", "CAPE", "SCARF", "TIARA", "RIBBON", "HUNT", "FIERCE" };
const int gearSlot[GEAR_COUNT] = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3 };
const char* const auraName[AURA_COUNT] = {
"SHI", "XIN",
"BI", "MO", "DUN", "XUE", "XIAO", "SHENG", "E",
"SHANG", "SHEN", "CI", "REN", "RE", "DIAN", "WU", "ZHI", "SHAN",
"FEI", "BO", "JU", "HONG", "JUE", "HOU", "DUNH", "ZI",
"ZOU", "PIAO", "PEN",
"DI" };
const int auraCost[AURA_COUNT] = {
0, 0,
20, 20, 20, 20, 20, 20, 20,
30, 30, 30, 30, 30, 30, 30, 30, 30,
100, 100, 100, 100, 100, 100, 100, 100,
120, 120, 120,
0 };
int auraRandCount = 1;
int wishMax[WISH_COUNT] = { 100, 100, 100, 100, 100, 3000, 3000, 3000, 3000, 500, 500, 500, 500, 500 };
const char* const prefName[PREF_COUNT] = {
"SHANG", "BO", "FEI", "HOU", "JU", "HONG", "DIAN", "CI", "JUE" };
const int prefAura[PREF_COUNT] = {
AURA_SHANG | AURA_SHEN, AURA_MO | AURA_BO, AURA_BI | AURA_FEI,
AURA_REN | AURA_HOU, AURA_RE | AURA_JU, AURA_XIAO | AURA_HONG,
AURA_SHENG | AURA_DIAN, AURA_XUE | AURA_CI, AURA_DUN | AURA_JUE };
int prefCount[1 << PREF_COUNT][5];
int prefTable[1 << PREF_COUNT][5][PREF_COUNT * (PREF_COUNT - 1) * (PREF_COUNT - 2) * (PREF_COUNT - 3) / 24];
const char* const amulName[AMUL_COUNT] = {
"STR", "AGI", "INT", "VIT", "SPR", "MND",
"PATK", "MATK", "SPD", "REC", "HP", "SLD",
"LCH", "RFL", "CRT", "SKL", "PDEF", "MDEF", "AAA", "CRTR", "SKLR" };
const int profitRate[4] = { 2, 3, 4, 6 }; // *50%
double sklRate[NPC_COUNT][2] = { {1.0, 1.0}, {3.0, 1.0}, {8.0, 1.0}, {1.0, 1.0},
{2.0, 1.0}, {5.0, 2.0}, {8.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0},
{1.0, 1.0},
{4.0, 1.0}};
double crtRate[NPC_COUNT][2] = { {1.0, 1.0}, {1.0, 1.0}, {0.0, 1.0}, {3.0, 1.0},
{2.0, 1.0}, {2.0, 1.0}, {0.0, 1.0}, {3.0, 1.0}, {4.0, 1.0}, {0.0, 1.0},
{1.0, 1.0},
{4.0, 1.0}};
int auraMax;
Player myself;
int totalAttr;
std::vector<NonPlayer> npcEnemy;
std::vector<Player> pcEnemy;
std::vector<double> pcWeight;
std::vector<int> pcType; // 1:Atk 2:Def 3:All
int pcAtkCount = 0;
int pcDefCount = 0;
Player* lastPc = NULL;
std::vector<Gear> gears[4];
BStat myStat;
std::vector<BStat> npcEnemyStat;
std::vector<BStat> pcEnemyStat;
struct BResult
{
int winner; // 0: attacker, 1: defender, 2: draw
double rate; // (hp+sld)/(hpM+sldM) of winner, or 1 if draw
};
struct AttrKey
{
int16_t at[ATTR_COUNT];
int8_t gi[4];
int32_t as;
inline bool operator==(const AttrKey& o) const
{
return memcmp(this, &o, sizeof(AttrKey)) == 0;
}
inline bool operator<(const AttrKey& o) const
{
return memcmp(this, &o, sizeof(AttrKey)) < 0;
}
void print() const
{
for (int i = 0; i < ATTR_COUNT; ++i)
{
printf("%d ", (int)at[i]);
}
printf("\n");
for (int i = 0; i < 4; ++i)
{
const Gear& gear = gears[i][gi[i]];
printf("%s", gearName[gear.type]);
if (gear.type != GEAR_NONE)
{
printf(" %d %d %d %d %d %d", gear.lvl, gear.percent[0], gear.percent[1], gear.percent[2], gear.percent[3], gear.isMyst ? 1 : 0);
}
printf("\n");
}
int auraCount = 0;
for (int i = 0; i < AURA_COUNT; ++i)
{
if (as & 1 << i) ++auraCount;
}
printf("%d", auraCount);
for (int i = 0; i < AURA_COUNT; ++i)
{
if (as & 1 << i) printf(" %s", auraName[i]);
}
printf("\n");
}
};
struct AttrKeyHash
{
inline size_t operator()(const AttrKey& key) const
{
return crc64r(&key, sizeof(AttrKey));
}
};
struct AttrScore
{
double v1, v2;
explicit AttrScore(double v1 = -1, double v2 = 0) : v1(v1), v2(v2)
{
}
inline bool operator<(const AttrScore& o) const
{
return v1 != o.v1 ? v1 < o.v1 : v2 < o.v2;
}
inline int comp(const AttrScore& o) const
{
return v1 < o.v1 ? -1 : v1 > o.v1 ? 1 : v2 < o.v2 ? -1 : v2 > o.v2 ? 1 : 0;
}
};
typedef std::pair<AttrKey, AttrScore> AttrPair;
struct AttrPairComp
{
inline bool operator()(const AttrPair& a, const AttrPair& b) const
{
int c = a.second.comp(b.second);
return c ? c > 0 : memcmp(&a.first, &b.first, sizeof(AttrKey)) < 0;
}
};
typedef std::tr1::unordered_map<AttrKey, AttrScore, AttrKeyHash> AttrMap;
typedef std::priority_queue<AttrPair, std::vector<AttrPair>, AttrPairComp> AttrQueue;
std::vector<AttrKey> attrSeed;
int initStep;
int64_t attrSeedTotal;
const int speedReduceMax = 80;
char buf[10000];
int version = 506;
int rseedGlobal = time(NULL);
int numThreads = 4;
int numTests = 1000;
double ciTest = 0;
int gridSize = 6;
int stepRate = 3;
int candidateMax = 20;
int startLevel = 0;
int reduceRateA = 3;
int reduceRateB = 10;
int pcWeightA = 1;
int pcWeightB = 1;
int maxAttr[ATTR_COUNT] = {};
int attrSeedMax = 1000000;
int auraFilter = AURA_DI;
bool verbose = false;
int defMode = 0; // 0:off 1:on 2:mix
bool debug = false;
pthread_mutex_t threadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t attrEvalTaskCond = PTHREAD_COND_INITIALIZER;
pthread_cond_t attrEvalTaskFullCond = PTHREAD_COND_INITIALIZER;
pthread_cond_t attrEvalFinishCond = PTHREAD_COND_INITIALIZER;
pthread_cond_t progressMeterFinishCond = PTHREAD_COND_INITIALIZER;
pthread_attr_t threadAttr;
volatile bool attrEvalWorking;
volatile bool progressMeterWorking;
volatile bool progressMeterAlive;
volatile bool signalCatch = false;
volatile int attrEvalAliveCount;
volatile int attrEvalWorkingCount;
volatile int calcAttrStage;
volatile int calcAttrCount;
volatile double bestWinRate;
volatile double bestProfit;
timeval calcAttrTvBegin;
void signalHandler(int sig)
{
signalCatch = true;
}
void ci(int s, int n, double& low, double& high)
{
if (n == 0)
{
low = 0.0;
high = 1.0;
return;
}
double z = 1.959964; // 95%
double a = 1.0 * s / n;
double c = 2 * n * a + z * z;
double r = sqrt(4 * n * a * (1 - a) + z * z) * z;
double t = 2 * (n + z * z);
low = (s == 0 ? 0.0 : (c - r) / t);
high = (s == n ? 1.0 : (c + r) / t);
}
int revMul(int a, double x)
{
int b = a / x;
while (int(b * x) <= a) ++b;
return --b;
}
int gcd(int a, int b)
{
while (a && b)
{
int c = a % b;
a = b;
b = c;
}
return a + b;
}
void initPrefTable()
{
memset(prefCount, 0, sizeof(prefCount));
for (int i = 0; i < 1 << PREF_COUNT; ++i)
{
int auraSkl = 0;
int prefN = 0;
for (int j = 0; j < PREF_COUNT; ++j)
{
if (i & (1 << j))
{
++prefN;
auraSkl |= prefAura[j];
}
}
if (prefN <= 4)
{
for (int j = 0; j <= i; ++j)
{
if ((j & i) == j)
{
prefTable[j][prefN][prefCount[j][prefN]++] = auraSkl;
}
}
}
for (int j = 0; j < prefN && j <= 4; ++j)
{
prefCount[i][j] = 1;
prefTable[i][j][0] = auraSkl;
}
}
auraRandCount = 1;
for (int i = 0; i < 1 << PREF_COUNT; ++i)
{
for (int j = 0; j <= 4; ++j)
{
auraRandCount = auraRandCount * prefCount[i][j] / gcd(auraRandCount, prefCount[i][j]);
}
}
}
class ProgressMeter
{
public:
void init(int initSeed, int initStep)
{
mInitSeed = initSeed;
mTotalStep = 0;
while (initStep > 0)
{
++mTotalStep;
initStep = initStep * (stepRate - 1) / stepRate;
}
mFirstRate = 1.0 * initSeed / (initSeed + mTotalStep * 1000);
mSecondRate = (1 - mFirstRate) / mTotalStep;
}
double getProgress(int s, int c)
{
if (s < 0)
{
return 1.0 * c / mInitSeed * mFirstRate;
}
else
{
double p = c / 50.0;
p = (p + 11 - sqrt(p * p - 18 * p + 121)) / 20;
return mSecondRate * (s + p) + mFirstRate;
}
}
protected:
int mInitSeed;
int mTotalStep;
double mFirstRate;
double mSecondRate;
};
ProgressMeter pm;
inline int myrand(int* rseed, int m)
{
const int M = 48271;
const int Q = 0x7FFFFFFF / M;
const int R = 0x7FFFFFFF % M;
*rseed = M * (*rseed % Q) - R * (*rseed / Q);
if (*rseed < 0) *rseed += 0x7FFFFFFF;
return *rseed % m;
}
inline int64_t myrand64(int* rseed, int64_t m)
{
if (m <= 0x7FFFFFFF) return myrand(rseed, m);
int64_t r = static_cast<int64_t>(myrand(rseed, 0x40000000)) << 30;
r |= myrand(rseed, 0x40000000);
return r % m;
}
inline int rand100(int* rseed)
{
return myrand(rseed, 100);
}
bool isSignedNumberDot(const char* s)
{
for (; *s; ++s) if ((*s < '0' || *s > '9') && *s != '.' && *s != '-') return false;
return true;
}
bool isNumberDot(const char* s)
{
for (; *s; ++s) if ((*s < '0' || *s > '9') && *s != '.') return false;
return true;
}
bool isNumber(const char* s)
{
for (; *s; ++s) if (*s < '0' || *s > '9') return false;
return true;
}
bool getNpcRolePrefix(char* str, int& role, int& prefix)
{
role = -1;
prefix = 0;
char* p = strchr(str, '_');
if (p) *p = 0;
for (int i = 0; i < NPC_COUNT; ++i)
{
if (strcmp(str, npcName[i]) == 0)
{
role = ROLE_NPC + i;
break;
}
}
if (role == -1) return false;
if (role == ROLE_LIU)
{
// 0-11: category
// 12-17: hpM
// 18-23: sldM
// 24-26: pAtk
// 27-29: mAtk
if (!p)
{
prefix = 0x3FFFFFFF;
}
else
{
++p;
if (strlen(p) != 16) return false;
#define GET_NUM(res, s, l, min, max) \
do \
{ \
int qcount = 0; \
res = 0; \
for (int j = s; j < s + l; ++j) \
{ \
if (p[j] == '?') \
{ \
++qcount; \
} \
else if (p[j] >= '0' && p[j] <= '9') \
{ \
res = res * 10 + (p[j] - '0'); \
} \
else \
{ \
res = -1; \
break; \
} \
} \
if (qcount == l) res = -2; \
else if (qcount > 0) res = -1; \
else if (res < min || res > max) res = -1; \
} \
while (false)
int res;
for (int i = 0; i < 6; ++i)
{
GET_NUM(res, i, 1, 0, 2);
if (res == -1) return false;
prefix |= (res == -2 ? 3 : res) << (i * 2);
}
for (int i = 0; i < 2; ++i)
{
GET_NUM(res, i * 3 + 6, 3, 280, 320);
if (res == -1) return false;
prefix |= (res == -2 ? 63 : res - 280) << (i * 6 + 12);
}
for (int i = 0; i < 2; ++i)
{
GET_NUM(res, i * 2 + 12, 2, 28, 32);
if (res == -1) return false;
prefix |= (res == -2 ? 7 : res - 28) << (i * 3 + 24);
}
#undef GET_NUM
}
}
else
{
while (p)
{
char* next = strchr(p + 1, '_');
if (next) *next = 0;
bool found = false;
for (int i = 0; i < PREF_COUNT; ++i)
{
if (strcmp(p + 1, prefName[i]) == 0)
{
prefix |= 1 << i;
found = true;
break;
}
}
if (!found) return false;
*p = 0;
p = next;
}
}
return true;
}
bool readGear(FILE* fp, Gear& gear)
{
long pos = ftell(fp);
for (;;)
{
if (fscanf(fp, "%s", buf) != 1)
{
fseek(fp, pos, SEEK_SET);
return false;
}
if (buf[0] == '/' && buf[1] == '/')
{
fgets(buf, sizeof(buf), fp);
pos = ftell(fp);
continue;
}
break;
}
gear.type = -1;
for (int i = 0; i < GEAR_COUNT; ++i)
{
if (strcmp(buf, gearName[i]) == 0)
{
gear.type = i;
break;
}
}
if (gear.type == -1)
{
fseek(fp, pos, SEEK_SET);
return false;
}
if (gear.type != GEAR_NONE)
{
int b;
if (fscanf(fp, "%d%d%d%d%d%d", &gear.lvl, &gear.percent[0], &gear.percent[1],
&gear.percent[2], &gear.percent[3], &b) != 6 ||
gear.lvl < 1 ||
gear.percent[0] < 40 || gear.percent[0] > 150 ||
gear.percent[1] < 40 || gear.percent[1] > 150 ||
gear.percent[2] < 40 || gear.percent[2] > 150 ||
gear.percent[3] < 40 || gear.percent[3] > 150 ||
b < 0 || b > 1)
{
fseek(fp, pos, SEEK_SET);
return false;
}
gear.isMyst = (b == 1);
}
return true;
}
bool readNonPlayer(FILE* fp, NonPlayer& npc)
{
long pos = ftell(fp);
for (;;)
{
if (fscanf(fp, "%s", buf) != 1)
{
fseek(fp, pos, SEEK_SET);
return false;
}
if (buf[0] == '/' && buf[1] == '/')
{
fgets(buf, sizeof(buf), fp);
pos = ftell(fp);
continue;
}
break;
}
if (!getNpcRolePrefix(buf, npc.role, npc.prefix))
{
fseek(fp, pos, SEEK_SET);
return false;
}
if (fscanf(fp, "%d%d", &npc.lvl, &npc.prefixCount) != 2 || npc.lvl < 1 ||
npc.prefixCount < 0 || npc.prefixCount > 4)
{
fseek(fp, pos, SEEK_SET);
return false;
}
return true;
}
bool readPlayer(FILE* fp, Player& pc)
{
long pos = ftell(fp);
for (;;)
{
if (fscanf(fp, "%s", buf) != 1)
{
fseek(fp, pos, SEEK_SET);
return false;
}
if (buf[0] == '/' && buf[1] == '/')
{
fgets(buf, sizeof(buf), fp);
pos = ftell(fp);
char* p = strstr(buf, " level:");
if (p && lastPc && lastPc->pBStat)
{
int lvl;
if (sscanf(p + 7, "%d", &lvl) == 1 && lvl >= 1)
{
lastPc->lvl = lvl;
lastPc->pBStat->lvl = lvl;
}
}
lastPc = NULL;
continue;
}
break;
}
pc.weight = 1;
pc.type = 3;
if (strcmp(buf, "ATK") == 0)
{
pc.type = 1;
if (fscanf(fp, "%s", buf) != 1)
{
printf("Error: EOF after \"ATK\"\n");
fseek(fp, pos, SEEK_SET);
return false;
}
}
else if (strcmp(buf, "DEF") == 0)
{
pc.type = 2;
if (fscanf(fp, "%s", buf) != 1)
{
printf("Error: EOF after \"DEF\"\n");
fseek(fp, pos, SEEK_SET);
return false;
}
}
if (buf[0] == 'W' && buf[1] == '=' && isSignedNumberDot(buf + 2))
{
if (sscanf(buf + 2, "%lf", &pc.weight) != 1)
{
printf("Error: Invalid \"W=\" parameter: %s\n", buf + 2);
fseek(fp, pos, SEEK_SET);
return false;
}
if (fscanf(fp, "%s", buf) != 1)
{
printf("Error: EOF after \"W=\"\n");
fseek(fp, pos, SEEK_SET);
return false;
}
}
char* p = strchr(buf, '_');
if (p != NULL)
{
pc.alias = p + 1;
*p = 0;
}
pc.role = -1;
for (int i = 0; i < PC_COUNT; ++i)
{
if (strcmp(buf, pcName[i]) == 0)
{
pc.role = ROLE_PC + i;
break;
}
}
if (pc.role == -1)
{
printf("Error: Unknown PC role name: %s\n", buf);
fseek(fp, pos, SEEK_SET);
return false;
}
if (fscanf(fp, "%s", buf) != 1)
{
printf("Error: EOF after PC role name\n");
fseek(fp, pos, SEEK_SET);
return false;
}
if (buf[0] == 'G' && buf[1] == '=')
{
if (!isNumber(buf + 2) || sscanf(buf + 2, "%d", &pc.growth) != 1 ||
pc.growth < 0)
{
printf("Error: Invalid \"G=\" parameter: %s\n", buf + 2);
fseek(fp, pos, SEEK_SET);
return false;
}
if (fscanf(fp, "%s", buf) != 1)
{
printf("Error: EOF after \"G=\"\n");
fseek(fp, pos, SEEK_SET);