// 安全距离增加扣分 //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 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 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); } //场地评分