public void reset_stat(board a) { Board = a.tosimple(); tree temp = boardtree.clone(); temp.pieceidx = boardtree.pieceidx; boardtree = temp; boardtree.Board = Board.clone(); extend_node(); }
// 洞判定部分可能更好 //private static int evaldeephole(int width) //{ // for (int i = width - 1; i < 10; ++i) // { // } //} public int evalatkdef(tree node) // 哪些是直接继承 哪些需要处理 { int score = 0; score += node.attack * W.atk; //score += node.def * W.def; // 在树中和取出是不一样的 score += (node.maxattack - node.attack) * W.maxatk; score += (node.maxdef - node.def) * W.maxdef; return(score); }
public void freenode(tree node) { foreach (tree chird in node.treenode) { freenode(chird); } node.useless = true; node.inplan = false; node = null; }
public void init() { boardtree = new tree(); board F = new board(new mino_gene(), new TopGarbage(), 5); boardtree.Board = Board.clone(); //for (int i = 0; i < 15; ++i) F.add_garbage(1); //boardtree.Board = F.tosimple(); //boardtree.ad //nodequeue.Add(boardtree); }
public void reset_stat(bool[,] field, bool b2b, int combo) { Board.field = field; Board.column_height = Board.updatecol(); Board.isb2b = b2b; Board.combo = combo; boardtree = new tree(); boardtree.Board = Board.clone(); extend_node(); }
public void runmove(tree move) { if (move.ishold) { runmove(6); } for (int i = 0; i < move.finmino.path.idx; ++i) { runmove(move.finmino.path.path[i]); } runmove(5); }
//public bool findnextsol() //{ // for (; ; ) // yield return false; // pass //} public tree clone() { tree cp = new tree(); cp.Board = Board.clone(); cp.garbage = garbage; // 可能有抵消 cp.attack = attack; cp.holdpiece = holdpiece; cp.battlescore = battlescore; // attack 可能继承 return(cp); }
//public void nodeadd(tree node) //{ // if (node.depth == calcdepth) nodequeue.Add(node); // //if (node.treenode.Count == 0 && !node.useless && node.pieceidx < nextquene.Count && !node.isextend) nodequeue.Add(node); // //cnt += node.treenode.Count; // foreach (tree chird in node.treenode) // { // nodeadd(chird); // } //} public void nodeadd(tree node) { if (node.inplan && node.pieceidx < nextcnt && !node.isextend) { nodequeue.Add(node); // 考虑遇到无用直接返回 } //if (node.treenode.Count == 0 && !node.useless && node.pieceidx < nextquene.Count && !node.isextend) nodequeue.Add(node); //cnt += node.treenode.Count; foreach (tree chird in node.treenode) { nodeadd(chird); } }
public int nodecnt(tree node) { int cnt = 0; if (node.depth == calcdepth) { cnt += 1; } //cnt += node.treenode.Count; foreach (tree chird in node.treenode) { cnt += nodecnt(chird); } return(cnt); }
public int nodedep(tree node) { int cnt = 0; if (!node.useless) { cnt = node.depth; //cnt += node.treenode.Count; foreach (tree chird in node.treenode) { cnt = Math.Max(nodedep(chird), cnt); } } return(cnt); }
public void reset_stat(bool[,] field, bool b2b, int combo) { tree temp = boardtree.clone(); temp.pieceidx = boardtree.pieceidx; Board = temp.Board.clone(); Board.field = field; Board.column_height = Board.updatecol(); Board.isb2b = b2b; Board.combo = combo; boardtree = temp; boardtree.Board = Board.clone(); extend_node(); }
public void bot_run() { if (bot.isdead) { isdead = true; return; } tree root = bot.requset_next_move(); if (root.isdead) { isdead = true; return; } Board.Spawn_piece(); runmove(root); int next = Minorule.genebag7int(); bot.add_next(next); Board.add_next_piece(next); bot.extend_node(); }
public int evalbattle(tree node) // 相对值? 需要向下累加 { int score = 0; score += W.movetime * node.finmino.path.movetime; if (node.finmino.name == "T" && (!node.finmino.Tspin || node.Board.clearrow == 0)) { score += W.wastedT; } score += W.fewcombo * node.Board.combo; if (node.Board.isperfectclear) { score += W.perfectclear * 1000; } if (node.Board.isb2bclear) { score += W.b2b_clear; } if (node.finmino.Tspin && node.finmino.name == "T") { if (node.Board.piece.mini) { score += W.tspin[0]; } else { score += W.tspin[node.Board.clearrow]; } } else { score += W.clear[node.Board.clearrow]; } //score return(score); }
public int evalmove(tree node) // 哪些是直接继承 哪些需要处理 { int score = 0; // 加一个combo if (node.Board.combo > 0) { score += W.combo; } if (node.holdT) { score += W.holdT; } if (node.holdI) { score += W.holdI; } if (node.Board.isb2b) { score += W.b2b; } return(score); }
public int evalparity(tree node) // 表面奇偶性 { int parity = 0; for (int i = 0; i < node.Board.column_height.Length; ++i) { if ((node.Board.column_height[i] & 1) == 1) { if ((i & 1) == 1) { parity += 1; } } else { if ((i & 1) == 1) { parity -= 1; } } } return(Math.Abs(parity)); }
public void findalladd(Juraknifecore bot) { // 攻击力判定 + t旋只改场地分 if (pieceidx >= bot.nextcnt) { return; } Tuple <int, int> res; this.nowpiece = bot.nextqueue[pieceidx % 30]; isextend = true; inplan = false; Board.piece = defaultop.demino.getmino(nowpiece); Board.piece.setpos(19, 3); List <mino> allpos = seacher.findallplace(Board); int chirdidx = pieceidx + 1; if (allpos == null) { tree chird = clone(); chird.isdead = true; chird.pieceidx = chirdidx; chird.inplan = false; chird.isextend = true; treenode.Add(chird); return; } ; foreach (mino m in allpos) { // 场外死亡判断 tree chird = clone(); chird.Board.piece = m; res = lock_piece_calc(ref chird.Board); chird.attack = chird.maxattack = res.Item1; chird.def = chird.maxdef = res.Item1 + res.Item2; // 已经消除了 还能叫防御吗 chird.finmino = m; chird.father = this; chird.ishold = false; chird.isdead = false; chird.holdpiece = holdpiece; chird.pieceidx = chirdidx; chird.depth = depth + 1; chird.maxdepth = chird.depth; chird.maxdepth = chird.pieceidx; chird.inplan = true; chird.res = bot.evalweight.evalfield(chird); chird.fieldscore = (int)chird.res.score; chird.battlescore += bot.evalweight.evalbattle(chird); // 相同的不要反复判了 chird.movescore = bot.evalweight.evalmove(chird); // 相同的不要反复判了 chird.atkscore = bot.evalweight.evalatkdef(chird); // 相同的不要反复判了 if (true || chird.holdT || hasnextT(bot, chirdidx)) // 当前块是t的时候 { tree Tchird1 = chird.clone(); Tchird1.Board.piece = defaultop.demino.getmino(2); Tchird1.Board.piece.setpos(19, 3); List <mino> Alltslot = search_tspin.findalltslot(Tchird1.Board); // 修改 /// 我是把tspin后的状态 提前压回该节点 if (Alltslot.Count != 0) { //List<mino> Alltslot = search_tspin.findalltslot(chird.Board); tree bestT; long minscore = chird.fieldscore; foreach (mino t in Alltslot) // 超过一个 干掉 { if (!t.Tspin) { continue; } tree Tchird = chird.clone(); Tchird.Board.piece = t; Tchird.finmino = t; res = lock_piece_calc(ref Tchird.Board); if (!t.mini) { Tchird.fieldscore = bot.evalweight.evalfield(Tchird).score; Tchird.fieldscore += bot.evalweight.W.tslot[res.Item2]; } else { Tchird.fieldscore = chird.fieldscore + bot.evalweight.W.tslot[4]; } //Tchird.score += bot.evalweight.evalbattle(Tchird); // 是否要battle也加上 // 其他节点借用了这个t的分值? 需不需要加入t坑评分 // 攻击也需要 if (Tchird.fieldscore > minscore && Tchird.Board.piece.Tspin) { minscore = Tchird.fieldscore; bestT = Tchird; } } chird.fieldscore = minscore; } } // 回传父节点 chird.updatefather(); // check update treenode.Add(chird); } if (holdpiece == -1) { int holdidx = pieceidx + 1, nextnext = pieceidx + 2; if (holdidx < bot.nextcnt) { // 保持连击的加分 // 防御是否应该削去 // 防御是给没打出攻击时才有的 // combo应该是个可延续状态 // 问题 特别喜欢打t1 // 不喜欢留防御 // todo T比较近的时候就可以开搜 // 优化 // 多next看t // 为什么不喜欢堆防御 // keepcombo的 def // 子节点也要前面的攻击 // 软降优化 // 扩展被选中的节点的所有子节点 // 需要参与排序的有 自身场地状态 从根到该节点所打出的攻击总数 该点的攻击,该点开始保持连击打出的最大防御数 路径总数(? 浪费t总数(这个不确定 // Board.piece = defaultop.demino.getmino(bot.nextqueue[holdidx % 30]); Board.piece.setpos(19, 3); List <mino> allpos2 = seacher.findallplace(Board); foreach (mino m in allpos2) { tree chird = clone(); chird.Board.piece = m; res = lock_piece_calc(ref chird.Board); chird.attack = chird.maxattack = res.Item1; chird.def = chird.maxdef = res.Item1 + res.Item2; // 已经消除了 还能叫防御吗 chird.finmino = m; chird.isdead = false; chird.ishold = true; chird.holdpiece = nowpiece; chird.father = this; chird.pieceidx = nextnext; chird.depth = depth + 1; chird.maxdepth = chird.pieceidx; chird.inplan = true; chird.res = bot.evalweight.evalfield(chird); chird.fieldscore = (int)chird.res.score; chird.battlescore += bot.evalweight.evalbattle(chird); // 作为攻击回传 chird.movescore = bot.evalweight.evalmove(chird); // 相同的不要反复判了 chird.atkscore = bot.evalweight.evalatkdef(chird); // 相同的不要反复判了 if (true || chird.holdT || hasnextT(bot, nextnext)) { tree Tchird1 = chird.clone(); Tchird1.Board.piece = defaultop.demino.getmino(2); Tchird1.Board.piece.setpos(19, 3); List <mino> Alltslot = search_tspin.findalltslot(Tchird1.Board); //List<mino> Alltslot = search_tspin.findalltslot(chird.Board); if (Alltslot.Count != 0) { tree bestT; long minscore = chird.fieldscore; foreach (mino t in Alltslot) { if (!t.Tspin) { continue; } tree Tchird = chird.clone(); Tchird.Board.piece = t; Tchird.finmino = t; res = lock_piece_calc(ref Tchird.Board); // 作为防御回传 Tchird.fieldscore = bot.evalweight.evalfield(Tchird).score; //Tchird.score += bot.evalweight.evalbattle(Tchird); // 是否要battle也加上 if (!t.mini) { Tchird.fieldscore = bot.evalweight.evalfield(Tchird).score; Tchird.fieldscore += bot.evalweight.W.tslot[res.Item2]; } else { Tchird.fieldscore = chird.fieldscore + bot.evalweight.W.tslot[4]; } if (Tchird.fieldscore > minscore && Tchird.Board.piece.Tspin) { minscore = Tchird.fieldscore; bestT = Tchird; } } chird.fieldscore = minscore; } } chird.updatefather(); // 回传父节点 treenode.Add(chird); } // 回传父节点 } } else { int temp = nowpiece; nowpiece = holdpiece; Board.piece = defaultop.demino.getmino(nowpiece); Board.piece.setpos(19, 3); List <mino> allpos1 = seacher.findallplace(Board); // 先对相对有用的节点更新 foreach (mino m in allpos1) { tree chird = clone(); chird.Board.piece = m; res = lock_piece_calc(ref chird.Board); chird.attack = chird.maxattack = res.Item1; chird.def = chird.maxdef = res.Item1 + res.Item2; // 已经消除了 还能叫防御吗 chird.finmino = m; chird.isdead = false; chird.ishold = true; chird.holdpiece = temp; // oops chird.pieceidx = chirdidx; chird.father = this; chird.depth = depth + 1; chird.maxdepth = chird.depth; chird.maxdepth = chird.pieceidx; chird.inplan = true; chird.res = bot.evalweight.evalfield(chird); chird.fieldscore = (int)chird.res.score; chird.battlescore += bot.evalweight.evalbattle(chird); chird.movescore = bot.evalweight.evalmove(chird); // 相同的不要反复判了 chird.atkscore = bot.evalweight.evalatkdef(chird); // 相同的不要反复判了 if (true || chird.holdT || hasnextT(bot, chirdidx)) { tree Tchird1 = chird.clone(); Tchird1.Board.piece = defaultop.demino.getmino(2); Tchird1.Board.piece.setpos(19, 3); List <mino> Alltslot = search_tspin.findalltslot(Tchird1.Board); //List<mino> Alltslot = search_tspin.findalltslot(chird.Board); if (Alltslot.Count != 0) { tree bestT; long minscore = chird.fieldscore; foreach (mino t in Alltslot) { if (!t.Tspin) { continue; // 相同场地不要去 有些无用场地需要吗 } tree Tchird = chird.clone(); Tchird.Board.piece = t; Tchird.finmino = t; res = lock_piece_calc(ref Tchird.Board); Tchird.fieldscore = bot.evalweight.evalfield(Tchird).score; //Tchird.battlescore += bot.evalweight.evalbattle(Tchird); // 是否要battle也加上 if (!t.mini) { Tchird.fieldscore = bot.evalweight.evalfield(Tchird).score; Tchird.fieldscore += bot.evalweight.W.tslot[res.Item2]; } else { Tchird.fieldscore = chird.fieldscore + bot.evalweight.W.tslot[4]; } if (Tchird.fieldscore > minscore && Tchird.Board.piece.Tspin) // 可以优化计算顺序 { minscore = Tchird.fieldscore; bestT = Tchird; } } chird.fieldscore = minscore; } } chird.updatefather(); // 回传父节点 treenode.Add(chird); } } }
public void run() { while (true) { Juraknifecore bot = new Juraknifecore(); bot.init(); //bot.boardtree.Board.console_print(false); mino_gene mino_Gene = new mino_gene(); Random rand = new Random(); for (int i = 0; i < 3; ++i) { //bot.add_next(rand.Next() % 7); bot.add_next(mino_Gene.genebag7int()); } //char a2 = Console.ReadKey().KeyChar; //bot.add_next(3); //bot.add_next(2); int t = 7; //int[] nextqq = { 3, 1, 6, 2, 0, 5, 2, 1, 4, 0, 1, 6, 5 }; Queue <tree> ans = new Queue <tree>(); while (true) //foreach (int q in nextqq) { //bot.add_next(rand.Next() % 7); bot.add_next(mino_Gene.genebag7int()); //bot.add_next(q); bot.extend_node(); //if (bot.boardtree.treenode[0].res.score < -1000000) { Console.WriteLine("ressearch"); foreach (tree chird in bot.boardtree.treenode) { chird.Board.console_print(false); Console.WriteLine("atk = {0}", chird.attack); Console.WriteLine("maxattack = {0}", chird.maxattack); Console.WriteLine("def = {0}", chird.def); Console.WriteLine("maxdef = {0}", chird.maxdef); Console.WriteLine("atkscore = {0}", chird.atkscore); Console.WriteLine("battlescore = {0}", chird.battlescore); Console.WriteLine("combo = {0}", chird.Board.combo); Console.WriteLine("clearrow = {0}", chird.Board.clearrow); Console.WriteLine("movetime = {0}", chird.finmino.path.movetime); Console.WriteLine("name = {0}", chird.finmino.name); Console.WriteLine("Tspin = {0}", chird.finmino.Tspin); Console.WriteLine("isb2bclear = {0}", chird.Board.isb2bclear); Console.WriteLine("nodebattlescore = {0}", bot.evalweight.evalbattle(chird)); Console.WriteLine(chird.score); Console.WriteLine("maxdepth = {0}", chird.maxdepth); //Console.WriteLine("scoreex = {0}", chird.scoreex); //Console.WriteLine(chird.finmino.minopos.x); //Console.WriteLine(chird.finmino.minopos.y); //Console.WriteLine(chird.finmino.stat); Console.WriteLine(chird.finmino.name); //foreach (int a in chird.Board.column_height) //{ // Console.Write(a); // Console.Write(" "); //} //Console.WriteLine(""); chird.finmino.console_print(); if (chird.holdpiece != -1) { defaultop.demino.getmino(chird.holdpiece).console_print(); } double kk = 0; //eval.evalhole(chird, chird.Board.column_height, 0, ref kk); //chird.res.print(); //char a1 = Console.ReadKey().KeyChar; } } tree root = bot.requset_next_move(); if (root.isdead) { Console.WriteLine(root.pieceidx);; break; } ; //ans.Enqueue(root); //if (ans.Count > 200) ans.Dequeue(); //eval.evalfield(root); //Console.Clear(); //root.Board.console_print(true, root.finmino); //if (root.pieceidx % 1 == 0 || root.score < -1000000) { root.Board.console_print(false); Console.WriteLine("resroot"); Console.WriteLine("atk = {0}", root.attack); Console.WriteLine("maxattack = {0}", root.maxattack); Console.WriteLine("def = {0}", root.def); Console.WriteLine("maxdef = {0}", root.maxdef); Console.WriteLine("atkscore = {0}", root.atkscore); Console.WriteLine("battlescore = {0}", root.battlescore); Console.WriteLine("combo = {0}", root.Board.combo); Console.WriteLine("clearrow = {0}", root.Board.clearrow); Console.WriteLine("movetime = {0}", root.finmino.path.movetime); Console.WriteLine("name = {0}", root.finmino.name); Console.WriteLine("Tspin = {0}", root.finmino.Tspin); Console.WriteLine("isb2bclear = {0}", root.Board.isb2bclear); Console.WriteLine("nodebattlescore = {0}", bot.evalweight.evalbattle(root)); Console.WriteLine(root.score); Console.WriteLine("maxdepth = {0}", root.maxdepth); //Console.WriteLine("scoreex = {0}", root.scoreex); //Console.WriteLine(bot.nodequeue.Count); //Console.WriteLine(root.pieceidx); //Console.WriteLine(root.Board.piece.name); //root.res.print(); //foreach (int a in root.Board.column_height) //{ // Console.Write(a); // Console.Write(" "); //} } //foreach (int a in root.Board.column_height) //{ // Console.Write(a); // Console.Write(" "); //} Console.WriteLine(""); //root.res.print(); Console.WriteLine("-----------------------------------------------"); root.finmino.console_print(); if (root.holdpiece != -1) { defaultop.demino.getmino(root.holdpiece).console_print(); } // char a1 = Console.ReadKey().KeyChar; //char a2 = Console.ReadKey().KeyChar; //foreach (tree a in bot.boardtree.treenode) //{ // //a.Board.console_print(false); // //char a1 = Console.ReadKey().KeyChar; //} //bot.add_next(2); //foreach (tree a in bot.boardtree.treenode) //{ // bot.extend_node(a); // foreach (tree a1 in a.treenode) // { // a1.Board.console_print(false); // char a2 = Console.ReadKey().KeyChar; // //char a1 = Console.ReadKey().KeyChar; // } //} } //foreach (tree root in ans) //{ // root.Board.console_print(false); // Console.WriteLine("resroot"); // Console.WriteLine(root.score); // Console.WriteLine(bot.nodequeue.Count); // Console.WriteLine(root.pieceidx); // Console.WriteLine(root.Board.piece.name); // root.res.print(); //} } }
} //场地评分 //public static double evalhole(tree node) //{ // double score = 0; // int roof = 0; // foreach (int a in node.Board.column_height) // { // roof = Math.Max(a, roof); // } // int digrow = 0; // 上层被挖开的所需层数 // double[] DIG = new double[node.Board.column_height.Length]; // int[] fulldig = new int[40]; // for (int row = roof - 1; row >= 0; --row) // { // int nextdig = 0;// 该层被挖开的所需层数 // for (int cell = 0; cell < node.Board.column_height.Length; ++cell) // { // if (!node.Board.field[row, cell]) // { // fulldig[row]++; // //if (row + 1 < node.Board.column_height[cell]) // if (node.Board.field[row + 1, cell]) // { // int temp = Math.Max(digrow, fulldig[row + 1] - fulldig[node.Board.column_height[cell]]); // nextdig = Math.Max(temp, nextdig); // score += temp * W.downstack; // } // else // { // if (DIG[cell] < 1000000) // DIG[cell] *= 5; // score += DIG[cell] * W.downstack; // } // } // } // fulldig[row] += fulldig[row + 1]; // for (int cell = 0; cell < node.Board.column_height.Length; ++cell) // { // if (node.Board.field[row + 1, cell]) // { // DIG[cell] = nextdig; // } // } // digrow = nextdig; // } // return score; //} // 空洞(可挖性评分; public evalresult evalnode(tree node) { return(new evalresult()); // pass // 评判场地 以及其他的各种状态 }
// 安全距离增加扣分 //public static int evalTmino() //{ //} public int evalhole(tree node, ref evalresult res) //问题很大。jpg 另外攻击意识修改 { int[] colhight = node.Board.column_height; int roof = 0; int score = 0; for (int i = 0; i < colhight.Length; ++i) { roof = Math.Max(colhight[i], roof); } int nextsafedis = 0; int safedis = 0; // 该行的安全堆叠层数基数 即上一次层的挖开数 + 1 // 加入dig int[] Dig = new int[10]; int[] fulldig = new int[40]; for (int row = roof - 1; row >= 0; --row) { bool canclear = true; safedis = nextsafedis; res.safedis[row] = safedis; int downcnt = safedis; for (int i = 0; i < 10; ++i) { if (!node.Board.field[row, i]) // colh { fulldig[row]++; if (colhight[i] >= row + 1) { canclear = false; // 最好检测一下是否封闭 if (node.Board.field[row + 1, i]) { int temp = Math.Max(downcnt, colhight[i] - row - 1) + 1; //score += W.safecost * temp; score += W.linefull * (fulldig[row + 1] - fulldig[row + temp]); res.linefull += W.linefull * (fulldig[row + 1] - fulldig[row + temp]); nextsafedis = Math.Max(nextsafedis, downcnt + 1); nextsafedis = Math.Max(nextsafedis, colhight[i] - row - 1); // 这个safedis需不需要下传 不依托与上层传递时 挖开这层的最少消行数 // 安全距离失误? } else { // 与上一个洞连接 理应传递上一层洞的挖开数 //score += W.safecost * safedis; int temp = Math.Max(downcnt - 1, colhight[i] - row - 1) + 1; score += W.linefull * (fulldig[row + 1] - fulldig[row + temp]); res.linefull += W.linefull * (fulldig[row + 1] - fulldig[row + temp]); nextsafedis = Math.Max(nextsafedis, downcnt); } } //if (colhight[i] == h + 1) // 这东西有啥用 //{ // // 露天 // holecnt++; //} //else if (colhight[i] >= h) //{ // canclear = false; // holecnt++; // // 依托于顶部 //} } } // 空格数目 // 如果顶上也是洞 再减 fulldig[row] += fulldig[row + 1]; if (canclear) { nextsafedis = safedis + 1; // 思考 //safedis = 0; } for (int i = 0; i < 10; ++i) //洞的层数 需要增加 { if (!node.Board.field[row, i]) // colh 检查!! 检查算法 { if (colhight[i] >= row + 1) { score += W.safecost * safedis /** Math.Max(nextsafedis - safedis, 0)*/; res.safe += W.safecost * safedis; // 似乎有失误 if (colhight[i] - row - 1 > (int)(1.5 * (safedis - row - 1))) { score += W.downstack * (colhight[i] - row - 1 - (int)(1.5 * (safedis - row - 1))); } else if (colhight[i] - row - 1 < (int)((safedis - row - 1))) { score += W.downstack * ((int)((safedis - row - 1)) - colhight[i] + row + 1); } } } } } return(score); }
public int evalhole(tree node, int[] colhight, int h, ref int score) // 造洞的分析 边缘空洞 { if (h >= 27) { return(0); // 或直接对堵洞判断 } bool canclear = true; int holecnt = 0; int downcnt = evalhole(node, colhight, h + 1, ref score); int nextsafedis = downcnt; int safedis = downcnt; // 该行的安全堆叠层数基数 即上一次层的挖开数 + 1 for (int i = 0; i < 10; ++i) { if (!node.Board.field[h, i]) // colh { if (colhight[i] >= h + 1) { canclear = false; // 最好检测一下是否封闭 if (node.Board.field[h + 1, i]) { nextsafedis = Math.Max(nextsafedis, downcnt + 1); nextsafedis = Math.Max(nextsafedis, colhight[i] - h - 1); // 这个safedis需不需要下传 不依托与上层传递时 挖开这层的最少消行数 // 安全距离失误? } else { // 与上一个洞连接 理应传递上一层洞的挖开数 nextsafedis = Math.Max(nextsafedis, downcnt); } holecnt++; } //if (colhight[i] == h + 1) // 这东西有啥用 //{ // // 露天 // holecnt++; //} //else if (colhight[i] >= h) //{ // canclear = false; // holecnt++; // // 依托于顶部 //} } } // 空格数目 // 如果顶上也是洞 再减 if (canclear) { nextsafedis = 0; safedis = 0; } for (int i = 0; i < 10; ++i) //洞的层数 需要增加 { if (!node.Board.field[h, i]) // colh 检查!! 检查算法 { if (colhight[i] >= h + 1) { score += W.safecost * safedis /** Math.Max(nextsafedis - safedis, 0)*/; if (colhight[i] - h - 1 > (int)(1.3 * (safedis - h - 1))) { score += W.downstack * (colhight[i] - h - 1 - (int)(1.3 * (safedis - h - 1))); } } } } return(nextsafedis); }
public tree requset_next_move(int jeo = 0) { // movereslut //if (boardtree.treenode.Count == 0) // return false; foreach (tree node in boardtree.treenode) { node.atkscore = evalweight.evalatkdef(node); if (node.attack > 0) { node.atkscore += Math.Min(node.def + node.maxdef - jeo, 0) * (-9999); } else { node.atkscore += -9999 * jeo; } } boardtree.treenode.Sort((a, b) => { long o = (b.score - a.score); var q = b.maxdepth - a.maxdepth; if (q != 0) { return(q); } if (o == 0) { return(0); } return(o > 0 ? 1 : -1); }); // 用不同方式排序 //int aa = nodedep(boardtree); for (int i = 1; i < boardtree.treenode.Count; ++i) { freenode(boardtree.treenode[i]); } //aa = nodedep(boardtree); if (boardtree.treenode.Count == 0) { Board.isdead = true; return(boardtree); } boardtree = boardtree.treenode[0]; // 节点不存在的问题 boardtree.father = null; if (!boardtree.isextend) { Console.WriteLine("当前节点未扩展"); boardtree.inplan = true; } //else int lastscore = 498; //for (int i = 0, cnt = 0; cnt < 20 && i < boardtree.treenode.Count; ++i) //{ // if (lastscore == boardtree.treenode[i].res.score) continue; // cnt++; // if (!boardtree.treenode[i].isextend) { boardtree.treenode[i].inplan = true; } // lastscore = boardtree.treenode[i].res.score; //} //extend_node(); // aa = nodedep(boardtree); System.GC.Collect(); //eval.evalfield(boardtree); // 重置nodequeue return(boardtree); }
public void extend_node() // 前两层可能可以放宽要求 // 考虑给tspin单独一层循环 { // bool flag = true; //while (calcdepth < nextquene.Count - 1) // 能够保持combo的要继续计算 无hold 会少计算一片 while (true) // 能够保持combo的要继续计算 无hold 会少计算一片 { nodequeue = new List <tree>(); nodeadd(boardtree); if (nodequeue.Count == 0) { break; // 异步时改为continue; } calcdepth += 1; flag = false; List <tree> nextpiece = new List <tree>(); int limit = 5; int qq = nodecnt(boardtree); // 会浪费时间吗 limit = Math.Min(nodequeue.Count, 6); nodequeue.Sort((a, b) => { long o = (b.score - a.score); var q = b.maxdepth - a.maxdepth; if (q != 0) { return(q); } if (o == 0) { return(0); } return(o > 0 ? 1 : -1); } ); // 全重置 haishinodequeue int lastscore = 498; HashSet <tree> nodefather = new HashSet <tree>(); for (int j = 0, cnt = 0; j < nodequeue.Count; ++j) // 剪枝思考 深度和分数的符合思考 { // cnt < Math.Max(nodequeue.Count / 20 + 1, limit) && //if (cnt > 10) //{ // //nodequeue[j].useless = true; // continue; //} if (nextcnt <= nodequeue[j].pieceidx || !nodequeue[j].inplan) { continue; } //nodequeue[j].inplan = false; //if (lastscore == nodequeue[j].res.score) //{ // //bool tag = true; // //for (int i = 0; i < 10; ++i) // //{ // // if (nodequeue[j - 1].Board.column_height[i] != nodequeue[j].Board.column_height[i] ) // // { // // tag = false; // // } // //} // //if (tag) { // nodequeue[j].fieldscore = -9999999; // nodequeue[j].useless = true; // //} //} if (cnt >= 6) { //nodequeue[j].inplan = false; break; } if (lastscore == nodequeue[j].res.score) { continue; } lastscore = nodequeue[j].res.score; flag = true; tree node = nodequeue[j]; if (node == null || node.useless) { nodequeue[j] = null; continue; } ; // 等下打上无用标记 // 好节点后可跟2层无用节点 if (nodequeue[j].father != null) { nodefather.Add(nodequeue[j].father); } cnt++; } if (nodefather.Count == 0) { if (!nodequeue[0].isextend) { nodequeue[0].findalladd(this); } //if (node.isdead) return; nodequeue[0].isextend = true; nodequeue[0].treenode.Sort((a, b) => { long o = (b.score - a.score); var q = b.maxdepth - a.maxdepth; if (q != 0) { return(q); } if (o == 0) { return(0); } return(o > 0 ? 1 : -1); }); } foreach (tree father in nodefather) { for (int j = 0, cnt = 0; j < father.treenode.Count; ++j) { if (nextcnt <= father.treenode[j].pieceidx || !father.treenode[j].inplan) { continue; } //father.treenode[j].inplan = false; if (cnt >= 6) { //nodequeue[j].inplan = false; break; } if (lastscore == father.treenode[j].res.score) { continue; } lastscore = father.treenode[j].res.score; flag = true; tree node = father.treenode[j]; //if (node == null || node.useless) //{ // nodequeue[j] = null; // continue; //}; cnt++; if (!node.isextend) { node.findalladd(this); } //if (node.isdead) return; node.isextend = true; node.treenode.Sort((a, b) => { long o = (b.score - a.score); var q = b.maxdepth - a.maxdepth; if (q != 0) { return(q); } if (o == 0) { return(0); } return(o > 0 ? 1 : -1); }); } } foreach (tree node in nodequeue) { node.inplan = false; } } }
public evalresult evalfield(tree node) { int score = 0; evalresult evalresult = new evalresult(); if (node.finmino.minopos.x >= 18) { node.isdead = true; evalresult.score = -99999999; return(evalresult); } int[] colh = new int[node.Board.column_height.Length + 2]; for (int i = 0; i < node.Board.column_height.Length; ++i) { colh[i + 1] = node.Board.column_height[i]; } colh[0] = colh[colh.Length - 1] = 60; int height = Math.Max(Math.Max(colh[4], colh[5]), Math.Max(colh[6], colh[7])); // 高度评分 evalresult.height = height * W.height[height / 7]; score += height * W.height[height / 7]; // 场地最低点 int minhigh = 40; for (int i = 1; i < colh.Length - 1; ++i) { minhigh = Math.Min(minhigh, colh[i]); } int minidx = 1; // 场地最低点 int mindel = 0; for (int i = 1; i < colh.Length - 1; ++i) { if (minhigh == colh[i] && Math.Min(colh[i - 1], colh[i + 1]) - colh[i] >= mindel) { minidx = i; mindel = Math.Min(colh[i - 1], colh[i + 1]) - colh[i]; } } evalresult.minidx = minidx; evalresult.minhigh = colh[minidx]; score += W.dephigh * colh[minidx]; score += W.col_minhigh[minidx - 1] * Math.Min(mindel, 5); if (mindel > 7) { score -= Math.Abs(W.col_minhigh[minidx - 1]) * mindel; } // 长洞(? // 深洞本身高度扣分 过深扣分 Queue <int> deepholequeue = new Queue <int>(); for (int i = 1; i < colh.Length - 1; ++i) { int left = colh[i - 1] - colh[i]; int right = colh[i + 1] - colh[i]; if (left >= 2 && right >= 2) // 都大于5制裁 { if (i != minidx || minhigh != 0) { //score += W.deephole * Math.Min(left, right); //evalresult.deephole += W.deephole * Math.Min(left, right); // duojinzhicai deepholequeue.Enqueue(Math.Min(left, right) /**+ Math.Max(left, right) / 2.0**/); } } } foreach (int a in deepholequeue) { //score += W.deephole * a; // 加入深洞底部厚度 score += W.deephole * a * deepholequeue.Count; evalresult.deephole += W.deephole * a * deepholequeue.Count; // duojinzhicai } deepholequeue.Clear(); // 凹形判定 // 单长洞考虑不扣 int lefidx = minidx - 1, ritidx = minidx + 1; int lefhig = colh[lefidx], rithig = colh[ritidx]; while (lefidx > 1) { if (colh[lefidx - 1] >= lefhig) // 大于太多也扣分(? { lefhig = colh[lefidx - 1]; } else { evalresult.wide += W.wide * (lefhig - colh[lefidx - 1]); score += W.wide * (lefhig - colh[lefidx - 1]); } lefidx -= 1; } while (ritidx < colh.Length - 1) { if (colh[ritidx + 1] >= rithig) { rithig = colh[ritidx + 1]; } else { evalresult.wide += W.wide * (rithig - colh[ritidx + 1]); score += W.wide * (rithig - colh[ritidx + 1]); } ritidx += 1; } // 连续性判定 for (int i = 2; i < colh.Length - 1; ++i) { int del; del = colh[i] - colh[i - 1]; //right = colh[i + 1] - colh[i]; //if (left >= 3 && right >= 3) score += Math.Abs(del) * W.deltcol; evalresult.Continuity += Math.Abs(del) * W.deltcol; } // 连续性 double avg = 0; for (int i = 1; i < colh.Length - 1; ++i) { avg += colh[i]; } // 平均值 // 是否减去最低点 //avg = (avg - minhigh) / (node.Board.column_height.Length - 1); avg /= node.Board.column_height.Length; // 方差 标准差 double bus_sq = 0, bus = 0; for (int i = 1; i < colh.Length - 1; ++i) { bus_sq += Math.Pow(colh[i] - avg, 2); } //bus_sq -= Math.Pow(minhigh - avg, 2); //bus = Math.Sqrt(bus_sq); // 方差 标准差 //score += bus * W.bus + bus_sq * W.bus_sq; //score += (int)(bus * W.bus); // // 奇偶性 int parity = evalparity(node); score += parity * W.parity; evalresult.parity += parity * W.parity; evalresult.hole = evalhole(node, ref evalresult); //evalhole(node, node.Board.column_height, 0, ref evalresult.hole); score += evalresult.hole; evalresult.score = score; return(evalresult); } //场地评分