chesspi_ai.cpp 4.5 KB
Newer Older
D
dev@dev.com 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <cstdio>
#include <memory.h>
#include <vector>
#include <string>
#include <cassert>
#include <algorithm>
#include <set>
#include <unordered_set>
#include <cmath>
#include <omp.h>
#include <atomic>
#include "chesspi.h"

D
dev@dev.com 已提交
14 15
static const unsigned int table_cost[16] = {1000000,150,150,150,150,150,150,500,500,150,150,100,100,100,100,100};
float calc_cost(const int coordx[/*32*/], const int coordy[/*32*/],const int alive[/*32*/],const int killed,const int idx)
D
dev@dev.com 已提交
16
{
D
dev@dev.com 已提交
17 18

	//	 * 帅士士相相马马车车炮炮兵兵兵兵兵  將仕仕象象馬馬車車砲砲卒卒卒卒卒
D
dev@dev.com 已提交
19 20 21

	assert(idx >= 16);

D
dev@dev.com 已提交
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
	unsigned int rescost = table_cost[idx%16];
	//位置加权
	switch (idx % 16) {
	//相士双全时击杀价值高
	case 1:
	case 2:
	case 3:
	case 4:
		if (alive[(idx-1)/2*2+1] || alive [(idx-1)/2*2+2])
			rescost *= 2;
		break;
	//马战线挺进,以及后期击杀价值高
	case 5:
	case 6:
		if (idx<16 )
			rescost *= 1+(coordy[idx]/3.0);
		else
			rescost *= 1+((11-coordy[idx])/3.0);
		rescost *= 1 + killed / 4.0;
		break;
	//车战线击杀高
	case 7:
	case 8:
		if (idx<16 )
			rescost *= 1+(coordy[idx]/3.0);
		else
			rescost *= 1+((11-coordy[idx])/3.0);
		break;
	//炮前期击杀高
	case 9:
	case 10:
		if (idx<16 )
			rescost *= 1+(coordy[idx]/3.0);
		else
			rescost *= 1+((11-coordy[idx])/3.0);
		rescost *= 1 + (32 - killed) / 4.0;
		break;
	//卒过河击杀高
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
		if (idx<16 )
			rescost *= coordy[idx]>5?4:1;
		else
			rescost *= coordy[idx]<6?4:1;
		//当头卒价值高
		if (coordx[idx]==5 && (coordy[idx]==4 || coordy[idx]==7))
			rescost *=10;
		break;
	default:
		break;
	}


D
dev@dev.com 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

	return rescost;
}

std::vector<chess_node> build_tree(const chess_node & root, const int side,const std::vector<chess_node> & history)
{
	std::vector<chess_node> tree;
	std::unordered_set <std::string> dict;
	for (const chess_node & n: history)
		dict.insert(node2hash(n.coords,n.alive));
	tree.push_back(root);
	tree[0].side = side % 2;
	tree[0].depth = 0;

	size_t curr_i = 0;
93
	size_t max_nodes = 1024*1024*8;
D
dev@dev.com 已提交
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
	while (tree.size()<=max_nodes && curr_i<tree.size())
	{
		const size_t ts = tree.size();
		const int cores = omp_get_num_procs();
		std::vector<std::vector<chess_node> > vec_appends;
		for (int i=0;i<cores;++i)
			vec_appends.push_back(std::vector<chess_node>());
		std::atomic<int> new_appends (0);
#pragma omp parallel for
		for (int i=curr_i;i<ts;++i)
		{
			if (new_appends + ts >=max_nodes)
				continue;
			const unsigned char clock = tree[i].depth;
			const int tid = omp_get_thread_num();
			if ((tree[i].alive & 0x00010001)==0x00010001)
			{
				const int curr_side = (side + clock) % 2;
				std::vector<chess_node> next_status =
						expand_node(tree[i],curr_side);

				const size_t sz = next_status.size();
				for (size_t j=0;j<sz;++j)
				{
					std::string ha = node2hash(next_status[j].coords,next_status[j].alive);
					bool needI = false;
#pragma omp critical
					{
						if (dict.find(ha)==dict.end())
						{
							needI = true;
							dict.insert(ha);
						}
					}
					if (needI)
					{
						next_status[j].parent = i;
						next_status[j].side = curr_side;
						next_status[j].depth = clock+1;
						vec_appends[tid].push_back(next_status[j]);
						++tree[i].leaves;
						++new_appends;
					}
				}
			}
		}
		for (int i=0;i<cores;++i)
		{
			if (vec_appends[i].size())
				std::move(vec_appends[i].begin(),vec_appends[i].end(),std::back_inserter(tree));
		}
		curr_i += (ts - curr_i);
	}

	//printf ("\nDepth = %d\n",tree.rbegin()->depth);

	return tree;
}

size_t judge_tree(std::vector<chess_node> & tree)
{
	const size_t total_nodes = tree.size();
	if (total_nodes<2)
		return 0;
	int side = tree[0].side;
	size_t i = total_nodes - 1;
	while (i > 0)
	{
		if (tree[i].side==0)
		{
D
dev@dev.com 已提交
164
			float ratio = sqrt((tree[i].jump_cost[1]+1) / (tree[i].jump_cost[0]+1)/ sqrt(tree[i].jump_cost[0]+1));
D
dev@dev.com 已提交
165 166 167 168
			tree[i].weight = ratio;
		}
		else
		{
D
dev@dev.com 已提交
169
			float ratio = sqrt((tree[i].jump_cost[0]+1) / (tree[i].jump_cost[1]+1)/ sqrt(tree[i].jump_cost[1]+1));
D
dev@dev.com 已提交
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
			tree[i].weight = ratio;
		}
		size_t parent = tree[i].parent;
		tree[parent].jump_cost[0] += tree[i].jump_cost[0] * tree[i].weight/tree[i].depth/tree[i].depth;
		tree[parent].jump_cost[1] += tree[i].jump_cost[1] * tree[i].weight/tree[i].depth/tree[i].depth;
		--i;
	}

	size_t p = 1;
	float max_v = 0;
	int max_p = 1;
	while (p<total_nodes)
	{
		if (tree[p].parent)
			break;
		//float v = (tree[p].jump_cost[1-side]+1)/(tree[p].jump_cost[side]);
		float v = (tree[p].weight);
		if (v > max_v)
		{
			max_v = v;
			max_p = p;
		}
		++p;
	}
	return max_p;
}