File indexing completed on 2024-11-24 03:43:17
0001 /******************************************************************* 0002 * 0003 * Copyright 2009 Pelladi Gabor <pelladigabor@gmail.com> 0004 * 0005 * Bovo is free software; you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation; either version 2, or (at your option) 0008 * any later version. 0009 * 0010 * Bovo is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with Bovo; see the file COPYING. If not, write to 0017 * the Free Software Foundation, 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 * 0020 ********************************************************************/ 0021 0022 #include "node.h" 0023 #include "ai_impl.h" 0024 0025 #include <cassert> 0026 0027 Node::Node(Standing *_standing, AiImpl *ai) 0028 : standing(_standing) 0029 , parent(nullptr) 0030 , child(nullptr) 0031 , depth(0) 0032 , signum(_standing->current == 0 ? 1 : -1) 0033 , alpha(MinHeur - 1) 0034 , beta(MaxHeur + 1) 0035 , is_exact(false) 0036 , evaluated(false) 0037 , depth_limit(ai->depth_limit) 0038 , max_branch(ai->max_branch) 0039 { 0040 generateSteps(); 0041 } 0042 0043 Node::Node(Standing *_standing, Node *_parent) 0044 : standing(_standing) 0045 , parent(_parent) 0046 , child(nullptr) 0047 , depth(_parent->depth + 1) 0048 , signum(-(_parent->signum)) 0049 , alpha(_parent->alpha) 0050 , beta(_parent->beta) 0051 , is_exact(false) 0052 , evaluated(false) 0053 , depth_limit(_parent->depth_limit) 0054 , max_branch(_parent->max_branch) 0055 { 0056 generateSteps(); 0057 } 0058 0059 Node::~Node() 0060 { 0061 delete child; 0062 delete standing; 0063 qDeleteAll(steps); 0064 } 0065 0066 void Node::generateSteps() 0067 { 0068 steps.clear(); 0069 if (depth >= depth_limit || standing->target) { 0070 heur_T hv = standing->hval; 0071 heur_T decay = depth_decay * depth; 0072 if (hv > 0) 0073 hv -= decay; 0074 else if (hv < 0) 0075 hv += decay; 0076 if (-decay <= hv && hv <= decay) 0077 hv = 0; 0078 alpha = beta = hv; 0079 evaluated = true; 0080 return; 0081 } 0082 0083 suggestions_T suggestions; 0084 standing->getSuggestions(suggestions); 0085 0086 for (suggestions_T::iterator s = suggestions.begin(); s != suggestions.end(); ++s) { 0087 pos_T x = s->x; 0088 pos_T y = s->y; 0089 assert(!standing->table[x][y]); 0090 auto p = new Standing(*this->standing); 0091 p->step(x, y); 0092 0093 heur_T pv = p->hval * signum; 0094 steps_T::iterator i; 0095 for (i = steps.begin(); i != steps.end() && signum * (*i)->hval > pv; ++i) 0096 ; 0097 steps.insert(i, p); 0098 0099 // we only keep the best looking positions 0100 if ((unsigned int)steps.size() > max_branch) { 0101 delete steps.back(); 0102 steps.pop_back(); 0103 } 0104 } 0105 assert(steps.size() > 0); 0106 } 0107 0108 void Node::calcHash(hash_T *hash, NodeHashData *data) 0109 { 0110 data->remaining_depth = depth_limit - depth; 0111 assert(data->remaining_depth > 0); 0112 0113 hash_T c_hash = 0; 0114 for (int i = 0; i < standing->table_size_x; i++) { 0115 for (int j = 0; j < standing->table_size_y; j++) { 0116 c_hash = c_hash * 3145 + standing->table[i][j]; 0117 } 0118 } 0119 c_hash += standing->current; 0120 data->checksum = c_hash; 0121 0122 c_hash = 0; 0123 for (int i = 0; i < standing->table_size_x; i++) { 0124 for (int j = 0; j < standing->table_size_y; j++) { 0125 c_hash = (c_hash * 5313 + standing->table[i][j]) % nodeHashSize; 0126 } 0127 } 0128 c_hash += standing->current; 0129 *hash = c_hash; 0130 }