[TestFixture]
public class AiTest
{
[Test]
public void Test()
{
Settings.Instance.LogFolderPath = @"C:\repository\GitHub\ChuckLu\Test\HearthbuddyRelease\Logs";
Settings.Instance.DataFolderPath =
@"C:\repository\GitHub\ChuckLu\Test\HearthbuddyRelease\Routines\DefaultRoutine\SilverFish\Data\";
if (Hrtprozis.Instance.settings == null)
{
Hrtprozis.Instance.setInstances();
ComboBreaker.Instance.setInstances();
PenalityManager.Instance.setInstances();
} //-mode: 0-all, 1-lethalcheck, 2-normal
Ai ai = Ai.Instance;
ai.autoTester(true, string.Empty, ); }
}
 if (mode ==  || mode == )
{
doallmoves(false, true);
calcTime = (DateTime.Now - strt).TotalSeconds;
help.logg("calculated " + calcTime);
retval.Add(calcTime);
} if (Settings.Instance.berserkIfCanFinishNextTour > && bestmoveValue > )
{ }
else if (bestmoveValue < )
{
// normal
if (mode == || mode == )
{
posmoves.Clear();
pMain = new Playfield();
pMain.print = printstuff;
posmoves.Add(pMain);
strt = DateTime.Now;
doallmoves(false, false);
calcTime = (DateTime.Now - strt).TotalSeconds;
help.logg("calculated " + calcTime);
retval.Add(calcTime);
}
}

发现格雷迈恩的效果,不知道怎么触发的,需要直接运行exe调试

在    routine.Tick();设置断点,F11之后会加载DefaultRoutine.dll

// Triton.Bot.RoutineManager
// Token: 0x060011C9 RID: 4553 RVA: 0x000B65BC File Offset: 0x000B47BC
public static void Tick(IRoutine routine)
{
RoutineManager.smethod_0(routine, RoutineManager.routineEvent_2);
try
{
routine.Tick();
}
catch (Exception exception)
{
RoutineManager.ilog_0.Error("Exception during routine Tick.", exception);
}
RoutineManager.smethod_0(routine, RoutineManager.routineEvent_3);
}
// HREngine.Bots.Ai
// Token: 0x06000061 RID: 97 RVA: 0x00009000 File Offset: 0x00007200
private void doallmoves(bool test, bool isLethalCheck)
{
foreach (EnemyTurnSimulator ets in this.enemyTurnSim)
{
ets.setMaxwide(true);
}
foreach (EnemyTurnSimulator ets2 in this.enemySecondTurnSim)
{
ets2.setMaxwide(true);
}
this.posmoves[].isLethalCheck = isLethalCheck;
this.mainTurnSimulator.doallmoves(this.posmoves[]);
this.bestplay = this.mainTurnSimulator.bestboard;
float bestval = this.mainTurnSimulator.bestmoveValue;
this.help.loggonoff(true);
this.help.logg("-------------------------------------");
bool flag = this.bestplay.ruleWeight != ;
if (flag)
{
this.help.logg("ruleWeight " + this.bestplay.ruleWeight * -);
}
bool flag2 = this.settings.printRules > ;
if (flag2)
{
string[] rulesStr = this.bestplay.rulesUsed.Split(new char[]
{
'@'
});
foreach (string rs in rulesStr)
{
bool flag3 = rs == "";
if (!flag3)
{
this.help.logg("rule: " + rs);
}
}
}
this.help.logg("value of best board " + bestval);
this.bestActions.Clear();
this.bestmove = null;
ActionNormalizer an = new ActionNormalizer();
bool flag4 = this.settings.adjustActions > ;
if (flag4)
{
an.adjustActions(this.bestplay, isLethalCheck);
}
foreach (Action a in this.bestplay.playactions)
{
this.bestActions.Add(new Action(a));
a.print(false);
}
bool flag5 = this.bestActions.Count >= ;
if (flag5)
{
this.bestmove = this.bestActions[];
this.bestActions.RemoveAt();
}
this.bestmoveValue = bestval;
bool flag6 = this.bestmove != null && this.bestmove.actionType > actionEnum.endturn;
if (flag6)
{
this.nextMoveGuess = new Playfield();
this.nextMoveGuess.doAction(this.bestmove);
}
else
{
this.nextMoveGuess.mana = -;
}
if (isLethalCheck)
{
this.lethalMissing = this.bestplay.enemyHero.armor + this.bestplay.enemyHero.Hp;
this.help.logg("missing dmg to lethal " + this.lethalMissing);
}
}
// HREngine.Bots.MiniSimulator
// Token: 0x060000E0 RID: 224 RVA: 0x00018480 File Offset: 0x00016680
public float doallmoves(Playfield playf)
{
this.print = playf.print;
this.isLethalCheck = playf.isLethalCheck;
this.enoughCalculations = false;
this.botBase = Ai.Instance.botBase;
this.posmoves.Clear();
this.twoturnfields.Clear();
this.addToPosmoves(playf);
bool havedonesomething = true;
List<Playfield> temp = new List<Playfield>();
int deep = ;
this.calculated = ;
Playfield bestold = null;
this.bestoldval = -2E+07f;
while (havedonesomething)
{
bool flag = this.printNormalstuff;
if (flag)
{
Helpfunctions.Instance.logg("ailoop");
}
GC.Collect();
temp.Clear();
temp.AddRange(this.posmoves);
this.posmoves.Clear();
havedonesomething = false;
this.threadnumberGlobal = ;
bool flag2 = this.print;
if (flag2)
{
this.startEnemyTurnSimThread(temp, , temp.Count);
}
else
{
Parallel.ForEach<Tuple<int, int>>(Partitioner.Create(, temp.Count), delegate(Tuple<int, int> range)
{
this.startEnemyTurnSimThread(temp, range.Item1, range.Item2);
});
}
foreach (Playfield p in temp)
{
bool flag3 = this.totalboards > ;
if (flag3)
{
this.calculated += p.nextPlayfields.Count;
}
bool flag4 = this.calculated <= this.totalboards;
if (flag4)
{
this.posmoves.AddRange(p.nextPlayfields);
p.nextPlayfields.Clear();
}
float pVal = this.botBase.getPlayfieldValue(p);
bool flag5 = pVal > this.bestoldval;
if (flag5)
{
this.bestoldval = pVal;
bestold = p;
this.bestoldDuplicates.Clear();
}
else
{
bool flag6 = pVal == this.bestoldval;
if (flag6)
{
this.bestoldDuplicates.Add(p);
}
}
}
bool flag7 = this.isLethalCheck && this.bestoldval >= 10000f;
if (flag7)
{
this.posmoves.Clear();
}
bool flag8 = this.posmoves.Count > ;
if (flag8)
{
havedonesomething = true;
}
bool flag9 = this.printNormalstuff;
if (flag9)
{
int donec = ;
foreach (Playfield p2 in this.posmoves)
{
bool complete = p2.complete;
if (complete)
{
donec++;
}
}
Helpfunctions.Instance.logg(string.Concat(new object[]
{
"deep ",
deep,
" len ",
this.posmoves.Count,
" dones ",
donec
}));
}
this.cuttingposibilities(this.isLethalCheck);
bool flag10 = this.printNormalstuff;
if (flag10)
{
Helpfunctions.Instance.logg("cut to len " + this.posmoves.Count);
}
deep++;
temp.Clear();
bool flag11 = this.calculated > this.totalboards;
if (flag11)
{
this.enoughCalculations = true;
}
bool flag12 = deep >= this.maxdeep;
if (flag12)
{
this.enoughCalculations = true;
}
}
bool flag13 = this.dirtyTwoTurnSim > && !this.twoturnfields.Contains(bestold);
if (flag13)
{
this.twoturnfields.Add(bestold);
}
this.posmoves.Clear();
this.posmoves.Add(bestold);
this.posmoves.AddRange(this.bestoldDuplicates);
bool flag14 = !this.isLethalCheck && this.bestoldval < 10000f;
if (flag14)
{
this.doDirtyTwoTurnsim();
}
bool flag15 = this.posmoves.Count >= ;
float result;
if (flag15)
{
this.posmoves.Sort((Playfield a, Playfield b) => this.botBase.getPlayfieldValue(b).CompareTo(this.botBase.getPlayfieldValue(a)));
Playfield bestplay = this.posmoves[];
float bestval = this.botBase.getPlayfieldValue(bestplay);
int pcount = this.posmoves.Count;
for (int i = ; i < pcount; i++)
{
float val = this.botBase.getPlayfieldValue(this.posmoves[i]);
bool flag16 = bestval > val;
if (flag16)
{
break;
}
bool flag17 = this.posmoves[i].cardsPlayedThisTurn > bestplay.cardsPlayedThisTurn;
if (!flag17)
{
bool flag18 = this.posmoves[i].cardsPlayedThisTurn == bestplay.cardsPlayedThisTurn;
if (flag18)
{
bool flag19 = bestplay.optionsPlayedThisTurn > this.posmoves[i].optionsPlayedThisTurn;
if (flag19)
{
goto IL_57A;
}
bool flag20 = bestplay.optionsPlayedThisTurn == this.posmoves[i].optionsPlayedThisTurn && bestplay.enemyHero.Hp <= this.posmoves[i].enemyHero.Hp;
if (flag20)
{
goto IL_57A;
}
}
bestplay = this.posmoves[i];
bestval = val;
}
IL_57A:;
}
this.bestmove = bestplay.getNextAction();
this.bestmoveValue = bestval;
this.bestboard = new Playfield(bestplay);
this.bestboard.guessingHeroHP = bestplay.guessingHeroHP;
this.bestboard.value = bestplay.value;
this.bestboard.hashcode = bestplay.hashcode;
this.bestoldDuplicates.Clear();
result = bestval;
}
else
{
this.bestmove = null;
this.bestmoveValue = -100000f;
this.bestboard = playf;
result = -10000f;
}
return result;
}
// HREngine.Bots.MiniSimulatorNextTurn
// Token: 0x060000EE RID: 238 RVA: 0x00019890 File Offset: 0x00017A90
public float doallmoves(Playfield playf, bool print = false)
{
bool isLethalCheck = playf.isLethalCheck;
int totalboards = Settings.Instance.nextTurnTotalBoards;
int maxwide = Settings.Instance.nextTurnMaxWide;
int maxdeep = Settings.Instance.nextTurnDeep;
bool playaround = Settings.Instance.playaround;
int playaroundprob = Settings.Instance.playaroundprob;
int playaroundprob2 = Settings.Instance.playaroundprob2;
this.botBase = Ai.Instance.botBase;
this.posmoves.Clear();
this.posmoves.Add(new Playfield(playf));
bool havedonesomething = true;
List<Playfield> temp = new List<Playfield>();
int deep = ;
this.calculated = ;
Playfield bestold = null;
float bestoldval = -2E+07f;
while (havedonesomething)
{
temp.Clear();
temp.AddRange(this.posmoves);
havedonesomething = false;
foreach (Playfield p in temp)
{
bool flag = p.complete || p.ownHero.Hp <= ;
if (!flag)
{
List<Action> actions = this.movegen.getMoveList(p, this.usePenalityManager, this.useCutingTargets, true);
foreach (Action a2 in actions)
{
havedonesomething = true;
Playfield pf = new Playfield(p);
pf.doAction(a2);
bool flag2 = pf.ownHero.Hp > ;
if (flag2)
{
this.posmoves.Add(pf);
}
bool flag3 = totalboards > ;
if (flag3)
{
this.calculated++;
}
}
p.endTurn();
bool flag4 = !isLethalCheck;
if (flag4)
{
this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2);
}
bool flag5 = this.botBase.getPlayfieldValue(p) > bestoldval;
if (flag5)
{
bestoldval = this.botBase.getPlayfieldValue(p);
bestold = p;
}
this.posmoves.Remove(p);
bool flag6 = this.calculated > totalboards;
if (flag6)
{
break;
}
}
}
this.cuttingposibilities(maxwide);
deep++;
bool flag7 = this.calculated > totalboards;
if (flag7)
{
break;
}
bool flag8 = deep >= maxdeep;
if (flag8)
{
break;
}
}
this.posmoves.Add(bestold);
foreach (Playfield p2 in this.posmoves)
{
bool flag9 = !p2.complete;
if (flag9)
{
p2.endTurn();
bool flag10 = !isLethalCheck;
if (flag10)
{
this.startEnemyTurnSim(p2, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2);
}
}
}
bool flag11 = this.posmoves.Count >= ;
float result;
if (flag11)
{
this.posmoves.Sort((Playfield a, Playfield b) => this.botBase.getPlayfieldValue(b).CompareTo(this.botBase.getPlayfieldValue(a)));
Playfield bestplay = this.posmoves[];
float bestval = this.botBase.getPlayfieldValue(bestplay);
int pcount = this.posmoves.Count;
for (int i = ; i < pcount; i++)
{
float val = this.botBase.getPlayfieldValue(this.posmoves[i]);
bool flag12 = bestval > val;
if (flag12)
{
break;
}
bool flag13 = bestplay.playactions.Count <= this.posmoves[i].playactions.Count;
if (!flag13)
{
bestplay = this.posmoves[i];
bestval = val;
}
}
this.bestmove = bestplay.getNextAction();
this.bestmoveValue = bestval;
this.bestboard = new Playfield(bestplay);
result = bestval;
}
else
{
this.bestmove = null;
this.bestmoveValue = -100000f;
this.bestboard = playf;
result = -10000f;
}
return result;
}

用单元测试来调试SilverFish AI的更多相关文章

  1. HearthBuddy Ai 调试实战2 在使用海巨人的时候,少召唤了一个图腾(费用是对的)

    问题 游戏面板 8是青玉之爪13是海巨人17是恐狼前锋 64是萨满 66是圣骑士63,99,46,是微型木乃伊[其中99和46都是2血3攻,63是2血1攻]57是鱼人木乃伊 微型木乃伊 "L ...

  2. HearthBuddy Ai调试实战1-->出牌的时候,少召唤了图腾就结束回合

    期望通过ai的调试,来搞明白出牌的逻辑. 55是投火无面者63是恐狼前锋34是风怒36是自动漩涡打击装置13是空灵召唤者, "LocStringZhCn": "<b ...

  3. 【vue】在VS Code中调试Jest单元测试

    在VS Code中调试Jest单元测试 添加调试任务 打开 vscode launch.json 文件,在 configurations 内加入下面代码 "configurations&qu ...

  4. HearthBuddy炉石兄弟 如何调试ai

    Sepefeets's update to botmaker's Silverfish AI This AI is a Custom Class for Hearthranger and Hearth ...

  5. ASP.NET 系列:单元测试

    单元测试可以有效的可以在编码.设计.调试到重构等多方面显著提升我们的工作效率和质量.github上可供参考和学习的各种开源项目众多,NopCommerce.Orchard等以及微软的asp.net m ...

  6. Unity 单元测试(NUnit,UnityTestTools)

    在软件开发中单元测试是非常重要的一个环节, =.=盘子脸去了几家公司都没有单元测试这个概念. 我们的系统虽然从代码看上是分离的, 在多数情况下都需要依赖于其他模块来运行.(单元测试部分内容教我解决这个 ...

  7. 使用 xUnit 编写 ASP.NET Core 单元测试

    还记得 .NET Framework 的 ASP.NET WebForm 吗?那个年代如果要在 Web 层做单元测试简直就是灾难啊..NET Core 吸取教训,在设计上考虑到了可测试性,就连 ASP ...

  8. 学习笔记之Python调试 - pdb

    python调试神器——pdb - 软谋python https://mp.weixin.qq.com/s/w3Xw8I_zh7MFq2dx5kdQXw 优秀开发者必备技能包:Python调试器 - ...

  9. .net持续集成单元测试篇之单元测试简介以及在visual studio中配置Nunit使用环境

    系列目录 单元测试及测试驱动开发简介 什么是单元测试 单元测试是一段自动化的代码,这段代码调用被测试的工作单元,之后对这个单元的单个最终结果的某些假设进行检验.单元测试几乎都是用单元测试框架编写的.单 ...

随机推荐

  1. JS实现旋转的魔方

    js <script> window.onload = function () { let cube = document.querySelector('.cube') let timer ...

  2. docker 第五篇 存储

    镜像概述复习 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层 如果运行中的容器修改了现有的一个已经存在的文件,那改文件将会从读写层下面的只读 ...

  3. 请求上下文HttpContext解释

    1 HttpContext上下文作用 有关应用程序状态信息,处理的请求以及构建的响应等信息全部通过HttpContext上下文获取 2 Httpcontext类用于从头至尾跟踪请求的状态,他也是有关请 ...

  4. sql 创建新表时的完成格式

    1 create table [dbo].[Customer] ( CustomerID int identity(1,1) not null, [Name] [nvarchar](50) null, ...

  5. ORACLE数据库 自动备份 定时计划任务 windows

    疑问为什么没有输入oracle 的数据库安装目录就能直接备份呢,可能是因为oracle默认安装c盘,在docs命令直接能操作吧,不信可以使用sqlplus试试. 一共分三步: 一.建立一个.bat 批 ...

  6. 20.SSM整合-全注解开发

    全注解开发 1.将SpringMVC改为注解 修改spring-mvc.xml 2.将Spring改为注解 将Service改为注解,完成Dao的注入 将事务以注解方式织入到Service 1.修改s ...

  7. 6.SpringMVC 配置式开发-处理器

    处理器除了实现Controller 接口外,还可以继承自一些其他的类,来完成一些特殊的功能 1.继承自AbstractController类 若处理器继承自AbstractController类,那么 ...

  8. Win10 通过附加进程调试时出现“此任务要求应用程序具有提升的权限”

    最近有新人在使用vs调试时出现了“此任务要求应用程序具有提升的权限”的提示,每次调试vs就会重启一次. 问到我时,我经过查了一番资料才给解决掉了. 其实,问题主要是因为直接启动vs项目时没有足够的权限 ...

  9. zabbix环境mysql分区表管理历史数据_python实现

    zabbix添加数据库表partition zabbix系统自身有housekeeper进程来清除超过保留时间的数据,但是数据量上来之后就会比较影响性能,因此可以使用mysql的表分区来解决这个问题, ...

  10. Vue介绍:vue导读2

    一.实例中的成员 二.高级指令 三.组件初识 一.实例中的成员 # 计算computed <!DOCTYPE html> <html> <head> <met ...