├── legacy ├── cython_execute.py ├── AI_Cython │ ├── ai_cython.py │ ├── setup.py │ ├── compile_cython.py │ └── ai_cython.pyx ├── AI_ML │ ├── model.sav │ ├── learn.py │ ├── create_data.py │ └── ai_cpp.cpp ├── setup.py ├── compile_cython.py ├── AI_Cpp │ ├── 20210618 │ │ └── ai_fast.cpp │ ├── adjust_parameter_sa.py │ ├── smoothing_parameter.py │ ├── adjust_parameter_ga.py │ └── ai_mcts.cpp └── AI_Python │ └── ai_python.py ├── .gitignore ├── compile.py ├── README.md ├── LICENSE ├── param.txt ├── pattern_compress.py ├── adjust_pattern_hand.py ├── const.txt ├── main.py ├── auto_game.py ├── check_pattern_param.py ├── adjust_params.py └── adjust_pattern.py /legacy/cython_execute.py: -------------------------------------------------------------------------------- 1 | import ai_cython_exe -------------------------------------------------------------------------------- /legacy/AI_Cython/ai_cython.py: -------------------------------------------------------------------------------- 1 | import ai_cython_exe -------------------------------------------------------------------------------- /legacy/AI_ML/model.sav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nyanyan/Reversi/HEAD/legacy/AI_ML/model.sav -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | data 3 | a.exe 4 | b.exe 5 | third_party 6 | param0.txt 7 | param1.txt 8 | param_base.txt 9 | param_pattern_hand.txt 10 | patttern_weight.txt 11 | state.txt 12 | create_param_arr.py 13 | ai_cython_exe.cp38-win_amd64.pyd 14 | adjust_pattern.cpp 15 | a.txt 16 | param_pattern_compress.txt 17 | -------------------------------------------------------------------------------- /legacy/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | from Cython.Build import cythonize 3 | from numpy import get_include # cimport numpy を使うため 4 | 5 | filename = input() 6 | 7 | ext = Extension("ai_cython_exe", sources=[filename], include_dirs=['.', get_include()]) 8 | setup(name="ai_cython_exe", ext_modules=cythonize([ext])) 9 | 10 | f = open('ai_cython_exe.cp38-win_amd64.pyd') 11 | f.close() 12 | -------------------------------------------------------------------------------- /legacy/AI_Cython/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | from Cython.Build import cythonize 3 | from numpy import get_include # cimport numpy を使うため 4 | 5 | filename = input() 6 | 7 | ext = Extension("ai_cython_exe", sources=[filename], include_dirs=['.', get_include()]) 8 | setup(name="ai_cython_exe", ext_modules=cythonize([ext])) 9 | 10 | f = open('ai_cython_exe.cp38-win_amd64.pyd') 11 | f.close() 12 | -------------------------------------------------------------------------------- /compile.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | 4 | argv = sys.argv 5 | 6 | if len(argv) < 2: 7 | print('arg err') 8 | exit() 9 | 10 | out_name = 'a.exe' if len(argv) == 2 else argv[2] 11 | 12 | cmd = 'g++ ' + argv[1] + ' -O3 -march=native -fexcess-precision=fast -funroll-loops -flto -mtune=native -o ' + out_name 13 | o = subprocess.run(cmd.split(), encoding='utf-8', stderr=subprocess.STDOUT, timeout=None) 14 | print('------------------compile done------------------') -------------------------------------------------------------------------------- /legacy/compile_cython.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | import os 4 | 5 | argv = sys.argv 6 | 7 | cmd = 'python setup.py build_ext --inplace' 8 | try: 9 | o = subprocess.run(cmd.split(), input=argv[1], encoding='utf-8', stderr=subprocess.STDOUT, timeout=None) 10 | except subprocess.CalledProcessError as e: 11 | print('ERROR:', e.stdout) 12 | exit() 13 | 14 | with open('ai_cython_exe.cp38-win_amd64.pyd', 'r') as f: 15 | pass 16 | 17 | print('------------------compile done------------------') -------------------------------------------------------------------------------- /legacy/AI_Cython/compile_cython.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | import os 4 | 5 | def debug(*args): print(*args, file=sys.stderr) 6 | 7 | cmd = 'python setup.py build_ext --inplace' 8 | try: 9 | o = subprocess.run(cmd.split(), input='ai_cython.pyx', encoding='utf-8', stderr=subprocess.STDOUT, timeout=None) 10 | except subprocess.CalledProcessError as e: 11 | debug('ERROR:', e.stdout) 12 | exit() 13 | 14 | with open('ai_cython_exe.cp38-win_amd64.pyd', 'r') as f: 15 | pass 16 | 17 | debug('------------------compile done------------------') -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reversi 2 | 3 | ## How to start (person vs person) 4 | open ```main.py``` and check that ```ai_mode``` is False. 5 | Then type 6 | ``` 7 | $ python main.py 8 | ``` 9 | 10 | ## How to start (person vs AI) 11 | 12 | ### Compile 13 | 14 | To compile `ai_cpp.cpp`, type 15 | 16 | ``` 17 | $ python compile.py ai_cpp.cpp 18 | ``` 19 | 20 | ### Execute 21 | 22 | Type 23 | 24 | ``` 25 | $ python main.py 26 | ``` 27 | then, the following description appears: 28 | ``` 29 | PERSON: person vs person 30 | BLACK: person(black) vs AI(white) 31 | WHITE: AI(black) vs person(white) 32 | choose: # type your choice 33 | ``` 34 | 35 | ## How to play 36 | For each actions, you type a coordinate. For example, 37 | ``` 38 | a b c d e f g h 39 | 1 . . . . . . . . 40 | 2 . . . . . . . . 41 | 3 . . . * . . . . 42 | 4 . . * X O . . . 43 | 5 . . . O X * . . 44 | 6 . . . . * . . . 45 | 7 . . . . . . . . 46 | 8 . . . . . . . . 47 | Black:c4 48 | ``` 49 | Place that you can place is shown as ```*```. 50 | If you place a stone on the right-down corner, you should write ```h8```. 51 | 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nyanyan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /param.txt: -------------------------------------------------------------------------------- 1 | 0.0 2 | 0.0 3 | 0.0 4 | 0.0 5 | 4.0 6 | 3.0 7 | 4.0 8 | 2.0 9 | 9.0 10 | 5.0 11 | 6.0 12 | 6.0 13 | 5.0 14 | 8.38 15 | 5.69 16 | 9.13 17 | 5.45 18 | 6.98 19 | 6.66 20 | 9.38 21 | 6.98 22 | 9.29 23 | 7.29 24 | 9.32 25 | 7.37 26 | 9.94 27 | 7.14 28 | 9.78 29 | 7.31 30 | 10.95 31 | 7.18 32 | 9.78 33 | 7.76 34 | 9.21 35 | 7.33 36 | 8.81 37 | 7.2 38 | 8.48 39 | 7.23 40 | 8.0 41 | 6.92 42 | 7.57 43 | 6.62 44 | 7.13 45 | 6.38 46 | 6.54 47 | 5.96 48 | 6.18 49 | 5.62 50 | 5.64 51 | 5.18 52 | 5.18 53 | 4.6 54 | 4.48 55 | 4.06 56 | 3.67 57 | 3.39 58 | 3.11 59 | 2.66 60 | 2.3 61 | 1.98 62 | 1.53 63 | 1.78 64 | 0.67 65 | 0.288 66 | -0.115 67 | 0.0 68 | -0.0096 69 | -0.1542 70 | -0.0288 71 | -0.0288 72 | 0.0 73 | -0.0096 74 | -0.0096 75 | 0.5 76 | 1.8 77 | 1.9 78 | -0.2011547613418304 79 | 0.05256421779943 80 | 0.079657943106798 81 | 0.6064154229278483 82 | 0.9510851378461812 83 | 0.7298915374395087 84 | 1.5074239387106616 85 | 1.4748191052602564 86 | 0.40072611426043 87 | 1.6670085089149844 88 | 1.8988640141207755 89 | 2.052469793113826 90 | 3.237677335263519 91 | 3.3740480754567748 92 | 1.5350314798267053 93 | 1.7 94 | 2.0 95 | 0.7 96 | 0.474054 97 | 0.345462 98 | 0.472862 99 | 0.125835 100 | 0.168511 101 | 0.139245 102 | 0.0 103 | 0.4998 104 | 0.144653 105 | -0.552854 106 | 0.247642 107 | 0.314905 108 | 0.53779 109 | 0.31567 110 | 0.170627 111 | -------------------------------------------------------------------------------- /pattern_compress.py: -------------------------------------------------------------------------------- 1 | char_s = 35 2 | char_e = 91 3 | num_s = 93 4 | num_e = 126 5 | ln = char_e - char_s 6 | 7 | pattern_all = 85293 8 | 9 | vals = [] 10 | with open('param_pattern.txt', 'r') as f: 11 | for _ in range(pattern_all): 12 | vals.append(float(f.readline())) 13 | 14 | vals_variation = sorted(list(set(vals))) 15 | around = [0 for _ in range(1000)] 16 | err = 0.0 17 | step = 0.0001 18 | while len(around) > char_e - char_s: 19 | err += step 20 | around = [] 21 | i = 0 22 | while i < len(vals_variation): 23 | avg = vals_variation[i] 24 | cnt = 1 25 | for j in range(i + 1, len(vals_variation)): 26 | if vals_variation[j] - vals_variation[i] > err: 27 | break 28 | avg += vals_variation[j] 29 | cnt += 1 30 | around.append(avg / cnt) 31 | i += cnt 32 | around.append(0.0) 33 | around.sort() 34 | print(len(around), char_e - char_s + 1) 35 | print(around) 36 | 37 | res_arr = [] 38 | for i in range(pattern_all): 39 | val = vals[i] 40 | tmp = -1 41 | min_err = 1000.0 42 | for j, k in enumerate(around): 43 | if abs(val - k) < min_err: 44 | min_err = abs(val - k) 45 | tmp = j 46 | res_arr.append(chr(tmp + char_s)) 47 | 48 | super_compress = [] 49 | for i in range(len(res_arr)): 50 | if len(super_compress): 51 | if ord(super_compress[-1]) >= num_s: 52 | if ord(super_compress[-1]) < num_e and super_compress[-2] == res_arr[i]: 53 | super_compress[-1] = chr(ord(super_compress[-1]) + 1) 54 | else: 55 | super_compress.append(res_arr[i]) 56 | else: 57 | if super_compress[-1] == res_arr[i]: 58 | super_compress.append(chr(num_s)) 59 | else: 60 | super_compress.append(res_arr[i]) 61 | else: 62 | super_compress.append(res_arr[i]) 63 | 64 | 65 | with open('param_pattern_compress.txt', 'w') as f: 66 | for i in range(len(super_compress)): 67 | if i % 300 == 0: 68 | f.write('"') 69 | f.write(super_compress[i]) 70 | if i % 300 == 299: 71 | f.write('"\n') 72 | -------------------------------------------------------------------------------- /legacy/AI_Cpp/adjust_parameter_sa.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | from random import random, randint 3 | 4 | def input_param(p, param, grid): 5 | for j in range(param_num): 6 | s = '' 7 | for i in range(max_turn): 8 | s += str(param[i][j]) + ' ' 9 | s += '\n' 10 | p.stdin.write(s.encode('utf-8')) 11 | p.stdin.flush() 12 | for i in range(max_turn): 13 | s = '' 14 | for j in range(hw * hw): 15 | s += str(grid[i][translate[j]]) + ' ' 16 | s += '\n' 17 | p.stdin.write(s.encode('utf-8')) 18 | p.stdin.flush() 19 | 20 | def normalize_weight(arr): 21 | sm = sum(arr) 22 | for i in range(param_num): 23 | arr[i] /= sm 24 | return arr 25 | 26 | def normalize_grid(arr): 27 | t = [4, 8, 8, 8, 4, 8, 8, 4, 8, 4] 28 | for i in range(grid_param_num): 29 | arr[i] *= t[i] 30 | sm = sum(arr) 31 | for i in range(grid_param_num): 32 | arr[i] /= sm 33 | for i in range(grid_param_num): 34 | arr[i] /= t[i] 35 | return arr 36 | 37 | def anneal(tl, param, grid): 38 | strt = time() 39 | while time() - strt < tl: 40 | idx = randint(0, max_turn - 1) 41 | if random() < 0.5: 42 | idx2 = randint(0, param_num - 1) 43 | else: 44 | idx2 = randint(0, grid_param_num - 1) 45 | 46 | 47 | 48 | 49 | hw = 8 50 | param_num = 6 51 | grid_param_num = 10 52 | max_turn = 60 53 | tl = 100 54 | 55 | param = [[0.0 for _ in range(param_num)] for _ in range(max_turn)] 56 | grid = [[0.0 for _ in range(grid_param_num)] for _ in range(max_turn)] 57 | 58 | translate = [ 59 | 0, 1, 2, 3, 3, 2, 1, 0, 60 | 1, 4, 5, 6, 6, 5, 4, 1, 61 | 2, 5, 7, 8, 8, 7, 5, 2, 62 | 3, 6, 8, 9, 9, 8, 6, 3, 63 | 3, 6, 8, 9, 9, 8, 6, 3, 64 | 2, 5, 7, 8, 8, 7, 5, 2, 65 | 1, 4, 5, 6, 6, 5, 4, 1, 66 | 0, 1, 2, 3, 3, 2, 1, 0 67 | ] 68 | 69 | with open('params.txt', 'r') as f: 70 | for j in range(param_num): 71 | for i in range(max_turn): 72 | param[i][j] = float(f.readline()) 73 | for i in range(max_turn): 74 | for j in range(hw * hw): 75 | grid[i][translate[j]] = float(f.readline()) -------------------------------------------------------------------------------- /adjust_pattern_hand.py: -------------------------------------------------------------------------------- 1 | pattern_num = 2 2 | 3 | each_param_num = [10, 8] 4 | 5 | def output(): 6 | with open('param_pattern.txt', 'w') as f: 7 | for i in range(pattern_num): 8 | for j in range(3 ** each_param_num[i]): 9 | f.write('{:f}'.format(ans[i][j]) + '\n') 10 | 11 | def create_nums(s, idx): 12 | if idx == len(s): 13 | return [0] 14 | if s[idx] == '0': 15 | return create_nums(s, idx + 1) 16 | elif s[idx] == '1': 17 | res = [] 18 | for i in create_nums(s, idx + 1): 19 | res.append(i + 3 ** (len(s) - 1 - idx)) 20 | return res 21 | elif s[idx] == '2': 22 | res = [] 23 | for i in create_nums(s, idx + 1): 24 | res.append(i + 2 * (3 ** (len(s) - 1 - idx))) 25 | return res 26 | else: 27 | res = [] 28 | for i in create_nums(s, idx + 1): 29 | res.append(i) 30 | res.append(i + 3 ** (len(s) - 1 - idx)) 31 | res.append(i + 2 * (3 ** (len(s) - 1 - idx))) 32 | return res 33 | 34 | def reverse_num(num): 35 | res = 0 36 | for i in reversed(range(len(s))): 37 | res += (3 ** i) * (num % 3) 38 | num //= 3 39 | return res 40 | 41 | def change_num(num): 42 | res = 0 43 | for i in range(len(s)): 44 | res += (3 ** i) * ((3 - num % 3) % 3) 45 | num //= 3 46 | return res 47 | 48 | ans = [[0 for _ in range(3 ** each_param_num[i])] for i in range(pattern_num)] 49 | 50 | with open('param_pattern.txt', 'r') as f: 51 | for i in range(2): 52 | for j in range(3 ** each_param_num[i]): 53 | ans[i][j] = float(f.readline()) 54 | 55 | while True: 56 | try: 57 | val = float(input('input a value: ')) 58 | s = input('input a number: ') 59 | if len(s) == 10: 60 | idx = 0 61 | else: 62 | idx = 1 63 | nums = create_nums(s, 0) 64 | if idx == 0: 65 | rev_nums = [] 66 | for i in nums: 67 | rev_nums.append(reverse_num(i)) 68 | nums.extend(rev_nums) 69 | for i in nums: 70 | ans[idx][i] = val 71 | ans[idx][change_num(i)] = -val 72 | output() 73 | except: 74 | print('failed') 75 | if input('exit?: ') == 'y': 76 | exit() 77 | -------------------------------------------------------------------------------- /legacy/AI_Cpp/smoothing_parameter.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | from random import random, randint 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | 6 | def input_param(p, param, grid): 7 | for j in range(param_num): 8 | s = '' 9 | for i in range(max_turn): 10 | s += str(param[i][j]) + ' ' 11 | s += '\n' 12 | p.stdin.write(s.encode('utf-8')) 13 | p.stdin.flush() 14 | for i in range(max_turn): 15 | s = '' 16 | for j in range(hw * hw): 17 | s += str(grid[i][translate[j]]) + ' ' 18 | s += '\n' 19 | p.stdin.write(s.encode('utf-8')) 20 | p.stdin.flush() 21 | 22 | def normalize_weight(arr): 23 | sm = sum(arr) 24 | for i in range(param_num): 25 | arr[i] /= sm 26 | return arr 27 | 28 | def normalize_grid(arr): 29 | t = [4, 8, 8, 8, 4, 8, 8, 4, 8, 4] 30 | for i in range(grid_param_num): 31 | arr[i] *= t[i] 32 | sm = sum(arr) 33 | for i in range(grid_param_num): 34 | arr[i] /= sm 35 | for i in range(grid_param_num): 36 | arr[i] /= t[i] 37 | return arr 38 | 39 | def anneal(tl, param, grid): 40 | strt = time() 41 | while time() - strt < tl: 42 | idx = randint(0, max_turn - 1) 43 | if random() < 0.5: 44 | idx2 = randint(0, param_num - 1) 45 | else: 46 | idx2 = randint(0, grid_param_num - 1) 47 | 48 | def func(x, coe): 49 | y = 0.0 50 | for i, c in enumerate(coe): 51 | d = len(coe) - i - 1 52 | y += c * (x ** d) 53 | return y 54 | 55 | def write_output(param, grid): 56 | with open('params.txt', 'w') as f: 57 | for j in range(param_num): 58 | for i in range(max_turn): 59 | f.write(str(param[i][j]) + '\n') 60 | for i in range(max_turn): 61 | for j in range(hw * hw): 62 | f.write(str(grid[i][translate[j]]) + '\n') 63 | 64 | 65 | hw = 8 66 | param_num = 6 67 | grid_param_num = 10 68 | max_turn = 60 69 | tl = 100 70 | param_deg = 5 71 | 72 | param = [[-1000.0 for _ in range(param_num)] for _ in range(max_turn)] 73 | grid = [[-1000.0 for _ in range(grid_param_num)] for _ in range(max_turn)] 74 | 75 | translate = [ 76 | 0, 1, 2, 3, 3, 2, 1, 0, 77 | 1, 4, 5, 6, 6, 5, 4, 1, 78 | 2, 5, 7, 8, 8, 7, 5, 2, 79 | 3, 6, 8, 9, 9, 8, 6, 3, 80 | 3, 6, 8, 9, 9, 8, 6, 3, 81 | 2, 5, 7, 8, 8, 7, 5, 2, 82 | 1, 4, 5, 6, 6, 5, 4, 1, 83 | 0, 1, 2, 3, 3, 2, 1, 0 84 | ] 85 | 86 | with open('params_20210519.txt', 'r') as f: 87 | x = range(max_turn) 88 | for j in range(param_num): 89 | y = [] 90 | for i in range(max_turn): 91 | y.append(float(f.readline())) 92 | coe = np.polyfit(x, y, param_deg) 93 | for k, l in enumerate([func(i, coe) for i in x]): 94 | param[k][j] = l 95 | #plt.plot(x, y) 96 | plt.plot(x, [param[k][j] for k in x], label=j) 97 | plt.legend() 98 | plt.show() 99 | 100 | for j in range(hw * hw // 2): 101 | if grid[0][translate[j]] != -1000.0: 102 | continue 103 | y = [] 104 | for i in range(max_turn): 105 | y.append(float(f.readline())) 106 | coe = np.polyfit(x, y, param_deg) 107 | for k, l in enumerate([func(i, coe) for i in x]): 108 | grid[k][translate[j]] = l 109 | #plt.plot(x, y) 110 | plt.plot(x, [grid[k][translate[j]] for k in x]) 111 | plt.show() 112 | 113 | x = range(max_turn) 114 | y = [] 115 | for i in range(max_turn): 116 | y.append(sum(param[i])) 117 | 118 | 119 | write_output(param, grid) 120 | -------------------------------------------------------------------------------- /const.txt: -------------------------------------------------------------------------------- 1 | 8 2 | 8 3 | 8 4 | 8 5 | 8 6 | 8 7 | 8 8 | 8 9 | 8 10 | 8 11 | 8 12 | 8 13 | 8 14 | 8 15 | 8 16 | 8 17 | 3 18 | 4 19 | 5 20 | 6 21 | 7 22 | 8 23 | 7 24 | 6 25 | 5 26 | 4 27 | 3 28 | 3 29 | 4 30 | 5 31 | 6 32 | 7 33 | 8 34 | 7 35 | 6 36 | 5 37 | 4 38 | 3 39 | 0 40 | 1 41 | 2 42 | 3 43 | 4 44 | 5 45 | 6 46 | 7 47 | 8 48 | 9 49 | 10 50 | 11 51 | 12 52 | 13 53 | 14 54 | 15 55 | 16 56 | 17 57 | 18 58 | 19 59 | 20 60 | 21 61 | 22 62 | 23 63 | 24 64 | 25 65 | 26 66 | 27 67 | 28 68 | 29 69 | 30 70 | 31 71 | 32 72 | 33 73 | 34 74 | 35 75 | 36 76 | 37 77 | 38 78 | 39 79 | 40 80 | 41 81 | 42 82 | 43 83 | 44 84 | 45 85 | 46 86 | 47 87 | 48 88 | 49 89 | 50 90 | 51 91 | 52 92 | 53 93 | 54 94 | 55 95 | 56 96 | 57 97 | 58 98 | 59 99 | 60 100 | 61 101 | 62 102 | 63 103 | 0 104 | 8 105 | 16 106 | 24 107 | 32 108 | 40 109 | 48 110 | 56 111 | 1 112 | 9 113 | 17 114 | 25 115 | 33 116 | 41 117 | 49 118 | 57 119 | 2 120 | 10 121 | 18 122 | 26 123 | 34 124 | 42 125 | 50 126 | 58 127 | 3 128 | 11 129 | 19 130 | 27 131 | 35 132 | 43 133 | 51 134 | 59 135 | 4 136 | 12 137 | 20 138 | 28 139 | 36 140 | 44 141 | 52 142 | 60 143 | 5 144 | 13 145 | 21 146 | 29 147 | 37 148 | 45 149 | 53 150 | 61 151 | 6 152 | 14 153 | 22 154 | 30 155 | 38 156 | 46 157 | 54 158 | 62 159 | 7 160 | 15 161 | 23 162 | 31 163 | 39 164 | 47 165 | 55 166 | 63 167 | 5 168 | 14 169 | 23 170 | 4 171 | 13 172 | 22 173 | 31 174 | 3 175 | 12 176 | 21 177 | 30 178 | 39 179 | 2 180 | 11 181 | 20 182 | 29 183 | 38 184 | 47 185 | 1 186 | 10 187 | 19 188 | 28 189 | 37 190 | 46 191 | 55 192 | 0 193 | 9 194 | 18 195 | 27 196 | 36 197 | 45 198 | 54 199 | 63 200 | 8 201 | 17 202 | 26 203 | 35 204 | 44 205 | 53 206 | 62 207 | 16 208 | 25 209 | 34 210 | 43 211 | 52 212 | 61 213 | 24 214 | 33 215 | 42 216 | 51 217 | 60 218 | 32 219 | 41 220 | 50 221 | 59 222 | 40 223 | 49 224 | 58 225 | 2 226 | 9 227 | 16 228 | 3 229 | 10 230 | 17 231 | 24 232 | 4 233 | 11 234 | 18 235 | 25 236 | 32 237 | 5 238 | 12 239 | 19 240 | 26 241 | 33 242 | 40 243 | 6 244 | 13 245 | 20 246 | 27 247 | 34 248 | 41 249 | 48 250 | 7 251 | 14 252 | 21 253 | 28 254 | 35 255 | 42 256 | 49 257 | 56 258 | 15 259 | 22 260 | 29 261 | 36 262 | 43 263 | 50 264 | 57 265 | 23 266 | 30 267 | 37 268 | 44 269 | 51 270 | 58 271 | 31 272 | 38 273 | 45 274 | 52 275 | 59 276 | 39 277 | 46 278 | 53 279 | 60 280 | 47 281 | 54 282 | 61 283 | 10 284 | 8 285 | 8 286 | 8 287 | 8 288 | 4 289 | 4 290 | 8 291 | 2 292 | 4 293 | 54 294 | 63 295 | 62 296 | 61 297 | 60 298 | 59 299 | 58 300 | 57 301 | 56 302 | 49 303 | 49 304 | 56 305 | 48 306 | 40 307 | 32 308 | 24 309 | 16 310 | 8 311 | 0 312 | 9 313 | 9 314 | 0 315 | 1 316 | 2 317 | 3 318 | 4 319 | 5 320 | 6 321 | 7 322 | 14 323 | 14 324 | 7 325 | 15 326 | 23 327 | 31 328 | 39 329 | 47 330 | 55 331 | 63 332 | 54 333 | 3 334 | 2 335 | 1 336 | 0 337 | 9 338 | 8 339 | 16 340 | 24 341 | 4 342 | 5 343 | 6 344 | 7 345 | 14 346 | 15 347 | 23 348 | 31 349 | 60 350 | 61 351 | 62 352 | 63 353 | 54 354 | 55 355 | 47 356 | 39 357 | 59 358 | 58 359 | 57 360 | 56 361 | 49 362 | 48 363 | 40 364 | 32 365 | 0 366 | 1 367 | 2 368 | 3 369 | 8 370 | 9 371 | 10 372 | 11 373 | 0 374 | 8 375 | 16 376 | 24 377 | 1 378 | 9 379 | 17 380 | 25 381 | 7 382 | 6 383 | 5 384 | 4 385 | 15 386 | 14 387 | 13 388 | 12 389 | 7 390 | 15 391 | 23 392 | 31 393 | 6 394 | 14 395 | 22 396 | 30 397 | 63 398 | 62 399 | 61 400 | 60 401 | 55 402 | 54 403 | 53 404 | 52 405 | 63 406 | 55 407 | 47 408 | 39 409 | 62 410 | 54 411 | 46 412 | 38 413 | 56 414 | 57 415 | 58 416 | 59 417 | 48 418 | 49 419 | 50 420 | 51 421 | 56 422 | 48 423 | 40 424 | 32 425 | 57 426 | 49 427 | 41 428 | 33 429 | 0 430 | 9 431 | 18 432 | 27 433 | 36 434 | 45 435 | 54 436 | 63 437 | 7 438 | 14 439 | 21 440 | 28 441 | 35 442 | 42 443 | 49 444 | 56 445 | 0 446 | 1 447 | 2 448 | 3 449 | 4 450 | 5 451 | 6 452 | 7 453 | 7 454 | 15 455 | 23 456 | 31 457 | 39 458 | 47 459 | 55 460 | 63 461 | 63 462 | 62 463 | 61 464 | 60 465 | 59 466 | 58 467 | 57 468 | 56 469 | 56 470 | 48 471 | 40 472 | 32 473 | 24 474 | 26 475 | 8 476 | 0 477 | -------------------------------------------------------------------------------- /legacy/AI_ML/learn.py: -------------------------------------------------------------------------------- 1 | from sklearn.model_selection import train_test_split 2 | from sklearn.linear_model import SGDRegressor 3 | from sklearn.pipeline import make_pipeline 4 | from sklearn.preprocessing import StandardScaler 5 | import numpy as np 6 | from PIL import Image 7 | import os 8 | from tqdm import trange 9 | import pickle 10 | 11 | import keras 12 | from keras.utils import np_utils 13 | from keras.layers.convolutional import Conv2D, MaxPooling2D 14 | from keras.models import Sequential 15 | from keras.layers.core import Dense, Dropout, Activation, Flatten 16 | from keras.preprocessing.image import array_to_img, img_to_array, load_img 17 | import numpy as np 18 | import pandas as pd 19 | from sklearn.model_selection import train_test_split 20 | import matplotlib.pyplot as plt 21 | 22 | from tensorflow import keras 23 | from tensorflow.keras import layers 24 | 25 | def digit(n, r): 26 | n = str(n) 27 | l = len(n) 28 | for i in range(r - l): 29 | n = '0' + n 30 | return n 31 | 32 | directry = 'data' 33 | hw = 8 34 | filenames = sorted(os.listdir(directry + '/0')) 35 | load_num = 1000 #len(filenames) 36 | 37 | features = [[] for _ in range(load_num)] 38 | for i in trange(load_num): 39 | filename = filenames[i] 40 | img0 = load_img(directry + '/0/' + filename, target_size=(64, 64)) 41 | img1 = load_img(directry + '/1/' + filename, target_size=(64, 64)) 42 | features[i].append(img_to_array(img0)) 43 | features[i].append(img_to_array(img1)) 44 | ''' 45 | for y in range(hw): 46 | for x in range(hw): 47 | features[i][0][y][x] = min(img0[y][x], 1) 48 | features[i][1][y][x] = min(img1[y][x], 1) 49 | ''' 50 | target = [0.0 for _ in range(load_num)] 51 | with open(directry + '/score.txt', 'r') as f: 52 | for i in trange(load_num): 53 | target[i] = float(f.readline()) 54 | 55 | features = np.asarray(features) 56 | target = np.asarray(target) 57 | 58 | print('all data', features.shape, target.shape) 59 | 60 | features_train, features_test, target_train, target_test = train_test_split(features, target,test_size=0.01, random_state=0) 61 | 62 | print('train', features_train.shape, target_train.shape) 63 | print('test ', features_test.shape, target_test.shape) 64 | 65 | 66 | model = Sequential() 67 | 68 | model.add(Conv2D(32, (3, 3), padding='same', input_shape=features_train.shape[1:])) 69 | model.add(Activation('relu')) 70 | model.add(Conv2D(32, (3, 3))) 71 | model.add(Activation('relu')) 72 | model.add(MaxPooling2D(pool_size=(2, 2))) 73 | model.add(Dropout(0.25)) 74 | 75 | model.add(Conv2D(64, (3, 3), padding='same')) 76 | model.add(Activation('relu')) 77 | model.add(Conv2D(64, (3, 3))) 78 | model.add(Activation('relu')) 79 | model.add(MaxPooling2D(pool_size=(2, 2))) 80 | model.add(Dropout(0.25)) 81 | 82 | model.add(Flatten()) 83 | model.add(Dense(512)) 84 | model.add(Activation('relu')) 85 | model.add(Dropout(0.5)) 86 | model.add(Dense(2)) # クラスは2個 87 | model.add(Activation('softmax')) 88 | 89 | # コンパイル 90 | model.compile(loss='categorical_crossentropy', optimizer='SGD', metrics=['accuracy']) 91 | 92 | # 実行。出力はなしで設定(verbose=0)。 93 | history = model.fit(features_train, target_train, batch_size=5, epochs=200, validation_data = (features_test, target_test), verbose = 0) 94 | 95 | def plot_history(history): 96 | hist = pd.DataFrame(history.history) 97 | hist['epoch'] = history.epoch 98 | 99 | plt.figure() 100 | plt.xlabel('Epoch') 101 | plt.ylabel('Mean Abs Error [MPG]') 102 | plt.plot(hist['epoch'], hist['mae'], 103 | label='Train Error') 104 | plt.plot(hist['epoch'], hist['val_mae'], 105 | label = 'Val Error') 106 | plt.ylim([0,5]) 107 | plt.legend() 108 | 109 | plt.figure() 110 | plt.xlabel('Epoch') 111 | plt.ylabel('Mean Square Error [$MPG^2$]') 112 | plt.plot(hist['epoch'], hist['mse'], 113 | label='Train Error') 114 | plt.plot(hist['epoch'], hist['val_mse'], 115 | label = 'Val Error') 116 | plt.ylim([0,20]) 117 | plt.legend() 118 | plt.show() 119 | 120 | 121 | plot_history(history) 122 | 123 | 124 | ''' 125 | print('learning start') 126 | learning = make_pipeline(StandardScaler(), SGDRegressor(max_iter=1000, tol=1e-3)) #Lasso(alpha=0.1,random_state=0) 127 | model = learning.fit(features_train,target_train) 128 | pickle.dump(model, open(filename, 'wb')) 129 | print('learning end') 130 | model = pickle.load(open(filename, 'rb')) 131 | ''' 132 | 133 | errors = [] 134 | exacts = [] 135 | for i in range(len(target_test)): 136 | prediction = model.predict([features_test[i]])[0][0] 137 | exact = target[i] 138 | err = abs(prediction - exact) 139 | print(err, prediction, exact) 140 | errors.append(err) 141 | exacts.append(abs(exact)) 142 | 143 | print(sum(errors) / len(errors)) 144 | print(sum(exacts) / len(exacts)) -------------------------------------------------------------------------------- /legacy/AI_Python/ai_python.py: -------------------------------------------------------------------------------- 1 | # Reversi AI 2 | 3 | import sys 4 | from random import random, shuffle 5 | def debug(*args, end='\n'): print(*args, file=sys.stderr, end=end) 6 | 7 | hw = 8 8 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 9 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 10 | 11 | def empty(grid, y, x): 12 | return grid[y][x] == -1 or grid[y][x] == 2 13 | 14 | def inside(y, x): 15 | return 0 <= y < hw and 0 <= x < hw 16 | 17 | weight = [ 18 | [100, -40, 20, 5, 5, 20, -40, 100], 19 | [-40, -80, -1, -1, -1, -1, -80, -40], 20 | [ 20, -1, 5, 1, 1, 5, -1, 20], 21 | [ 5, -1, 1, 0, 0, 1, -1, 5], 22 | [ 5, -1, 1, 0, 0, 1, -1, 5], 23 | [ 20, -1, 5, 1, 1, 5, -1, 20], 24 | [-40, -80, -1, -1, -1, -1, -80, -40], 25 | [100, -40, 20, 5, 5, 20, -40, 100] 26 | ] 27 | 28 | def check(grid, player, y, x): 29 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 30 | res = 0 31 | for dr in range(8): 32 | ny = y + dy[dr] 33 | nx = x + dx[dr] 34 | if not inside(ny, nx): 35 | continue 36 | if empty(grid, ny, nx): 37 | continue 38 | if grid[ny][nx] == player: 39 | continue 40 | plus = 0 41 | flag = False 42 | for d in range(hw): 43 | nny = ny + d * dy[dr] 44 | nnx = nx + d * dx[dr] 45 | if not inside(nny, nnx): 46 | break 47 | if empty(grid, nny, nnx): 48 | break 49 | if grid[nny][nnx] == player: 50 | flag = True 51 | break 52 | plus += 1 53 | if flag: 54 | res += plus 55 | for d in range(plus): 56 | nny = ny + d * dy[dr] 57 | nnx = nx + d * dx[dr] 58 | res_grid[nny][nnx] = True 59 | return res, res_grid 60 | 61 | def check_canput(grid, player, y, x): 62 | for dr in range(8): 63 | ny = y + dy[dr] 64 | nx = x + dx[dr] 65 | if not inside(ny, nx): 66 | continue 67 | if empty(grid, ny, nx): 68 | continue 69 | if grid[ny][nx] == player: 70 | continue 71 | plus = 0 72 | flag = False 73 | for d in range(hw): 74 | nny = ny + d * dy[dr] 75 | nnx = nx + d * dx[dr] 76 | if not inside(nny, nnx): 77 | break 78 | if empty(grid, nny, nnx): 79 | break 80 | if grid[nny][nnx] == player: 81 | return 1 82 | plus += 1 83 | return 0 84 | 85 | def evaluate(player, grid): 86 | res = 0 87 | for y in range(hw): 88 | for x in range(hw): 89 | if empty(grid, y, x): 90 | res += check_canput(grid, player, y, x) * vacant_cnt / hw / hw * 20 91 | res -= check_canput(grid, 1 - player, y, x) * vacant_cnt / hw / hw * 20 92 | else: 93 | res += weight[y][x] * ((grid[y][x] == player) * 2 - 1) 94 | return res 95 | 96 | def end_game(player, grid): 97 | res = 0 98 | for y in range(hw): 99 | for x in range(hw): 100 | if not empty(grid, y, x): 101 | res += (grid[y][x] != player) * 2 - 1 102 | if res > 0: 103 | return 10000 104 | elif res < 0: 105 | return -10000 106 | else: 107 | return 5000 108 | 109 | def isskip(grid): 110 | for y in range(hw): 111 | for x in range(hw): 112 | if grid[y][x] == 2: 113 | return False 114 | return True 115 | 116 | def check_pass(player, grid): 117 | for y in range(hw): 118 | for x in range(hw): 119 | if grid[y][x] == 2: 120 | grid[y][x] = -1 121 | res = True 122 | for y in range(hw): 123 | for x in range(hw): 124 | if not empty(grid, y, x): 125 | continue 126 | plus, _ = check_canput(grid, player, y, x) 127 | if plus: 128 | res = False 129 | return grid 130 | 131 | def open_eval(grid, ty, tx, plus_grid): 132 | seen = [[False for _ in range(hw)] for _ in range(hw)] 133 | seen[ty][tx] = True 134 | res = 0 135 | for dr in range(8): 136 | ny = ty + dy[dr] 137 | nx = tx + dx[dr] 138 | if not inside(ny, nx): 139 | continue 140 | if seen[ny][nx]: 141 | continue 142 | if empty(grid, ny, nx): 143 | seen[ny][nx] = True 144 | res += 1 145 | for y in range(hw): 146 | for x in range(hw): 147 | if not plus_grid[y][x]: 148 | continue 149 | for dr in range(8): 150 | ny = y + dy[dr] 151 | nx = x + dx[dr] 152 | if not inside(ny, nx): 153 | continue 154 | if seen[ny][nx]: 155 | continue 156 | if empty(grid, ny, nx): 157 | seen[ny][nx] = True 158 | res += 1 159 | grid[ty][tx] = -1 160 | return res 161 | 162 | def output(grid, func): 163 | func(' ', end='') 164 | for i in range(hw): 165 | func(i, end=' ') 166 | func('') 167 | for y in range(hw): 168 | func(str(y) + '0', end='') 169 | for x in range(hw): 170 | func('○' if grid[y][x] == 0 else '●' if grid[y][x] == 1 else '* ' if grid[y][x] == 2 else '. ', end='') 171 | func('') 172 | 173 | def nega_max(player, grid, depth, alpha, beta, skip_cnt): 174 | global ansy, ansx 175 | if skip_cnt == 2: 176 | return end_game(ai_player, grid) 177 | elif depth == 0: 178 | return evaluate(ai_player, grid) 179 | lst = [] 180 | for y in range(hw): 181 | for x in range(hw): 182 | if grid[y][x] != -1: 183 | continue 184 | num, plus_grid = check(grid, player, y, x) 185 | if not num: 186 | continue 187 | lst.append([open_eval(grid, y, x, plus_grid), plus_grid, y, x]) 188 | if not lst: 189 | return max(alpha, -nega_max(1 - player, grid, depth, -beta, -alpha, skip_cnt + 1)) 190 | lst.sort() 191 | #debug([i[0] for i in lst]) 192 | for _, plus_grid, y, x in lst: 193 | n_grid = [[i for i in j] for j in grid] 194 | n_grid[y][x] = player 195 | for ny in range(hw): 196 | for nx in range(hw): 197 | if plus_grid[ny][nx]: 198 | n_grid[ny][nx] = player 199 | val = -nega_max(1 - player, n_grid, depth - 1, -beta, -alpha, 0) 200 | if val > alpha: 201 | alpha = val 202 | if depth == max_depth: 203 | ansy = y 204 | ansx = x 205 | if alpha >= beta: 206 | break 207 | return alpha 208 | 209 | ai_player = int(input()) 210 | grid = [[-1 if int(i) == 2 else int(i) for i in input().split()] for _ in range(hw)] 211 | vacant_cnt = 0 212 | for y in range(hw): 213 | for x in range(hw): 214 | vacant_cnt += (grid[y][x] == -1) 215 | max_depth = 4 216 | ansy = -1 217 | ansx = -1 218 | score = nega_max(ai_player, grid, max_depth, -100000000, 100000000, 0) 219 | debug('score', score) 220 | print(ansy, ansx) 221 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # reversi software 2 | import subprocess 3 | from time import sleep 4 | 5 | hw = 8 6 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 7 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 8 | 9 | 10 | def empty(grid, y, x): 11 | return grid[y][x] == -1 or grid[y][x] == 2 12 | 13 | 14 | def inside(y, x): 15 | return 0 <= y < hw and 0 <= x < hw 16 | 17 | 18 | def check(grid, player, y, x): 19 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 20 | res = 0 21 | for dr in range(8): 22 | ny = y + dy[dr] 23 | nx = x + dx[dr] 24 | if not inside(ny, nx): 25 | continue 26 | if empty(grid, ny, nx): 27 | continue 28 | if grid[ny][nx] == player: 29 | continue 30 | #print(y, x, dr, ny, nx) 31 | plus = 0 32 | flag = False 33 | for d in range(hw): 34 | nny = ny + d * dy[dr] 35 | nnx = nx + d * dx[dr] 36 | if not inside(nny, nnx): 37 | break 38 | if empty(grid, nny, nnx): 39 | break 40 | if grid[nny][nnx] == player: 41 | flag = True 42 | break 43 | #print(y, x, dr, nny, nnx) 44 | plus += 1 45 | if flag: 46 | res += plus 47 | for d in range(plus): 48 | nny = ny + d * dy[dr] 49 | nnx = nx + d * dx[dr] 50 | res_grid[nny][nnx] = True 51 | return res, res_grid 52 | 53 | 54 | class reversi: 55 | def __init__(self): 56 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 57 | self.grid[3][3] = 1 58 | self.grid[3][4] = 0 59 | self.grid[4][3] = 0 60 | self.grid[4][4] = 1 61 | self.player = 0 # 0: 黒 1: 白 62 | self.nums = [2, 2] 63 | 64 | def move(self, y, x): 65 | plus, plus_grid = check(self.grid, self.player, y, x) 66 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 67 | print('Please input a correct move') 68 | return 69 | self.grid[y][x] = self.player 70 | for ny in range(hw): 71 | for nx in range(hw): 72 | if plus_grid[ny][nx]: 73 | self.grid[ny][nx] = self.player 74 | self.nums[self.player] += 1 + plus 75 | self.nums[1 - self.player] -= plus 76 | self.player = 1 - self.player 77 | 78 | def check_pass(self): 79 | for y in range(hw): 80 | for x in range(hw): 81 | if self.grid[y][x] == 2: 82 | self.grid[y][x] = -1 83 | res = True 84 | for y in range(hw): 85 | for x in range(hw): 86 | if not empty(self.grid, y, x): 87 | continue 88 | plus, _ = check(self.grid, self.player, y, x) 89 | if plus: 90 | res = False 91 | self.grid[y][x] = 2 92 | if res: 93 | print('Pass!') 94 | self.player = 1 - self.player 95 | return res 96 | 97 | def output(self): 98 | print(' ', end='') 99 | for i in range(hw): 100 | print(chr(ord('a') + i), end=' ') 101 | print('') 102 | for y in range(hw): 103 | print(str(y + 1) + ' ', end='') 104 | for x in range(hw): 105 | print('O ' if self.grid[y][x] == 0 else 'X ' if self.grid[y] 106 | [x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 107 | print('') 108 | 109 | def end(self): 110 | if min(self.nums) == 0: 111 | return True 112 | res = True 113 | for y in range(hw): 114 | for x in range(hw): 115 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 116 | res = False 117 | return res 118 | 119 | def judge(self): 120 | if self.nums[0] > self.nums[1]: 121 | print('Black won!', self.nums[0], '-', self.nums[1]) 122 | elif self.nums[1] > self.nums[0]: 123 | print('White won!', self.nums[0], '-', self.nums[1]) 124 | else: 125 | print('Draw!', self.nums[0], '-', self.nums[1]) 126 | 127 | 128 | tl = 2000 129 | ai_mode = True 130 | ai_player = 1 131 | while True: 132 | print('Choose game style:', 'PERSON: person vs person', 133 | 'BLACK: person(black) vs AI(white)', 'WHITE: AI(black) vs person(white)', sep='\n') 134 | style = input('choose: ') 135 | if(style == 'PERSON'): 136 | ai_mode = False 137 | elif(style == 'BLACK'): 138 | ai_player = 1 139 | elif(style == 'WHITE'): 140 | ai_player = 0 141 | else: 142 | print('The input is invalid\n') 143 | continue 144 | break 145 | 146 | if ai_mode: 147 | ai = subprocess.Popen( 148 | './a.exe'.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE) 149 | stdin = str(ai_player) + '\n' + str(tl) + '\n' 150 | ai.stdin.write(stdin.encode('utf-8')) 151 | ai.stdin.flush() 152 | # weight canput confirm 153 | #param = [0.25, 0.3, 0.0, 0.2, 0.1, 0.05, 0.1, 0.55, 0.3, 0.0, 0.1, -0.05] 154 | #[0.30288811933933507, 0.023667040619869673, 0.38484168625403836, 0.11491476667436311, 0.17290370673757446, 0.0007846803748192674, 0.12637328291777342, 0.27743891909702173, 0.3224275886777521, 0.12516714992181288, 0.017010853296369526, 0.1315822060892702] 155 | #[0.29897487925488575, 0.2563073241985653, 0.09962883504717203, 0.3015360766231666, 0.04355288487621023, 0.10724068225578637, 0.7042631039296219, 0.2370638323464772, -0.0439910303578425, -0.004576588174042863] 156 | #[0.34536779645622856, 0.1691274097088668, 0.0892489731834872, 0.37682794628570937, 0.01942787436570797, 0.12257349937655919, 0.6659002360919307, 0.26888169690483155, -0.026666677139788895, -0.030688755233532452] 157 | #[0.3, 0.2, 0.1, 0.395, 0.005, 0.1, 0.65, 0.295, -0.05, 0.005] 158 | #[0.35040005986471073, 0.15947540029536195, 0.2057166496401806, 0.2844078901997467, 0.01119177727784958, 0.15605466760887582, 0.8291261122201004, 0.003627442893174265] 159 | #[0.2672372538812086, 0.29215254984703876, 0.4406101962717526, 0.07938086187048915, 0.29975313369335055, 0.6208660044361604] 160 | sleep(0.5) 161 | 162 | rv = reversi() 163 | while True: 164 | if rv.check_pass() and rv.check_pass(): 165 | break 166 | rv.output() 167 | s = 'Black' if rv.player == 0 else 'White' 168 | if ai_mode and rv.player == ai_player: 169 | stdin = '' 170 | for y in range(hw): 171 | for x in range(hw): 172 | stdin += str(rv.grid[y][x]) + ' ' 173 | stdin += '\n' 174 | # print(stdin) 175 | ai.stdin.write(stdin.encode('utf-8')) 176 | ai.stdin.flush() 177 | y, x = [int(i) for i in ai.stdout.readline().decode().strip().split()] 178 | print(s + ': ' + chr(x + ord('a')) + str(y + 1)) 179 | else: 180 | ss = input(s + ': ') 181 | if ss == 'exit': 182 | break 183 | try: 184 | x = int(ord(ss[0]) - ord('a')) 185 | y = int(ss[1]) - 1 186 | except: 187 | print('Please input correct') 188 | continue 189 | if not inside(y, x): 190 | print('Please input correct') 191 | continue 192 | rv.move(y, x) 193 | if rv.end(): 194 | break 195 | rv.check_pass() 196 | rv.output() 197 | rv.judge() 198 | if ai_mode: 199 | ai.kill() 200 | -------------------------------------------------------------------------------- /legacy/AI_ML/create_data.py: -------------------------------------------------------------------------------- 1 | # reversi software 2 | import subprocess 3 | from time import sleep 4 | from random import random, randint, shuffle 5 | import numpy as np 6 | from PIL import Image 7 | import os, glob 8 | import math 9 | import cv2 10 | from tqdm import trange 11 | 12 | hw = 8 13 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 14 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 15 | 16 | def digit(n, r): 17 | n = str(n) 18 | l = len(n) 19 | for i in range(r - l): 20 | n = '0' + n 21 | return n 22 | 23 | def empty(grid, y, x): 24 | return grid[y][x] == -1 or grid[y][x] == 2 25 | 26 | def inside(y, x): 27 | return 0 <= y < hw and 0 <= x < hw 28 | 29 | def check(grid, player, y, x): 30 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 31 | res = 0 32 | for dr in range(8): 33 | ny = y + dy[dr] 34 | nx = x + dx[dr] 35 | if not inside(ny, nx): 36 | continue 37 | if empty(grid, ny, nx): 38 | continue 39 | if grid[ny][nx] == player: 40 | continue 41 | #print(y, x, dr, ny, nx) 42 | plus = 0 43 | flag = False 44 | for d in range(hw): 45 | nny = ny + d * dy[dr] 46 | nnx = nx + d * dx[dr] 47 | if not inside(nny, nnx): 48 | break 49 | if empty(grid, nny, nnx): 50 | break 51 | if grid[nny][nnx] == player: 52 | flag = True 53 | break 54 | #print(y, x, dr, nny, nnx) 55 | plus += 1 56 | if flag: 57 | res += plus 58 | for d in range(plus): 59 | nny = ny + d * dy[dr] 60 | nnx = nx + d * dx[dr] 61 | res_grid[nny][nnx] = True 62 | return res, res_grid 63 | 64 | class reversi: 65 | def __init__(self): 66 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 67 | self.grid[3][3] = 1 68 | self.grid[3][4] = 0 69 | self.grid[4][3] = 0 70 | self.grid[4][4] = 1 71 | self.player = 0 # 0: 黒 1: 白 72 | self.nums = [2, 2] 73 | 74 | def move(self, y, x): 75 | plus, plus_grid = check(self.grid, self.player, y, x) 76 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 77 | #print('Please input a correct move') 78 | return 1 79 | self.grid[y][x] = self.player 80 | for ny in range(hw): 81 | for nx in range(hw): 82 | if plus_grid[ny][nx]: 83 | self.grid[ny][nx] = self.player 84 | self.nums[self.player] += 1 + plus 85 | self.nums[1 - self.player] -= plus 86 | self.player = 1 - self.player 87 | return 0 88 | 89 | def check_pass(self): 90 | for y in range(hw): 91 | for x in range(hw): 92 | if self.grid[y][x] == 2: 93 | self.grid[y][x] = -1 94 | res = True 95 | for y in range(hw): 96 | for x in range(hw): 97 | if not empty(self.grid, y, x): 98 | continue 99 | plus, _ = check(self.grid, self.player, y, x) 100 | if plus: 101 | res = False 102 | self.grid[y][x] = 2 103 | if res: 104 | #print('Pass!') 105 | self.player = 1 - self.player 106 | return res 107 | 108 | def output(self): 109 | print(' ', end='') 110 | for i in range(hw): 111 | print(chr(ord('a') + i), end=' ') 112 | print('') 113 | for y in range(hw): 114 | print(str(y + 1) + ' ', end='') 115 | for x in range(hw): 116 | print('○' if self.grid[y][x] == 0 else '●' if self.grid[y][x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 117 | print('') 118 | 119 | def end(self): 120 | if min(self.nums) == 0: 121 | return True 122 | res = True 123 | for y in range(hw): 124 | for x in range(hw): 125 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 126 | res = False 127 | return res 128 | 129 | def judge(self): 130 | if self.nums[0] > self.nums[1]: 131 | #print('Black won!', self.nums[0], '-', self.nums[1]) 132 | return 0 133 | elif self.nums[1] > self.nums[0]: 134 | #print('White won!', self.nums[0], '-', self.nums[1]) 135 | return 1 136 | else: 137 | #print('Draw!', self.nums[0], '-', self.nums[1]) 138 | return -1 139 | 140 | def match(use_param, strt_num): 141 | images = [[], []] 142 | ai = [subprocess.Popen('a.exe'.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE) for _ in range(2)] 143 | lst = [0, 1] 144 | shuffle(lst) 145 | for i in range(2): 146 | stdin = str(lst[i]) + '\n' 147 | ai[i].stdin.write(stdin.encode('utf-8')) 148 | ai[i].stdin.flush() 149 | stdin = str(tl) + '\n' 150 | ai[i].stdin.write(stdin.encode('utf-8')) 151 | ai[i].stdin.flush() 152 | for j in range(param_num): 153 | stdin = str(use_param[i][j]) + '\n' 154 | ai[i].stdin.write(stdin.encode('utf-8')) 155 | ai[i].stdin.flush() 156 | rv = reversi() 157 | while True: 158 | if rv.check_pass() and rv.check_pass(): 159 | break 160 | img0 = np.zeros((8, 8), np.uint8) 161 | img1 = np.zeros((8, 8), np.uint8) 162 | for y in range(hw): 163 | for x in range(hw): 164 | img0[y][x] = int(rv.grid[y][x] == 0) * 255 165 | img1[y][x] = int(rv.grid[y][x] == 1) * 255 166 | images[0].append(img0) 167 | images[1].append(img1) 168 | stdin = '' 169 | for y in range(hw): 170 | for x in range(hw): 171 | stdin += str(rv.grid[y][x]) + ' ' 172 | stdin += '\n' 173 | ai[rv.player].stdin.write(stdin.encode('utf-8')) 174 | ai[rv.player].stdin.flush() 175 | y, x = [int(i) for i in ai[rv.player].stdout.readline().decode().strip().split()] 176 | if rv.move(y, x): 177 | print('illegal move') 178 | break 179 | if rv.end(): 180 | break 181 | rv.check_pass() 182 | winner = rv.judge() 183 | for i in range(2): 184 | ai[i].kill() 185 | ln = len(images[0]) 186 | final_score = (rv.nums[0] - rv.nums[1]) / ln 187 | with open('data/score.txt', 'a') as f: 188 | for i in range(ln): 189 | f.write(str(final_score * (i + 1)) + '\n') 190 | s = digit(strt_num + i, 10) 191 | cv2.imwrite('data/0/' + s + '.tif', images[0][i]) 192 | cv2.imwrite('data/1/' + s + '.tif', images[1][i]) 193 | return strt_num + ln 194 | 195 | population = 1000 196 | match_num = 2000 197 | param_num = 12 198 | tl = 100 199 | 200 | param_base = [0.25, 0.3, 0.0, 0.2, 0.1, 0.05, 0.1, 0.55, 0.3, 0.0, 0.1, -0.05] 201 | 202 | param = [[0.0 for _ in range(param_num)] for _ in range(population)] 203 | for i in range(population): 204 | for j in range(param_num): 205 | param[i][j] = param_base[j] + random() * 0.2 - 0.1 206 | sm = sum(param[i][:param_num // 2]) 207 | for j in range(param_num // 2): 208 | param[i][j] /= sm 209 | sm = sum(param[i][param_num // 2:]) 210 | for j in range(param_num // 2, param_num): 211 | param[i][j] /= sm 212 | 213 | use_param = [[-1.0 for _ in range(param_num)] for _ in range(2)] 214 | strt_num = 0 215 | for _ in trange(match_num): 216 | me = randint(0, population - 1) 217 | op = randint(0, population - 1) 218 | for j in range(param_num): 219 | use_param[0][j] = param[me][j] 220 | use_param[1][j] = param[op][j] 221 | strt_num = match(use_param, strt_num) 222 | print(strt_num) -------------------------------------------------------------------------------- /auto_game.py: -------------------------------------------------------------------------------- 1 | # reversi software 2 | import subprocess 3 | from time import sleep 4 | from random import random, randint 5 | 6 | hw = 8 7 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 8 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 9 | 10 | def empty(grid, y, x): 11 | return grid[y][x] == -1 or grid[y][x] == 2 12 | 13 | def inside(y, x): 14 | return 0 <= y < hw and 0 <= x < hw 15 | 16 | def check(grid, player, y, x): 17 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 18 | res = 0 19 | for dr in range(8): 20 | ny = y + dy[dr] 21 | nx = x + dx[dr] 22 | if not inside(ny, nx): 23 | continue 24 | if empty(grid, ny, nx): 25 | continue 26 | if grid[ny][nx] == player: 27 | continue 28 | #print(y, x, dr, ny, nx) 29 | plus = 0 30 | flag = False 31 | for d in range(hw): 32 | nny = ny + d * dy[dr] 33 | nnx = nx + d * dx[dr] 34 | if not inside(nny, nnx): 35 | break 36 | if empty(grid, nny, nnx): 37 | break 38 | if grid[nny][nnx] == player: 39 | flag = True 40 | break 41 | #print(y, x, dr, nny, nnx) 42 | plus += 1 43 | if flag: 44 | res += plus 45 | for d in range(plus): 46 | nny = ny + d * dy[dr] 47 | nnx = nx + d * dx[dr] 48 | res_grid[nny][nnx] = True 49 | return res, res_grid 50 | 51 | class reversi: 52 | def __init__(self): 53 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 54 | self.grid[3][3] = 1 55 | self.grid[3][4] = 0 56 | self.grid[4][3] = 0 57 | self.grid[4][4] = 1 58 | self.player = 0 # 0: 黒 1: 白 59 | self.nums = [2, 2] 60 | 61 | def move(self, y, x): 62 | plus, plus_grid = check(self.grid, self.player, y, x) 63 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 64 | print('Please input a correct move') 65 | return 66 | self.grid[y][x] = self.player 67 | for ny in range(hw): 68 | for nx in range(hw): 69 | if plus_grid[ny][nx]: 70 | self.grid[ny][nx] = self.player 71 | self.nums[self.player] += 1 + plus 72 | self.nums[1 - self.player] -= plus 73 | self.player = 1 - self.player 74 | 75 | def check_pass(self): 76 | for y in range(hw): 77 | for x in range(hw): 78 | if self.grid[y][x] == 2: 79 | self.grid[y][x] = -1 80 | res = True 81 | for y in range(hw): 82 | for x in range(hw): 83 | if not empty(self.grid, y, x): 84 | continue 85 | plus, _ = check(self.grid, self.player, y, x) 86 | if plus: 87 | res = False 88 | self.grid[y][x] = 2 89 | if res: 90 | #print('Pass!') 91 | self.player = 1 - self.player 92 | return res 93 | 94 | def output(self): 95 | print(' ', end='') 96 | for i in range(hw): 97 | print(chr(ord('a') + i), end=' ') 98 | print('') 99 | for y in range(hw): 100 | print(str(y + 1) + ' ', end='') 101 | for x in range(hw): 102 | print('○' if self.grid[y][x] == 0 else '●' if self.grid[y][x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 103 | print('') 104 | 105 | def output_file(self): 106 | res = '' 107 | for y in range(hw): 108 | for x in range(hw): 109 | res += '*' if self.grid[y][x] == 0 else 'O' if self.grid[y][x] == 1 else '-' 110 | res += ' *' 111 | return res 112 | 113 | def end(self): 114 | if min(self.nums) == 0: 115 | return True 116 | res = True 117 | for y in range(hw): 118 | for x in range(hw): 119 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 120 | res = False 121 | return res 122 | 123 | def judge(self): 124 | if self.nums[0] > self.nums[1]: 125 | #print('Black won!', self.nums[0], '-', self.nums[1]) 126 | return 0 127 | elif self.nums[1] > self.nums[0]: 128 | #print('White won!', self.nums[0], '-', self.nums[1]) 129 | return 1 130 | else: 131 | #print('Draw!', self.nums[0], '-', self.nums[1]) 132 | return -1 133 | 134 | def match(): 135 | ai_player = 1 136 | ai = subprocess.Popen('./b.exe'.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE) 137 | stdin = str(ai_player) + '\n' + str(tl) + '\n' 138 | ai.stdin.write(stdin.encode('utf-8')) 139 | ai.stdin.flush() 140 | rv = reversi() 141 | while True: 142 | if rv.check_pass() and rv.check_pass(): 143 | break 144 | rv.output() 145 | y = -1 146 | x = -1 147 | if rv.player == ai_player: 148 | stdin = '' 149 | for y in range(hw): 150 | for x in range(hw): 151 | stdin += str(rv.grid[y][x]) + ' ' 152 | stdin += '\n' 153 | ai.stdin.write(stdin.encode('utf-8')) 154 | ai.stdin.flush() 155 | y, x = [int(i) for i in ai.stdout.readline().decode().strip().split()] 156 | else: 157 | with open('state.txt', 'w') as f: 158 | f.write(rv.output_file()) 159 | place = r'C:\Program Files\MasterReversiPro' 160 | value = r'MRSolver.exe -m 7 -f C:\home\Reversi\state.txt' 161 | all_data = subprocess.Popen(value.split(), cwd=place, stdout=subprocess.PIPE, shell=True).communicate()[0] 162 | for data in all_data.decode().strip().split(): 163 | if data[:2] == '->': 164 | x, y = ord(data[2]) - ord('A'), int(data[3]) - 1 165 | break 166 | rv.move(y, x) 167 | if rv.end(): 168 | break 169 | rv.check_pass() 170 | rv.output() 171 | winner = rv.judge() 172 | ai.kill() 173 | return rv.nums[ai_player] - rv.nums[1 - ai_player] if rv.nums[1 - ai_player] > 0 else hw * hw 174 | 175 | tl = 5000 176 | #double weight_weight_s, canput_weight_s, confirm_weight_s, stone_weight_s, open_weight_s, out_weight_s, weight_weight_e, canput_weight_e, confirm_weight_e, stone_weight_e, open_weight_e, out_weight_e; 177 | 178 | 179 | #param = [0.25, 0.3, 0.0, 0.2, 0.1, 0.05, 0.1, 0.55, 0.3, 0.0, 0.1, -0.05] 180 | #[0.30288811933933507, 0.023667040619869673, 0.38484168625403836, 0.11491476667436311, 0.17290370673757446, 0.0007846803748192674, 0.12637328291777342, 0.27743891909702173, 0.3224275886777521, 0.12516714992181288, 0.017010853296369526, 0.1315822060892702] 181 | #[0.29897487925488575, 0.2563073241985653, 0.09962883504717203, 0.3015360766231666, 0.04355288487621023, 0.10724068225578637, 0.7042631039296219, 0.2370638323464772, -0.0439910303578425, -0.004576588174042863] 182 | #[0.34536779645622856, 0.1691274097088668, 0.0892489731834872, 0.37682794628570937, 0.01942787436570797, 0.12257349937655919, 0.6659002360919307, 0.26888169690483155, -0.026666677139788895, -0.030688755233532452] 183 | #[0.3, 0.2, 0.1, 0.395, 0.005, 0.1, 0.6, 0.295, 0.0, 0.005] 184 | #[0.2608336598778891, 0.1527989383786458, 0.3599495272757296, 0.21569888036289153, 0.010718994104843985, 0.19964746620817103, 0.15820182158874269, 0.38477257203715615, 0.21678102609238753, 0.04059711407354259] 185 | #[0.2, 0.1, 0.2, 0.3, 0.2, 0.0, 0.2, 0.6, 0.0, 0.2] 186 | #[0.35040005986471073, 0.15947540029536195, 0.2057166496401806, 0.2844078901997467, 0.01119177727784958, 0.15605466760887582, 0.8291261122201004, 0.003627442893174265] 187 | #[0.2672372538812086, 0.29215254984703876, 0.4406101962717526, 0.07938086187048915, 0.29975313369335055, 0.6208660044361604] 188 | print('match end score', match()) -------------------------------------------------------------------------------- /check_pattern_param.py: -------------------------------------------------------------------------------- 1 | from random import random 2 | import subprocess 3 | from time import time 4 | from random import randint, random 5 | from tqdm import trange 6 | import matplotlib.pyplot as plt 7 | from math import sqrt, exp 8 | 9 | pattern_num = 5 10 | index_num = 38 11 | 12 | ''' 13 | translate_raw = [ 14 | [0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 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], 15 | [0, 8, 16, 24, 32, 40, 48, 56], [1, 9, 17, 25, 33, 41, 49, 57], [2, 10, 18, 26, 34, 42, 50, 58], [3, 11, 19, 27, 35, 43, 51, 59], [4, 12, 20, 28, 36, 44, 52, 60], [5, 13, 21, 29, 37, 45, 53, 61], [6, 14, 22, 30, 38, 46, 54, 62], [7, 15, 23, 31, 39, 47, 55, 63], 16 | [5, 14, 23], [4, 13, 22, 31], [3, 12, 21, 30, 39], [2, 11, 20, 29, 38, 47], [1, 10, 19, 28, 37, 46, 55], [0, 9, 18, 27, 36, 45, 54, 63], [8, 17, 26, 35, 44, 53, 62], [16, 25, 34, 43, 52, 61], [24, 33, 42, 51, 60], [32, 41, 50, 59], [40, 49, 58], 17 | [2, 9, 16], [3, 10, 17, 24], [4, 11, 18, 25, 32], [5, 12, 19, 26, 33, 40], [6, 13, 20, 27, 34, 41, 48], [7, 14, 21, 28, 35, 42, 49, 56], [15, 22, 29, 36, 43, 50, 57], [23, 30, 37, 44, 51, 58], [31, 38, 45, 52, 59], [39, 46, 53, 60], [47, 54, 61] 18 | ] 19 | same_param = [0, 1, 2, 3, 3, 2, 1, 0, 0, 1, 2, 3, 3, 2, 1, 0, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4] 20 | ''' 21 | translate = [] 22 | eval_translate = [] 23 | each_param_num = [] 24 | 25 | edge1 = [ 26 | [54, 63, 62, 61, 60, 59, 58, 57, 56, 49], 27 | [49, 56, 48, 40, 32, 24, 16, 8, 0, 9], 28 | [9, 0, 1, 2, 3, 4, 5, 6, 7, 14], 29 | [14, 7, 15, 23, 31, 39, 47, 55, 63, 54] 30 | ] 31 | 32 | edge2 = [] 33 | for arr in edge1: 34 | edge2.append(arr) 35 | edge2.append(list(reversed(arr))) 36 | translate.append(edge2) 37 | eval_translate.append(edge1) 38 | each_param_num.append(3 ** 10) 39 | 40 | corner1= [ 41 | [3, 2, 1, 0, 9, 8, 16, 24], 42 | [4, 5, 6, 7, 14, 15, 23, 31], 43 | [60, 61, 62, 63, 54, 55, 47, 39], 44 | [59, 58, 57, 56, 49, 48, 40, 32] 45 | ] 46 | 47 | corner2 = [ 48 | [3, 2, 1, 0, 9, 8, 16, 24], 49 | [24, 16, 8, 0, 9, 1, 2, 3], 50 | [4, 5, 6, 7, 14, 15, 23, 31], 51 | [31, 23, 15, 7, 14, 6, 5, 4], 52 | [60, 61, 62, 63, 54, 55, 47, 39], 53 | [39, 47, 55, 63, 54, 62, 61, 60], 54 | [59, 58, 57, 56, 49, 48, 40, 32], 55 | [32, 40, 48, 56, 49, 57, 58, 59] 56 | ] 57 | 58 | translate.append(corner2) 59 | eval_translate.append(corner1) 60 | each_param_num.append(3 ** 8) 61 | 62 | corner24 = [ 63 | [0, 1, 2, 3, 8, 9, 10, 11], 64 | [0, 8, 16, 24, 1, 9, 17, 25], 65 | [7, 6, 5, 4, 15, 14, 13, 12], 66 | [7, 15, 23, 31, 6, 14, 22, 30], 67 | [63, 62, 61, 60, 55, 54, 53, 52], 68 | [63, 55, 47, 39, 62, 54, 46, 38], 69 | [56, 57, 58, 59, 48, 49, 50, 51], 70 | [56, 48, 40, 32, 57, 49, 41, 33] 71 | ] 72 | 73 | translate.append(corner24) 74 | eval_translate.append(corner24) 75 | each_param_num.append(3 ** 8) 76 | 77 | diagonal1 = [ 78 | [0, 9, 18, 27, 36, 45, 54, 63], 79 | [7, 14, 21, 28, 35, 42, 49, 56] 80 | ] 81 | 82 | diagonal2 = [] 83 | for arr in diagonal1: 84 | diagonal2.append(arr) 85 | diagonal2.append(list(reversed(arr))) 86 | translate.append(diagonal2) 87 | eval_translate.append(diagonal1) 88 | each_param_num.append(3 ** 8) 89 | 90 | edge1 = [ 91 | [0, 1, 2, 3, 4, 5, 6, 7], 92 | [7, 15, 23, 31, 39, 47, 55, 63], 93 | [63, 62, 61, 60, 59, 58, 57, 56], 94 | [56, 48, 40, 32, 24, 26, 8, 0] 95 | ] 96 | 97 | edge2 = [] 98 | for arr in edge1: 99 | edge2.append(arr) 100 | edge2.append(list(reversed(arr))) 101 | translate.append(edge2) 102 | eval_translate.append(edge1) 103 | each_param_num.append(3 ** 8) 104 | 105 | 106 | pattern_param = [[] for _ in range(pattern_num)] 107 | with open('param_pattern.txt', 'r') as f: 108 | for i in range(pattern_num): 109 | for j in range(each_param_num[i]): 110 | pattern_param[i].append(float(f.readline())) 111 | weight = [[] for _ in range(pattern_num)] 112 | with open('patttern_weight.txt', 'r') as f: 113 | for i in range(pattern_num): 114 | for j in range(3): 115 | weight[i].append(float(f.readline())) 116 | 117 | win_num = [[0 for _ in range(each_param_num[i])] for i in range(pattern_num)] 118 | seen_num = [[0 for _ in range(each_param_num[i])] for i in range(pattern_num)] 119 | ans = [[0 for _ in range(each_param_num[i])] for i in range(pattern_num)] 120 | 121 | seen_grid = [] 122 | prospect = [] 123 | 124 | 125 | hw = 8 126 | hw2 = 64 127 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 128 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 129 | 130 | def empty(grid, y, x): 131 | return grid[y][x] == -1 or grid[y][x] == 2 132 | 133 | def inside(y, x): 134 | return 0 <= y < hw and 0 <= x < hw 135 | 136 | def check(grid, player, y, x): 137 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 138 | res = 0 139 | for dr in range(8): 140 | ny = y + dy[dr] 141 | nx = x + dx[dr] 142 | if not inside(ny, nx): 143 | continue 144 | if empty(grid, ny, nx): 145 | continue 146 | if grid[ny][nx] == player: 147 | continue 148 | #print(y, x, dr, ny, nx) 149 | plus = 0 150 | flag = False 151 | for d in range(hw): 152 | nny = ny + d * dy[dr] 153 | nnx = nx + d * dx[dr] 154 | if not inside(nny, nnx): 155 | break 156 | if empty(grid, nny, nnx): 157 | break 158 | if grid[nny][nnx] == player: 159 | flag = True 160 | break 161 | #print(y, x, dr, nny, nnx) 162 | plus += 1 163 | if flag: 164 | res += plus 165 | for d in range(plus): 166 | nny = ny + d * dy[dr] 167 | nnx = nx + d * dx[dr] 168 | res_grid[nny][nnx] = True 169 | return res, res_grid 170 | 171 | class reversi: 172 | def __init__(self): 173 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 174 | self.grid[3][3] = 1 175 | self.grid[3][4] = 0 176 | self.grid[4][3] = 0 177 | self.grid[4][4] = 1 178 | self.player = 0 # 0: 黒 1: 白 179 | self.nums = [2, 2] 180 | 181 | def move(self, y, x): 182 | plus, plus_grid = check(self.grid, self.player, y, x) 183 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 184 | print('Please input a correct move') 185 | return 1 186 | self.grid[y][x] = self.player 187 | for ny in range(hw): 188 | for nx in range(hw): 189 | if plus_grid[ny][nx]: 190 | self.grid[ny][nx] = self.player 191 | self.nums[self.player] += 1 + plus 192 | self.nums[1 - self.player] -= plus 193 | self.player = 1 - self.player 194 | return 0 195 | 196 | def check_pass(self): 197 | for y in range(hw): 198 | for x in range(hw): 199 | if self.grid[y][x] == 2: 200 | self.grid[y][x] = -1 201 | res = True 202 | for y in range(hw): 203 | for x in range(hw): 204 | if not empty(self.grid, y, x): 205 | continue 206 | plus, _ = check(self.grid, self.player, y, x) 207 | if plus: 208 | res = False 209 | self.grid[y][x] = 2 210 | if res: 211 | #print('Pass!') 212 | self.player = 1 - self.player 213 | return res 214 | 215 | def output(self): 216 | print(' ', end='') 217 | for i in range(hw): 218 | print(chr(ord('a') + i), end=' ') 219 | print('') 220 | for y in range(hw): 221 | print(str(y + 1) + ' ', end='') 222 | for x in range(hw): 223 | print('○' if self.grid[y][x] == 0 else '●' if self.grid[y][x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 224 | print('') 225 | 226 | def output_file(self): 227 | res = '' 228 | for y in range(hw): 229 | for x in range(hw): 230 | res += '*' if self.grid[y][x] == 0 else 'O' if self.grid[y][x] == 1 else '-' 231 | res += ' *' 232 | return res 233 | 234 | def end(self): 235 | if min(self.nums) == 0: 236 | return True 237 | res = True 238 | for y in range(hw): 239 | for x in range(hw): 240 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 241 | res = False 242 | return res 243 | 244 | def judge(self): 245 | if self.nums[0] > self.nums[1]: 246 | #print('Black won!', self.nums[0], '-', self.nums[1]) 247 | return 0 248 | elif self.nums[1] > self.nums[0]: 249 | #print('White won!', self.nums[0], '-', self.nums[1]) 250 | return 1 251 | else: 252 | #print('Draw!', self.nums[0], '-', self.nums[1]) 253 | return -1 254 | 255 | def translate_p(grid, arr): 256 | res = [] 257 | for i in range(len(arr)): 258 | tmp = 0 259 | for j in reversed(range(len(arr[i]))): 260 | tmp *= 3 261 | tmp2 = grid[arr[i][j] // hw][arr[i][j] % hw] 262 | if tmp2 == 0: 263 | tmp += 1 264 | elif tmp2 == 1: 265 | tmp += 2 266 | res.append(tmp) 267 | return res 268 | 269 | def translate_o(grid, arr): 270 | res = [] 271 | for i in range(len(arr)): 272 | tmp = 0 273 | for j in reversed(range(len(arr[i]))): 274 | tmp *= 3 275 | tmp2 = grid[arr[i][j] // hw][arr[i][j] % hw] 276 | if tmp2 == 1: 277 | tmp += 1 278 | elif tmp2 == 0: 279 | tmp += 2 280 | res.append(tmp) 281 | return res 282 | 283 | def calc_weight(idx, x): 284 | x1 = 4.0 / 64 285 | x2 = 32.0 / 64 286 | x3 = 64.0 / 64 287 | y1, y2, y3 = weight[idx] 288 | a = ((y1 - y2) * (x1 - x3) - (y1 - y3) * (x1 - x2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) 289 | b = (y1 - y2) / (x1 - x2) - a * (x1 + x2) 290 | c = y1 - a * x1 * x1 - b * x1 291 | return a * x * x + b * x + c 292 | 293 | def collect(s): 294 | global seen_grid, prospect 295 | grids = [] 296 | rv = reversi() 297 | idx = 2 298 | while True: 299 | if rv.check_pass() and rv.check_pass(): 300 | break 301 | turn = 0 if s[idx] == '+' else 1 302 | x = ord(s[idx + 1]) - ord('a') 303 | y = int(s[idx + 2]) - 1 304 | idx += 3 305 | if rv.move(y, x): 306 | print('error') 307 | break 308 | grids.append([[i for i in j] for j in rv.grid]) 309 | if rv.end(): 310 | break 311 | rv.check_pass() 312 | #if abs(rv.nums[0] - rv.nums[1]) < 20: 313 | # return 314 | rv.output() 315 | #winner = rv.judge() 316 | x = range(len(grids)) 317 | y = [] 318 | result = [2.0 / (1.0 + exp(-(rv.nums[0] - rv.nums[1]) / 5)) - 1.0 for _ in range(len(grids))] 319 | for turn, grid in enumerate(grids): 320 | val = 0.0 321 | for i in range(pattern_num): 322 | tmp = 0.0 323 | for j in translate_p(grid, eval_translate[i]): 324 | tmp += pattern_param[i][j] 325 | val += tmp * calc_weight(i, (turn + 4) / hw2) 326 | y.append(val) 327 | plt.plot(x, y) 328 | plt.plot(x, result) 329 | plt.ylim(-1.25, 1.25) 330 | plt.show() 331 | 332 | with open('third_party/xxx.gam', 'rb') as f: 333 | raw_data = f.read() 334 | games = [i for i in raw_data.splitlines()] 335 | 336 | num = 1000 337 | #lst = [randint(0, 100000) for _ in range(num)] 338 | for i in trange(num): 339 | collect(str(games[i])) -------------------------------------------------------------------------------- /adjust_params.py: -------------------------------------------------------------------------------- 1 | from random import random, randint 2 | import subprocess 3 | import trueskill 4 | from tqdm import trange 5 | from time import time 6 | 7 | hw = 8 8 | hw2 = 64 9 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 10 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 11 | 12 | population = 10 13 | param_num = 95 14 | change_param = list(range(param_num))#list(set(range(param_num)) - set([65, 64, 63]) - set(range(30))) # list(set(range(51, 78)) | set([45, 46, 47])) 15 | tim = 10 16 | 17 | def empty(grid, y, x): 18 | return grid[y][x] == -1 or grid[y][x] == 2 19 | 20 | def inside(y, x): 21 | return 0 <= y < hw and 0 <= x < hw 22 | 23 | def check(grid, player, y, x): 24 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 25 | res = 0 26 | for dr in range(8): 27 | ny = y + dy[dr] 28 | nx = x + dx[dr] 29 | if not inside(ny, nx): 30 | continue 31 | if empty(grid, ny, nx): 32 | continue 33 | if grid[ny][nx] == player: 34 | continue 35 | #print(y, x, dr, ny, nx) 36 | plus = 0 37 | flag = False 38 | for d in range(hw): 39 | nny = ny + d * dy[dr] 40 | nnx = nx + d * dx[dr] 41 | if not inside(nny, nnx): 42 | break 43 | if empty(grid, nny, nnx): 44 | break 45 | if grid[nny][nnx] == player: 46 | flag = True 47 | break 48 | #print(y, x, dr, nny, nnx) 49 | plus += 1 50 | if flag: 51 | res += plus 52 | for d in range(plus): 53 | nny = ny + d * dy[dr] 54 | nnx = nx + d * dx[dr] 55 | res_grid[nny][nnx] = True 56 | return res, res_grid 57 | 58 | class reversi: 59 | def __init__(self): 60 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 61 | self.grid[3][3] = 1 62 | self.grid[3][4] = 0 63 | self.grid[4][3] = 0 64 | self.grid[4][4] = 1 65 | self.player = 0 # 0: 黒 1: 白 66 | self.nums = [2, 2] 67 | 68 | def move(self, y, x): 69 | plus, plus_grid = check(self.grid, self.player, y, x) 70 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 71 | print('Please input a correct move') 72 | return 1 73 | self.grid[y][x] = self.player 74 | for ny in range(hw): 75 | for nx in range(hw): 76 | if plus_grid[ny][nx]: 77 | self.grid[ny][nx] = self.player 78 | self.nums[self.player] += 1 + plus 79 | self.nums[1 - self.player] -= plus 80 | self.player = 1 - self.player 81 | return 0 82 | 83 | def check_pass(self): 84 | for y in range(hw): 85 | for x in range(hw): 86 | if self.grid[y][x] == 2: 87 | self.grid[y][x] = -1 88 | res = True 89 | for y in range(hw): 90 | for x in range(hw): 91 | if not empty(self.grid, y, x): 92 | continue 93 | plus, _ = check(self.grid, self.player, y, x) 94 | if plus: 95 | res = False 96 | self.grid[y][x] = 2 97 | if res: 98 | #print('Pass!') 99 | self.player = 1 - self.player 100 | return res 101 | 102 | def output(self): 103 | print(' ', end='') 104 | for i in range(hw): 105 | print(chr(ord('a') + i), end=' ') 106 | print('') 107 | for y in range(hw): 108 | print(str(y + 1) + ' ', end='') 109 | for x in range(hw): 110 | print('○' if self.grid[y][x] == 0 else '●' if self.grid[y][x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 111 | print('') 112 | 113 | def output_file(self): 114 | res = '' 115 | for y in range(hw): 116 | for x in range(hw): 117 | res += '*' if self.grid[y][x] == 0 else 'O' if self.grid[y][x] == 1 else '-' 118 | res += ' *' 119 | return res 120 | 121 | def end(self): 122 | if min(self.nums) == 0: 123 | return True 124 | res = True 125 | for y in range(hw): 126 | for x in range(hw): 127 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 128 | res = False 129 | return res 130 | 131 | def judge(self): 132 | if self.nums[0] > self.nums[1]: 133 | #print('Black won!', self.nums[0], '-', self.nums[1]) 134 | return 0 135 | elif self.nums[1] > self.nums[0]: 136 | #print('White won!', self.nums[0], '-', self.nums[1]) 137 | return 1 138 | else: 139 | #print('Draw!', self.nums[0], '-', self.nums[1]) 140 | return -1 141 | 142 | def match(param0, param1): 143 | while True: 144 | try: 145 | with open('param0.txt', 'w') as f: 146 | for i in range(param_num): 147 | f.write(str(param0[i]) + '\n') 148 | break 149 | except: 150 | continue 151 | while True: 152 | try: 153 | with open('param1.txt', 'w') as f: 154 | for i in range(param_num): 155 | f.write(str(param1[i]) + '\n') 156 | break 157 | except: 158 | continue 159 | res0 = -1 160 | res1 = -1 161 | ai = [subprocess.Popen(('./a.exe param' + str(i) + '.txt').split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE) for i in range(2)] 162 | for i in range(2): 163 | stdin = str(i) + '\n' + str(100) + '\n' 164 | ai[i].stdin.write(stdin.encode('utf-8')) 165 | ai[i].stdin.flush() 166 | rv = reversi() 167 | while True: 168 | if rv.check_pass() and rv.check_pass(): 169 | break 170 | #rv.output() 171 | y = -1 172 | x = -1 173 | stdin = '' 174 | for y in range(hw): 175 | for x in range(hw): 176 | stdin += str(rv.grid[y][x]) + ' ' 177 | stdin += '\n' 178 | ai[rv.player].stdin.write(stdin.encode('utf-8')) 179 | ai[rv.player].stdin.flush() 180 | #print(stdin) 181 | #print(rv.player) 182 | s = time() 183 | y, x = [int(i) for i in ai[rv.player].stdout.readline().decode().strip().split()] 184 | if (time() - s > 0.2): 185 | print(stdin) 186 | print(rv.player) 187 | print(y, x) 188 | if rv.move(y, x): 189 | print(stdin) 190 | print(rv.player) 191 | print(y, x) 192 | if rv.end(): 193 | break 194 | rv.check_pass() 195 | #rv.output() 196 | winner = rv.judge() 197 | if winner == 0: 198 | res0 = 0 199 | res1 = 1 200 | elif winner == -1: 201 | res0 = 0 202 | res1 = 0 203 | else: 204 | res0 = 1 205 | res1 = 0 206 | for i in range(2): 207 | ai[i].kill() 208 | return res0, res1 209 | ''' 210 | def rate(idx1): 211 | idx2 = randint(0, population - 1) 212 | r1, r2 = match(parents[idx1][0], diversity[idx2][0]) 213 | (parents[idx1][1],),(diversity[idx2][1],), = env.rate(((parents[idx1][1],), (diversity[idx2][1],),), ranks=[r1, r2,]) 214 | r2, r1 = match(diversity[idx2][0], parents[idx1][0]) 215 | (parents[idx1][1],),(diversity[idx2][1],), = env.rate(((parents[idx1][1],), (diversity[idx2][1],),), ranks=[r1, r2,]) 216 | ''' 217 | def rate_children(param, rating, idx2): 218 | #idx2 = randint(0, population - 1) 219 | r1, r2 = match(param, diversity[idx2]) 220 | if r1 < r2: 221 | rating += 1 222 | elif r1 > r2: 223 | rating -= 1 224 | #(rating,),(diversity[idx2][1],), = env.rate(((rating,), (diversity[idx2][1],),), ranks=[r1, r2,]) 225 | r2, r1 = match(diversity[idx2], param) 226 | if r1 < r2: 227 | rating += 1 228 | elif r1 > r2: 229 | rating -= 1 230 | #(rating,),(diversity[idx2][1],), = env.rate(((rating,), (diversity[idx2][1],),), ranks=[r1, r2,]) 231 | return rating 232 | 233 | mu = 25. 234 | sigma = mu / 3. 235 | beta = sigma / 2. 236 | tau = sigma / 100. 237 | draw_probability = 0.1 238 | backend = None 239 | 240 | env = trueskill.TrueSkill( 241 | mu=mu, sigma=sigma, beta=beta, tau=tau, 242 | draw_probability=draw_probability, backend=backend) 243 | 244 | def hill_climb(param, tl): 245 | strt = time() 246 | max_rating = env.create_rating() 247 | for i in range(tim): 248 | max_rating = rate_children(param, max_rating, i) 249 | while time() - strt < tl: 250 | f_param = [i for i in param] 251 | param[randint(20, 33)] += random() * 0.06 - 0.03 252 | rating = env.create_rating() 253 | for i in range(tim): 254 | rating = rate_children(param, rating, i) 255 | if env.expose(max_rating) < env.expose(rating): 256 | max_rating = rating 257 | else: 258 | param = [i for i in f_param] 259 | return param, max_rating 260 | 261 | ''' 262 | parents = [] 263 | for _ in range(1): 264 | param = [] 265 | for i in range(param_num): 266 | param.append(param_base[i]) 267 | parents.append([param, env.create_rating()]) 268 | for _ in range(1, population): 269 | param = [] 270 | for i in range(20): 271 | param.append(param_base[i]) 272 | for i in range(20, 34): 273 | param.append(param_base[i] + random() * 0.5 - 0.25) 274 | for i in range(34, param_num): 275 | param.append(param_base[i]) 276 | parents.append([param, env.create_rating()]) 277 | ''' 278 | while True: 279 | param_base = [] 280 | with open('param_base.txt', 'r') as f: 281 | for _ in range(param_num): 282 | param_base.append(float(f.readline())) 283 | diversity = [] 284 | for _ in range(population): 285 | param = [] 286 | for i in range(param_num): 287 | if i in change_param: 288 | param.append(param_base[i] + random() * 0.6 - 0.3) 289 | else: 290 | param.append(param_base[i]) 291 | diversity.append(param) 292 | ''' 293 | parents = [] 294 | for _ in range(population): 295 | param = [] 296 | for i in range(param_num): 297 | param.append(random()) 298 | parents.append([param, env.create_rating()]) 299 | ''' 300 | ''' 301 | for i in trange(population * tim): 302 | rate(i % population) 303 | ''' 304 | cnt = 0 305 | max_rating = 0 #env.create_rating() 306 | for i in trange(tim): 307 | max_rating = rate_children(param_base, max_rating, i) 308 | max_param = [i for i in param_base] 309 | max_float_rating = max_rating 310 | while True: 311 | f_param = [param_base[i] for i in range(param_num)] 312 | param_base[change_param[randint(0, len(change_param) - 1)]] += random() * 1.0 - 0.5 313 | rating = 0 #env.create_rating() 314 | for i in range(tim): 315 | rating = rate_children(param_base, rating, i) 316 | if max_float_rating <= rating: 317 | max_rating = rating 318 | max_float_rating = rating 319 | with open('param.txt', 'w') as f: 320 | for i in range(param_num): 321 | f.write(str(param_base[i]) + '\n') 322 | else: 323 | param_base = [f_param[i] for i in range(param_num)] 324 | print(cnt, max_float_rating, max_rating, rating) 325 | if max_rating > tim * 2 * 0.75: 326 | break 327 | cnt += 1 328 | with open('param_base.txt', 'w') as f: 329 | for i in range(param_num): 330 | f.write(str(param_base[i]) + '\n') 331 | 332 | ''' 333 | while True: 334 | idx1 = randint(0, population - 1) 335 | idx2 = idx1 336 | while idx1 == idx2: 337 | idx2 = randint(0, population - 1) 338 | children = [[i for i in hill_climb(parents[idx1][0], 5.0)], [i for i in hill_climb(parents[idx2][0], 5.0)]] 339 | param1 = [] 340 | param2 = [] 341 | dv = randint(21, 32) 342 | for i in range(dv): 343 | param1.append(parents[idx1][0][i]) 344 | param2.append(parents[idx2][0][i]) 345 | for i in range(dv, param_num): 346 | param1.append(parents[idx2][0][i]) 347 | param2.append(parents[idx1][0][i]) 348 | children.append([i for i in hill_climb(param1, 5.0)]) 349 | children.append([i for i in hill_climb(param2, 5.0)]) 350 | children.sort(key=lambda x: env.expose(x[1]), reverse=True) 351 | parents[idx1] = children[0] 352 | parents[idx2] = children[1] 353 | arr = [env.expose(parents[i][1]) for i in range(population)] 354 | idx = arr.index(max(arr)) 355 | print(cnt, arr[idx]) 356 | with open('param.txt', 'w') as f: 357 | for i in range(param_num): 358 | f.write(str(parents[idx][0][i]) + '\n') 359 | cnt += 1 360 | ''' -------------------------------------------------------------------------------- /legacy/AI_Cpp/adjust_parameter_ga.py: -------------------------------------------------------------------------------- 1 | # reversi software 2 | import subprocess 3 | from time import sleep 4 | from random import random, randint, shuffle 5 | import matplotlib.pyplot as plt 6 | 7 | hw = 8 8 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 9 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 10 | 11 | def empty(grid, y, x): 12 | return grid[y][x] == -1 or grid[y][x] == 2 13 | 14 | def inside(y, x): 15 | return 0 <= y < hw and 0 <= x < hw 16 | 17 | def check(grid, player, y, x): 18 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 19 | res = 0 20 | for dr in range(8): 21 | ny = y + dy[dr] 22 | nx = x + dx[dr] 23 | if not inside(ny, nx): 24 | continue 25 | if empty(grid, ny, nx): 26 | continue 27 | if grid[ny][nx] == player: 28 | continue 29 | #print(y, x, dr, ny, nx) 30 | plus = 0 31 | flag = False 32 | for d in range(hw): 33 | nny = ny + d * dy[dr] 34 | nnx = nx + d * dx[dr] 35 | if not inside(nny, nnx): 36 | break 37 | if empty(grid, nny, nnx): 38 | break 39 | if grid[nny][nnx] == player: 40 | flag = True 41 | break 42 | #print(y, x, dr, nny, nnx) 43 | plus += 1 44 | if flag: 45 | res += plus 46 | for d in range(plus): 47 | nny = ny + d * dy[dr] 48 | nnx = nx + d * dx[dr] 49 | res_grid[nny][nnx] = True 50 | return res, res_grid 51 | 52 | class reversi: 53 | def __init__(self): 54 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 55 | self.grid[3][3] = 1 56 | self.grid[3][4] = 0 57 | self.grid[4][3] = 0 58 | self.grid[4][4] = 1 59 | self.player = 0 # 0: 黒 1: 白 60 | self.nums = [2, 2] 61 | 62 | def move(self, y, x): 63 | plus, plus_grid = check(self.grid, self.player, y, x) 64 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 65 | #print('Please input a correct move') 66 | return 1 67 | self.grid[y][x] = self.player 68 | for ny in range(hw): 69 | for nx in range(hw): 70 | if plus_grid[ny][nx]: 71 | self.grid[ny][nx] = self.player 72 | self.nums[self.player] += 1 + plus 73 | self.nums[1 - self.player] -= plus 74 | self.player = 1 - self.player 75 | return 0 76 | 77 | def check_pass(self): 78 | for y in range(hw): 79 | for x in range(hw): 80 | if self.grid[y][x] == 2: 81 | self.grid[y][x] = -1 82 | res = True 83 | for y in range(hw): 84 | for x in range(hw): 85 | if not empty(self.grid, y, x): 86 | continue 87 | plus, _ = check(self.grid, self.player, y, x) 88 | if plus: 89 | res = False 90 | self.grid[y][x] = 2 91 | if res: 92 | #print('Pass!') 93 | self.player = 1 - self.player 94 | return res 95 | 96 | def output(self): 97 | print(' ', end='') 98 | for i in range(hw): 99 | print(chr(ord('a') + i), end=' ') 100 | print('') 101 | for y in range(hw): 102 | print(str(y + 1) + ' ', end='') 103 | for x in range(hw): 104 | print('○' if self.grid[y][x] == 0 else '●' if self.grid[y][x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 105 | print('') 106 | 107 | def end(self): 108 | if min(self.nums) == 0: 109 | return True 110 | res = True 111 | for y in range(hw): 112 | for x in range(hw): 113 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 114 | res = False 115 | return res 116 | 117 | def judge(self): 118 | if self.nums[0] > self.nums[1]: 119 | #print('Black won!', self.nums[0], '-', self.nums[1]) 120 | return 0 121 | elif self.nums[1] > self.nums[0]: 122 | #print('White won!', self.nums[0], '-', self.nums[1]) 123 | return 1 124 | else: 125 | #print('Draw!', self.nums[0], '-', self.nums[1]) 126 | return -1 127 | 128 | translate = [ 129 | 0, 1, 2, 3, 3, 2, 1, 0, 130 | 1, 4, 5, 6, 6, 5, 4, 1, 131 | 2, 5, 7, 8, 8, 7, 5, 2, 132 | 3, 6, 8, 9, 9, 8, 6, 3, 133 | 3, 6, 8, 9, 9, 8, 6, 3, 134 | 2, 5, 7, 8, 8, 7, 5, 2, 135 | 1, 4, 5, 6, 6, 5, 4, 1, 136 | 0, 1, 2, 3, 3, 2, 1, 0 137 | ] 138 | 139 | def input_param(p, param, grid): 140 | for j in range(param_num): 141 | s = '' 142 | for i in range(max_turn): 143 | s += str(param[i][j]) + ' ' 144 | s += '\n' 145 | p.stdin.write(s.encode('utf-8')) 146 | p.stdin.flush() 147 | for i in range(max_turn): 148 | s = '' 149 | for j in range(hw * hw): 150 | s += str(grid[i][translate[j]]) + ' ' 151 | s += '\n' 152 | p.stdin.write(s.encode('utf-8')) 153 | p.stdin.flush() 154 | 155 | def match(param1, grid1, param2, grid2): 156 | ai = [subprocess.Popen('a.exe'.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE) for _ in range(2)] 157 | me = randint(0, 1) 158 | stdin = str(me) + '\n' + str(tl) + '\n' 159 | ai[0].stdin.write(stdin.encode('utf-8')) 160 | input_param(ai[0], param1, grid1) 161 | stdin = str(1 - me) + '\n' + str(tl) + '\n' 162 | ai[1].stdin.write(stdin.encode('utf-8')) 163 | input_param(ai[1], param2, grid2) 164 | rv = reversi() 165 | while True: 166 | if rv.check_pass() and rv.check_pass(): 167 | break 168 | stdin = '' 169 | for y in range(hw): 170 | for x in range(hw): 171 | stdin += str(rv.grid[y][x]) + ' ' 172 | stdin += '\n' 173 | if rv.player == me: 174 | ai[0].stdin.write(stdin.encode('utf-8')) 175 | ai[0].stdin.flush() 176 | y, x = [int(i) for i in ai[0].stdout.readline().decode().strip().split()] 177 | else: 178 | ai[1].stdin.write(stdin.encode('utf-8')) 179 | ai[1].stdin.flush() 180 | y, x = [int(i) for i in ai[1].stdout.readline().decode().strip().split()] 181 | if rv.move(y, x): 182 | print('illegal move') 183 | for i in range(2): 184 | ai[i].kill() 185 | return 0 186 | if rv.end(): 187 | break 188 | rv.check_pass() 189 | winner = rv.judge() 190 | for i in range(2): 191 | ai[i].kill() 192 | return rv.nums[me] - rv.nums[1 - me] if rv.nums[me] > 0 and rv.nums[1 - me] > 0 else hw * hw if rv.nums[1 - me] == 0 else -hw * hw 193 | 194 | def normalize_weight(arr): 195 | sm = sum(arr) 196 | for i in range(param_num): 197 | arr[i] /= sm 198 | return arr 199 | 200 | def normalize_grid(arr): 201 | t = [4, 8, 8, 8, 4, 8, 8, 4, 8, 4] 202 | for i in range(grid_param_num): 203 | arr[i] *= t[i] 204 | sm = sum(arr) 205 | for i in range(grid_param_num): 206 | arr[i] /= sm 207 | for i in range(grid_param_num): 208 | arr[i] /= t[i] 209 | return arr 210 | 211 | def moving_avg(arr, s, e): 212 | for j in range(len(arr[0])): 213 | for i in range(s, e): 214 | sm = 0 215 | for k in range(i, i + avg_num): 216 | sm += arr[k][j] 217 | arr[i][j] = sm / avg_num 218 | return arr 219 | 220 | def write_output(param, grid): 221 | with open('params.txt', 'w') as f: 222 | for j in range(param_num): 223 | for i in range(max_turn): 224 | f.write(str(param[i][j]) + '\n') 225 | for i in range(max_turn): 226 | for j in range(hw * hw): 227 | f.write(str(grid[i][translate[j]]) + '\n') 228 | 229 | population = 200 230 | match_num = 20 231 | param_num = 6 232 | grid_param_num = 10 233 | max_turn = 60 234 | avg_num = 30 235 | tl = 100 236 | 237 | param_base = [0.25, 0.3, 0.0, 0.2, 0.1, 0.05] #[0.30288811933933507, 0.023667040619869673, 0.38484168625403836, 0.11491476667436311, 0.17290370673757446, 0.0007846803748192674, 0.12637328291777342, 0.27743891909702173, 0.3224275886777521, 0.12516714992181288, 0.017010853296369526, 0.1315822060892702] 238 | grid_base = [68, -12, 53, -8, -62, -33, -7, 26, 8, -18] 239 | 240 | 241 | param = [[[0.0 for _ in range(param_num)] for _ in range(max_turn + avg_num * 2)] for _ in range(population)] 242 | grid = [[[0.0 for _ in range(grid_param_num)] for _ in range(max_turn + avg_num * 2)] for _ in range(population)] 243 | for i in range(population): 244 | for j in range(max_turn + avg_num): 245 | for k in range(param_num): 246 | param[i][j][k] = random() 247 | for k in range(grid_param_num): 248 | grid[i][j][k] = random() 249 | param[i] = moving_avg(param[i], 0, max_turn + avg_num) 250 | grid[i] = moving_avg(grid[i], 0, max_turn + avg_num) 251 | for j in range(max_turn): 252 | param[i][j] = normalize_weight(param[i][j]) 253 | grid[i][j] = normalize_grid(grid[i][j]) 254 | ''' 255 | x = range(max_turn) 256 | y = [param[i][j][0] for j in range(max_turn)] 257 | plt.plot(x, y) 258 | plt.show() 259 | ''' 260 | 261 | win_rate = [0 for _ in range(population)] 262 | parents = [-1, -1] 263 | children = [[[-1 for _ in range(param_num)] for _ in range(max_turn + avg_num * 2)] for _ in range(2)] 264 | children_grid = [[[-1 for _ in range(grid_param_num)] for _ in range(max_turn + avg_num * 2)] for _ in range(2)] 265 | 266 | for i in range(population): 267 | for _ in range(match_num): 268 | op = randint(0, population - 1) 269 | win_rate[i] += match(param[i], grid[i], param[op], grid[op]) 270 | win_rate[i] /= match_num 271 | print(win_rate[i]) 272 | 273 | print('initialized') 274 | 275 | cnt = 0 276 | t = 0 277 | while True: 278 | parents[0] = randint(0, population - 1) 279 | parents[1] = parents[0] 280 | while parents[1] == parents[0]: 281 | parents[1] = randint(0, population - 1) 282 | div1 = randint(1, max_turn + avg_num - 1) 283 | for i in range(div1): 284 | for j in range(param_num): 285 | children[0][i][j] = param[parents[0]][i][j] 286 | children[1][i][j] = param[parents[1]][i][j] 287 | for j in range(grid_param_num): 288 | children_grid[0][i][j] = grid[parents[0]][i][j] 289 | children_grid[1][i][j] = grid[parents[1]][i][j] 290 | for i in range(div1, max_turn + avg_num * 2): 291 | for j in range(param_num): 292 | children[0][i][j] = param[parents[1]][i][j] 293 | children[1][i][j] = param[parents[0]][i][j] 294 | for j in range(grid_param_num): 295 | children_grid[0][i][j] = grid[parents[1]][i][j] 296 | children_grid[1][i][j] = grid[parents[0]][i][j] 297 | ''' 298 | x = range(max_turn) 299 | y = [param[parents[0]][j][0] for j in range(max_turn)] 300 | plt.plot(x, y) 301 | y = [param[parents[1]][j][0] - 0.1 for j in range(max_turn)] 302 | plt.plot(x, y) 303 | y = [children[0][j][0] - 0.2 for j in range(max_turn)] 304 | plt.plot(x, y) 305 | for i in range(2): 306 | children[i] = moving_avg(children[i], max(0, div1 - avg_num), div1) 307 | children_grid[i] = moving_avg(children_grid[i], max(0, div1 - avg_num), div1) 308 | x = range(max_turn) 309 | y = [children[0][j][0] - 0.3 for j in range(max_turn)] 310 | plt.plot(x, y) 311 | print(div1) 312 | plt.show() 313 | ''' 314 | for i in range(2): 315 | for j in range(max_turn): 316 | children[i][j] = normalize_weight(children[i][j]) 317 | children_grid[i][j] = normalize_grid(children_grid[i][j]) 318 | individual = [] 319 | for i in range(2): 320 | individual.append([0.0, param[parents[i]], grid[parents[i]]]) 321 | for i in range(2): 322 | individual.append([0.0, children[i], children_grid[i]]) 323 | for child in range(4): 324 | for _ in range(match_num): 325 | op = randint(0, population - 1) 326 | individual[child][0] += match(individual[child][1], individual[child][2], param[op], grid[op]) 327 | individual[child][0] /= match_num 328 | individual.sort(reverse=True) 329 | #print([i[0] for i in individual]) 330 | for i in range(2): 331 | param[parents[i]] = [[ii for ii in jj] for jj in individual[i][1]] 332 | grid[parents[i]] = [[ii for ii in jj] for jj in individual[i][2]] 333 | win_rate[parents[i]] = individual[i][0] 334 | cnt += 1 335 | t += 1 336 | #if t & (1 << 1): 337 | t = 0 338 | mx = max(win_rate) 339 | mx_idx = win_rate.index(mx) 340 | print(cnt, mx) 341 | write_output(param[mx_idx], grid[mx_idx]) 342 | 343 | -------------------------------------------------------------------------------- /adjust_pattern.py: -------------------------------------------------------------------------------- 1 | from random import random 2 | import subprocess 3 | from time import time 4 | from random import randint, random 5 | from tqdm import trange 6 | from math import exp, log, sqrt 7 | 8 | start_temp = 20 9 | end_temp = 0.01 10 | 11 | def tempera(strt, now, tl): 12 | x = (now - strt) / tl 13 | return pow(start_temp, 1 - x) * pow(end_temp, x) 14 | #return start_temp + (end_tmp - start_temp) * (now - strt) / tl 15 | 16 | def prob(p_score, n_score, strt, now, tl): 17 | dis = n_score - p_score 18 | if dis >= 0.0: 19 | return 1.0 20 | return exp(dis / tempera(strt, now, tl)) 21 | 22 | pattern_num = 5 23 | index_num = 38 24 | param_num = 92 25 | 26 | base_param = [] 27 | with open('param_base.txt', 'r') as f: 28 | for _ in range(param_num): 29 | base_param.append(float(f.readline())) 30 | 31 | ''' 32 | translate_raw = [ 33 | [0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 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], 34 | [0, 8, 16, 24, 32, 40, 48, 56], [1, 9, 17, 25, 33, 41, 49, 57], [2, 10, 18, 26, 34, 42, 50, 58], [3, 11, 19, 27, 35, 43, 51, 59], [4, 12, 20, 28, 36, 44, 52, 60], [5, 13, 21, 29, 37, 45, 53, 61], [6, 14, 22, 30, 38, 46, 54, 62], [7, 15, 23, 31, 39, 47, 55, 63], 35 | [5, 14, 23], [4, 13, 22, 31], [3, 12, 21, 30, 39], [2, 11, 20, 29, 38, 47], [1, 10, 19, 28, 37, 46, 55], [0, 9, 18, 27, 36, 45, 54, 63], [8, 17, 26, 35, 44, 53, 62], [16, 25, 34, 43, 52, 61], [24, 33, 42, 51, 60], [32, 41, 50, 59], [40, 49, 58], 36 | [2, 9, 16], [3, 10, 17, 24], [4, 11, 18, 25, 32], [5, 12, 19, 26, 33, 40], [6, 13, 20, 27, 34, 41, 48], [7, 14, 21, 28, 35, 42, 49, 56], [15, 22, 29, 36, 43, 50, 57], [23, 30, 37, 44, 51, 58], [31, 38, 45, 52, 59], [39, 46, 53, 60], [47, 54, 61] 37 | ] 38 | same_param = [0, 1, 2, 3, 3, 2, 1, 0, 0, 1, 2, 3, 3, 2, 1, 0, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4] 39 | ''' 40 | translate = [] 41 | eval_translate = [] 42 | each_param_num = [] 43 | 44 | edgex1 = [ 45 | [54, 63, 62, 61, 60, 59, 58, 57, 56, 49], 46 | [49, 56, 48, 40, 32, 24, 16, 8, 0, 9], 47 | [9, 0, 1, 2, 3, 4, 5, 6, 7, 14], 48 | [14, 7, 15, 23, 31, 39, 47, 55, 63, 54] 49 | ] 50 | 51 | edgex2 = [] 52 | for arr in edgex1: 53 | edgex2.append(arr) 54 | edgex2.append(list(reversed(arr))) 55 | translate.append(edgex2) 56 | eval_translate.append(edgex1) 57 | each_param_num.append(3 ** 10) 58 | 59 | corner1= [ 60 | [3, 2, 1, 0, 9, 8, 16, 24], 61 | [4, 5, 6, 7, 14, 15, 23, 31], 62 | [60, 61, 62, 63, 54, 55, 47, 39], 63 | [59, 58, 57, 56, 49, 48, 40, 32] 64 | ] 65 | 66 | corner2 = [ 67 | [3, 2, 1, 0, 9, 8, 16, 24], 68 | [24, 16, 8, 0, 9, 1, 2, 3], 69 | [4, 5, 6, 7, 14, 15, 23, 31], 70 | [31, 23, 15, 7, 14, 6, 5, 4], 71 | [60, 61, 62, 63, 54, 55, 47, 39], 72 | [39, 47, 55, 63, 54, 62, 61, 60], 73 | [59, 58, 57, 56, 49, 48, 40, 32], 74 | [32, 40, 48, 56, 49, 57, 58, 59] 75 | ] 76 | 77 | translate.append(corner2) 78 | eval_translate.append(corner1) 79 | each_param_num.append(3 ** 8) 80 | 81 | corner24 = [ 82 | [0, 1, 2, 3, 8, 9, 10, 11], 83 | [0, 8, 16, 24, 1, 9, 17, 25], 84 | [7, 6, 5, 4, 15, 14, 13, 12], 85 | [7, 15, 23, 31, 6, 14, 22, 30], 86 | [63, 62, 61, 60, 55, 54, 53, 52], 87 | [63, 55, 47, 39, 62, 54, 46, 38], 88 | [56, 57, 58, 59, 48, 49, 50, 51], 89 | [56, 48, 40, 32, 57, 49, 41, 33] 90 | ] 91 | 92 | translate.append(corner24) 93 | eval_translate.append(corner24) 94 | each_param_num.append(3 ** 8) 95 | 96 | diagonal1 = [ 97 | [0, 9, 18, 27, 36, 45, 54, 63], 98 | [7, 14, 21, 28, 35, 42, 49, 56] 99 | ] 100 | 101 | diagonal2 = [] 102 | for arr in diagonal1: 103 | diagonal2.append(arr) 104 | diagonal2.append(list(reversed(arr))) 105 | translate.append(diagonal2) 106 | eval_translate.append(diagonal1) 107 | each_param_num.append(3 ** 8) 108 | 109 | edge1 = [ 110 | [0, 1, 2, 3, 4, 5, 6, 7], 111 | [7, 15, 23, 31, 39, 47, 55, 63], 112 | [63, 62, 61, 60, 59, 58, 57, 56], 113 | [56, 48, 40, 32, 24, 26, 8, 0] 114 | ] 115 | 116 | edge2 = [] 117 | for arr in edge1: 118 | edge2.append(arr) 119 | edge2.append(list(reversed(arr))) 120 | translate.append(edge2) 121 | eval_translate.append(edge1) 122 | each_param_num.append(3 ** 8) 123 | 124 | ''' 125 | diagonal1 = [ 126 | [0, 9, 18, 27, 36, 45, 54, 63], 127 | [7, 14, 21, 28, 35, 42, 49, 56] 128 | ] 129 | diagonal2 = [] 130 | for arr in diagonal1: 131 | diagonal2.append(arr) 132 | diagonal2.append(list(reversed(arr))) 133 | translate.append(diagonal2) 134 | eval_translate.append(diagonal1) 135 | each_param_num.append(3 ** 8) 136 | ''' 137 | 138 | win_num = [[0 for _ in range(each_param_num[i])] for i in range(pattern_num)] 139 | seen_num = [[0 for _ in range(each_param_num[i])] for i in range(pattern_num)] 140 | ans = [[0 for _ in range(each_param_num[i])] for i in range(pattern_num)] 141 | weight = [[1.0 for _ in range(3)] for _ in range(pattern_num)] 142 | ''' 143 | with open('param_pattern.txt', 'r') as f: 144 | for i in range(pattern_num): 145 | for j in range(each_param_num[i]): 146 | ans[i][j] = float(f.readline()) 147 | ''' 148 | seen_grid = [] 149 | 150 | 151 | hw = 8 152 | hw2 = 64 153 | dy = [0, 1, 0, -1, 1, 1, -1, -1] 154 | dx = [1, 0, -1, 0, 1, -1, 1, -1] 155 | 156 | def empty(grid, y, x): 157 | return grid[y][x] == -1 or grid[y][x] == 2 158 | 159 | def inside(y, x): 160 | return 0 <= y < hw and 0 <= x < hw 161 | 162 | def check(grid, player, y, x): 163 | res_grid = [[False for _ in range(hw)] for _ in range(hw)] 164 | res = 0 165 | for dr in range(8): 166 | ny = y + dy[dr] 167 | nx = x + dx[dr] 168 | if not inside(ny, nx): 169 | continue 170 | if empty(grid, ny, nx): 171 | continue 172 | if grid[ny][nx] == player: 173 | continue 174 | #print(y, x, dr, ny, nx) 175 | plus = 0 176 | flag = False 177 | for d in range(hw): 178 | nny = ny + d * dy[dr] 179 | nnx = nx + d * dx[dr] 180 | if not inside(nny, nnx): 181 | break 182 | if empty(grid, nny, nnx): 183 | break 184 | if grid[nny][nnx] == player: 185 | flag = True 186 | break 187 | #print(y, x, dr, nny, nnx) 188 | plus += 1 189 | if flag: 190 | res += plus 191 | for d in range(plus): 192 | nny = ny + d * dy[dr] 193 | nnx = nx + d * dx[dr] 194 | res_grid[nny][nnx] = True 195 | return res, res_grid 196 | 197 | class reversi: 198 | def __init__(self): 199 | self.grid = [[-1 for _ in range(hw)] for _ in range(hw)] 200 | self.grid[3][3] = 1 201 | self.grid[3][4] = 0 202 | self.grid[4][3] = 0 203 | self.grid[4][4] = 1 204 | self.player = 0 # 0: 黒 1: 白 205 | self.nums = [2, 2] 206 | 207 | def move(self, y, x): 208 | plus, plus_grid = check(self.grid, self.player, y, x) 209 | if (not empty(self.grid, y, x)) or (not inside(y, x)) or not plus: 210 | print('Please input a correct move') 211 | return 1 212 | self.grid[y][x] = self.player 213 | for ny in range(hw): 214 | for nx in range(hw): 215 | if plus_grid[ny][nx]: 216 | self.grid[ny][nx] = self.player 217 | self.nums[self.player] += 1 + plus 218 | self.nums[1 - self.player] -= plus 219 | self.player = 1 - self.player 220 | return 0 221 | 222 | def check_pass(self): 223 | for y in range(hw): 224 | for x in range(hw): 225 | if self.grid[y][x] == 2: 226 | self.grid[y][x] = -1 227 | res = True 228 | for y in range(hw): 229 | for x in range(hw): 230 | if not empty(self.grid, y, x): 231 | continue 232 | plus, _ = check(self.grid, self.player, y, x) 233 | if plus: 234 | res = False 235 | self.grid[y][x] = 2 236 | if res: 237 | #print('Pass!') 238 | self.player = 1 - self.player 239 | return res 240 | 241 | def output(self): 242 | print(' ', end='') 243 | for i in range(hw): 244 | print(chr(ord('a') + i), end=' ') 245 | print('') 246 | for y in range(hw): 247 | print(str(y + 1) + ' ', end='') 248 | for x in range(hw): 249 | print('○' if self.grid[y][x] == 0 else '●' if self.grid[y][x] == 1 else '* ' if self.grid[y][x] == 2 else '. ', end='') 250 | print('') 251 | 252 | def output_file(self): 253 | res = '' 254 | for y in range(hw): 255 | for x in range(hw): 256 | res += '*' if self.grid[y][x] == 0 else 'O' if self.grid[y][x] == 1 else '-' 257 | res += ' *' 258 | return res 259 | 260 | def end(self): 261 | if min(self.nums) == 0: 262 | return True 263 | res = True 264 | for y in range(hw): 265 | for x in range(hw): 266 | if self.grid[y][x] == -1 or self.grid[y][x] == 2: 267 | res = False 268 | return res 269 | 270 | def judge(self): 271 | if self.nums[0] > self.nums[1]: 272 | #print('Black won!', self.nums[0], '-', self.nums[1]) 273 | return 0 274 | elif self.nums[1] > self.nums[0]: 275 | #print('White won!', self.nums[0], '-', self.nums[1]) 276 | return 1 277 | else: 278 | #print('Draw!', self.nums[0], '-', self.nums[1]) 279 | return -1 280 | 281 | def translate_p(grid, arr): 282 | res = [] 283 | for i in range(len(arr)): 284 | tmp = 0 285 | for j in reversed(range(len(arr[i]))): 286 | tmp *= 3 287 | tmp2 = grid[arr[i][j] // hw][arr[i][j] % hw] 288 | if tmp2 == 0: 289 | tmp += 1 290 | elif tmp2 == 1: 291 | tmp += 2 292 | res.append(tmp) 293 | return res 294 | 295 | def translate_o(grid, arr): 296 | res = [] 297 | for i in range(len(arr)): 298 | tmp = 0 299 | for j in reversed(range(len(arr[i]))): 300 | tmp *= 3 301 | tmp2 = grid[arr[i][j] // hw][arr[i][j] % hw] 302 | if tmp2 == 1: 303 | tmp += 1 304 | elif tmp2 == 0: 305 | tmp += 2 306 | res.append(tmp) 307 | return res 308 | 309 | def collect(s): 310 | global seen_grid 311 | grids = [] 312 | rv = reversi() 313 | idx = 2 314 | while True: 315 | if rv.check_pass() and rv.check_pass(): 316 | break 317 | turn = 0 if s[idx] == '+' else 1 318 | x = ord(s[idx + 1]) - ord('a') 319 | y = int(s[idx + 2]) - 1 320 | idx += 3 321 | if rv.move(y, x): 322 | print('error') 323 | break 324 | grids.append([[i for i in j] for j in rv.grid]) 325 | if rv.end(): 326 | break 327 | rv.check_pass() 328 | #rv.output() 329 | #print(rv.nums[0], rv.nums[1]) 330 | seen_grid.append([]) 331 | #winner = rv.judge() 332 | score = 2.0 / (1.0 + exp(-(rv.nums[0] - rv.nums[1]) / 5)) - 1.0 333 | for turn, grid in enumerate(grids): 334 | tmp = [score, (turn + 4) / 64] 335 | for i in range(pattern_num): 336 | tmp.append(translate_p(grid, eval_translate[i])) 337 | for j in translate_p(grid, translate[i]): 338 | seen_num[i][j] += 1 339 | win_num[i][j] += tmp[0] 340 | for j in translate_o(grid, translate[i]): 341 | seen_num[i][j] += 1 342 | win_num[i][j] -= tmp[0] 343 | seen_grid[-1].append(tmp) 344 | ''' 345 | 346 | def collect(): 347 | global seen_grid 348 | with open('param0.txt', 'w') as f: 349 | for i in range(param_num): 350 | f.write(str(base_param[i] + random() * 0.4 - 0.2) + '\n') 351 | with open('param1.txt', 'w') as f: 352 | for i in range(param_num): 353 | f.write(str(base_param[i] + random() * 0.4 - 0.2) + '\n') 354 | ai = [subprocess.Popen(('./a.exe param' + str(i) + '.txt').split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE) for i in range(2)] 355 | for i in range(2): 356 | ai[i].stdin.write((str(i) + '\n' + '100' + '\n').encode('utf-8')) 357 | ai[i].stdin.flush() 358 | grids = [] 359 | rv = reversi() 360 | idx = 2 361 | while True: 362 | if rv.check_pass() and rv.check_pass(): 363 | break 364 | stdin = '' 365 | for y in range(hw): 366 | for x in range(hw): 367 | stdin += str(rv.grid[y][x]) + ' ' 368 | stdin += '\n' 369 | ai[rv.player].stdin.write(stdin.encode('utf-8')) 370 | ai[rv.player].stdin.flush() 371 | y, x, val = [float(i) for i in ai[rv.player].stdout.readline().decode().strip().split()] 372 | y = int(y) 373 | x = int(x) 374 | if rv.move(y, x): 375 | print('error') 376 | for i in range(2): 377 | ai[i].kill() 378 | return 379 | grids.append([val / 4 if rv.player == 0 else -val / 4, [[i for i in j] for j in rv.grid]]) 380 | if rv.end(): 381 | break 382 | for i in range(2): 383 | ai[i].kill() 384 | rv.check_pass() 385 | #rv.output() 386 | #print(rv.nums[0], rv.nums[1]) 387 | seen_grid.append([]) 388 | #winner = rv.judge() 389 | score = 2.0 / (1.0 + exp(-(rv.nums[0] - rv.nums[1]) / 5)) - 1.0 390 | for turn in range(len(grids)): 391 | if turn + 25 < len(grids): 392 | val = grids[turn + 25][0] 393 | else: 394 | val = score * turn / len(grids) 395 | grid = grids[turn][1] 396 | tmp = [score * turn / len(grids)] 397 | for i in range(pattern_num): 398 | tmp.append(translate_p(grid, eval_translate[i])) 399 | for j in translate_p(grid, translate[i]): 400 | seen_num[i][j] += 1 401 | win_num[i][j] += val 402 | for j in translate_o(grid, translate[i]): 403 | seen_num[i][j] += 1 404 | win_num[i][j] -= val 405 | seen_grid[-1].append(tmp) 406 | ''' 407 | 408 | def calc_weight(idx, x): 409 | x1 = 4.0 / 64 410 | x2 = 32.0 / 64 411 | x3 = 64.0 / 64 412 | y1, y2, y3 = weight[idx] 413 | a = ((y1 - y2) * (x1 - x3) - (y1 - y3) * (x1 - x2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) 414 | b = (y1 - y2) / (x1 - x2) - a * (x1 + x2) 415 | c = y1 - a * x1 * x1 - b * x1 416 | return a * x * x + b * x + c 417 | 418 | def scoring(): 419 | res = 0.0 420 | cnt = 0 421 | for game in range(len(seen_grid)): 422 | for turn, arr in enumerate(seen_grid[game]): 423 | cnt += 1 424 | result = arr[0] 425 | val = 0.0 426 | for i in range(pattern_num): 427 | tmp = 0.0 428 | for j in arr[i + 2]: 429 | tmp += ans[i][j] 430 | val += tmp * calc_weight(i, arr[1]) 431 | res += (val - result) ** 2 432 | ''' 433 | if val * result < 0.0: 434 | res += abs(val - result) 435 | else: 436 | res += abs(val - result) * 0.5 437 | ''' 438 | ''' 439 | #res *= pow(val, result) * pow(1 - val, 1 - result) # * 0.01 + 0.99 440 | if val != 0.0: 441 | res += result * log(val) 442 | if 1.0 - val != 0.0: 443 | res += (1.0 - result) * log(1.0 - val) 444 | ''' 445 | return res / cnt 446 | 447 | def anneal1(tl): 448 | global ans, start_temp, end_temp 449 | score = scoring() 450 | print('anneal1') 451 | print(score) 452 | strt = time() 453 | cnt = 0 454 | while time() - strt < tl: 455 | idx1 = randint(0, pattern_num - 1) 456 | idx2 = randint(0, 2) 457 | f_weight = weight[idx1][idx2] 458 | weight[idx1][idx2] += random() - 0.5 459 | n_score = scoring() 460 | if n_score < score: 461 | score = n_score 462 | print(score) 463 | cnt += 1 464 | else: 465 | weight[idx1][idx2] = f_weight 466 | if cnt % 10 == 0: 467 | output() 468 | 469 | def anneal2(tl): 470 | global ans, start_temp, end_temp 471 | score = scoring() 472 | min_score = score 473 | print('anneal2') 474 | print(score) 475 | strt = time() 476 | cnt = 0 477 | while time() - strt < tl: 478 | idx1 = randint(0, pattern_num - 1) 479 | idx2 = randint(0, each_param_num[idx1] - 1) 480 | f_val = ans[idx1][idx2] 481 | ans[idx1][idx2] += random() * 0.01 - 0.005 482 | n_score = scoring() 483 | if n_score < score: 484 | score = n_score 485 | print(score) 486 | cnt += 1 487 | else: 488 | ans[idx1][idx2] = f_val 489 | if cnt % 10 == 0: 490 | output() 491 | 492 | 493 | def output(): 494 | with open('param_pattern.txt', 'w') as f: 495 | for i in range(pattern_num): 496 | for j in range(each_param_num[i]): 497 | f.write('{:f}'.format(ans[i][j]) + '\n') 498 | with open('patttern_weight.txt', 'w') as f: 499 | for i in range(pattern_num): 500 | for j in range(3): 501 | f.write('{:f}'.format(weight[i][j]) + '\n') 502 | 503 | ''' 504 | g = [ 505 | [-1, -1, -1, -1, 1, 0, 0, 0], 506 | [-1, -1, -1, 0, 0, 1, 0, 0], 507 | [1, 0, -1, -1, 0, 0, 1, 1], 508 | [0, 1, 0, 1, 1, 1, 1, 1], 509 | [-1, -1, -1, -1, -1, -1, -1, 1], 510 | [0, 1, 1, 0, -1, -1, -1, -1], 511 | [1, 1, 1, 0, 0, 1, 0, -1], 512 | [0, -1, 1, -1, 0, -1, 1, 1] 513 | ] 514 | stdin = '' 515 | for y in range(hw): 516 | for x in range(hw): 517 | stdin += str(g[y][x]) + ' ' 518 | stdin += '\n' 519 | print(0) 520 | print(10) 521 | print(stdin) 522 | print('') 523 | print(translate_p(g, edge1)) 524 | print(translate_p(g, corner1)) 525 | exit() 526 | ''' 527 | 528 | with open('third_party/xxx.gam', 'rb') as f: 529 | raw_data = f.read() 530 | games = [i for i in raw_data.splitlines()] 531 | 532 | 533 | num = 1000 534 | lst = [randint(0, 100000) for i in range(num)] 535 | for i in trange(num): 536 | collect(str(games[lst[i]])) 537 | ''' 538 | for _ in trange(100): 539 | collect() 540 | ''' 541 | for i in range(pattern_num): 542 | for j in range(each_param_num[i]): 543 | ans[i][j] = win_num[i][j] / max(1, seen_num[i][j]) 544 | 545 | output() 546 | #anneal0(10.0) 547 | while True: 548 | anneal1(10.0) 549 | output() 550 | anneal2(10.0) 551 | output() 552 | output() -------------------------------------------------------------------------------- /legacy/AI_Cython/ai_cython.pyx: -------------------------------------------------------------------------------- 1 | # distutils: language=c++ 2 | #cython: language_level=3, boundscheck=False, wraparound=False, initializedcheck=False, cdivision=True 3 | 4 | # Reversi AI Cython version 5 | 6 | from __future__ import print_function 7 | from libcpp.vector cimport vector 8 | from libcpp.algorithm cimport sort as csort 9 | from libcpp.map cimport map as cmap 10 | from libcpp.unordered_map cimport unordered_map as umap 11 | from libcpp.pair cimport pair 12 | import sys 13 | from random import random, shuffle 14 | from time import time 15 | def debug(*args, end='\n'): print(*args, file=sys.stderr, end=end) 16 | 17 | DEF hw = 8 18 | DEF hw2 = hw * hw 19 | DEF window = 0.00001 20 | cdef int[8] dy = [0, 1, 0, -1, 1, 1, -1, -1] 21 | cdef int[8] dx = [1, 0, -1, 0, 1, -1, 1, -1] 22 | 23 | cdef bint inside(int y, int x): 24 | return 0 <= y < hw and 0 <= x < hw 25 | 26 | cdef double[hw2] weight = [ 27 | 3.2323232323232323, 0.23088023088023088, 1.3852813852813852, 1.0389610389610389, 1.0389610389610389, 1.3852813852813852, 0.23088023088023088, 3.2323232323232323, 28 | 0.23088023088023088, 0.0, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.0, 0.23088023088023088, 29 | 1.3852813852813852, 0.9004329004329005, 1.0389610389610389, 0.9466089466089466, 0.9466089466089466, 1.0389610389610389, 0.9004329004329005, 1.3852813852813852, 30 | 1.0389610389610389, 0.9004329004329005, 0.9466089466089466, 0.9235209235209235, 0.9235209235209235, 0.9466089466089466, 0.9004329004329005, 1.0389610389610389, 31 | 1.0389610389610389, 0.9004329004329005, 0.9466089466089466, 0.9235209235209235, 0.9235209235209235, 0.9466089466089466, 0.9004329004329005, 1.0389610389610389, 32 | 1.3852813852813852, 0.9004329004329005, 1.0389610389610389, 0.9466089466089466, 0.9466089466089466, 1.0389610389610389, 0.9004329004329005, 1.3852813852813852, 33 | 0.23088023088023088, 0.0, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.0, 0.23088023088023088, 34 | 3.2323232323232323, 0.23088023088023088, 1.3852813852813852, 1.0389610389610389, 1.0389610389610389, 1.3852813852813852, 0.23088023088023088, 3.2323232323232323 35 | ] 36 | 37 | ''' 38 | weight = [ 39 | 100, -30, 20, 5, 5, 20, -30, 100, 40 | -30, -40, -1, -1, -1, -1, -40, -30, 41 | 20, -1, 5, 1, 1, 5, -1, 20, 42 | 5, -1, 1, 0, 0, 1, -1, 5, 43 | 5, -1, 1, 0, 0, 1, -1, 5, 44 | 20, -1, 5, 1, 1, 5, -1, 20, 45 | -30, -40, -1, -1, -1, -1, -40, -30, 46 | 100, -30, 20, 5, 5, 20, -30, 100 47 | ] 48 | min_weight = min(weight) 49 | weight = [weight[i] - min_weight for i in range(hw2)] 50 | weight_sm = sum(weight) / hw2 51 | print(weight_sm) 52 | weight = [weight[i] / weight_sm for i in range(hw2)] 53 | for i in range(0, hw2, 8): 54 | print(weight[i:i + 8]) 55 | exit() 56 | ''' 57 | cdef int[hw][hw] confirm_lst = [ 58 | [63, 62, 61, 60, 59, 58, 57, 56], 59 | [56, 57, 58, 59, 60, 61, 62, 63], 60 | [63, 55, 47, 39, 31, 23, 15, 7], 61 | [ 7, 15, 23, 31, 39, 47, 55, 63], 62 | [ 7, 6, 5, 4, 3, 2, 1, 0], 63 | [ 0, 1, 2, 3, 4, 5, 6, 7], 64 | [56, 48, 40 , 32, 24, 16, 8, 0], 65 | [ 0, 8, 16, 24, 32, 40, 48, 56] 66 | ] 67 | cdef unsigned long long[4] confirm_num = [ 68 | 0b0000000000000000000000000000000000000000000000000000000011111111, 69 | 0b0000000100000001000000010000000100000001000000010000000100000001, 70 | 0b1111111100000000000000000000000000000000000000000000000000000000, 71 | 0b1000000010000000100000001000000010000000100000001000000010000000 72 | ] 73 | 74 | cdef struct grid_priority: 75 | double priority 76 | unsigned long long me 77 | unsigned long long op 78 | int open_val 79 | 80 | 81 | cdef unsigned long long check_mobility(unsigned long long grid_me, unsigned long long grid_op): 82 | cdef unsigned long long res, t, u, v, w 83 | res = 0 84 | # 左だけ高速に演算できる 85 | t = 0b1111111100000000111111110000000011111111000000001111111100000000 86 | u = grid_op & t 87 | v = (grid_me & t) << 1 88 | w = ~(v | grid_op) 89 | res |= w & (u + v) & t 90 | t = 0b0000000011111111000000001111111100000000111111110000000011111111 91 | u = grid_op & t 92 | v = (grid_me & t) << 1 93 | w = ~(v | grid_op) 94 | res |= w & (u + v) & t 95 | 96 | cdef int i 97 | w = grid_op & 0x7e7e7e7e7e7e7e7e 98 | t = w & (grid_me >> 1) 99 | for i in range(hw - 3): 100 | t |= w & (t >> 1) 101 | res |= (t >> 1) 102 | 103 | w = grid_op & 0x00FFFFFFFFFFFF00 104 | t = w & (grid_me << hw) 105 | for i in range(hw - 3): 106 | t |= w & (t << hw) 107 | res |= (t << hw) 108 | t = w & (grid_me >> hw) 109 | for i in range(hw - 3): 110 | t |= w & (t >> hw) 111 | res |= (t >> hw) 112 | 113 | w = grid_op & 0x007e7e7e7e7e7e00 114 | t = w & (grid_me << (hw - 1)) 115 | for i in range(hw - 3): 116 | t |= w & (t << (hw - 1)) 117 | res |= (t << (hw - 1)) 118 | t = w & (grid_me >> (hw - 1)) 119 | for i in range(hw - 3): 120 | t |= w & (t >> (hw - 1)) 121 | res |= (t >> (hw - 1)) 122 | 123 | t = w & (grid_me << (hw + 1)) 124 | for i in range(hw - 3): 125 | t |= w & (t << (hw + 1)) 126 | res |= (t << (hw + 1)) 127 | t = w & (grid_me >> (hw + 1)) 128 | for i in range(hw - 3): 129 | t |= w & (t >> (hw + 1)) 130 | res |= (t >> (hw + 1)) 131 | return ~(grid_me | grid_op) & res 132 | 133 | cdef int check_confirm(unsigned long long grid, int idx): 134 | cdef int i, res = 0 135 | for i in range(hw): 136 | if 1 & (grid >> confirm_lst[idx][i]): 137 | res += 1 138 | else: 139 | break 140 | return res 141 | 142 | cdef int dfs(int i): 143 | global marked 144 | cdef int res = 1 145 | marked |= 1 << i 146 | if i - 1 >= 0 and not (1 & (marked >> (i - 1))): 147 | res += dfs(i - 1) 148 | if i + 1 < hw2 and not (1 & (marked >> (i + 1))): 149 | res += dfs(i + 1) 150 | if i - hw >= 0 and not (1 & (marked >> (i - hw))): 151 | res += dfs(i - hw) 152 | if i + hw < hw2 and not (1 & (marked >> (i + hw))): 153 | res += dfs(i + hw) 154 | if i - hw - 1 >= 0 and not (1 & (marked >> (i - hw - 1))): 155 | res += dfs(i - hw - 1) 156 | if i + hw + 1 < hw2 and not (1 & (marked >> (i + hw + 1))): 157 | res += dfs(i + hw + 1) 158 | if i - hw + 1 >= 0 and not (1 & (marked >> (i - hw + 1))): 159 | res += dfs(i - hw + 1) 160 | if i + hw - 1 < hw2 and not (1 & (marked >> (i + hw - 1))): 161 | res += dfs(i + hw - 1) 162 | return res 163 | 164 | cdef double evaluate(unsigned long long grid_me, unsigned long long grid_op, int canput, int open_val): 165 | global marked 166 | cdef int canput_all = canput 167 | cdef double weight_me = 0.0, weight_op = 0.0 168 | cdef int me_cnt = 0, op_cnt = 0 169 | cdef int confirm_me = 0, confirm_op = 0 170 | cdef int stone_me = 0, stone_op = 0 171 | cdef unsigned long long mobility, stones 172 | cdef int i, j 173 | for i in range(hw2): 174 | if 1 & (grid_me >> (hw2 - i - 1)): 175 | weight_me += weight[i] 176 | me_cnt += 1 177 | elif 1 & (grid_op >> (hw2 - i - 1)): 178 | weight_op += weight[i] 179 | op_cnt += 1 180 | mobility = check_mobility(grid_me, grid_op) 181 | for i in range(hw2): 182 | canput_all += 1 & (mobility >> i) 183 | stones = grid_me | grid_op 184 | ''' 185 | if vacant_cnt - max_depth < 5: 186 | marked = stones 187 | for i in range(hw2): 188 | if 1 & (marked >> i): 189 | continue 190 | if dfs(i) & 1: 191 | odd_vacant += 1 192 | ''' 193 | for i in range(0, hw, 2): 194 | if stones ^ confirm_num[i // 2]: 195 | for j in range(2): 196 | confirm_me += max(0, check_confirm(grid_me, i + j) - 1) 197 | confirm_op += max(0, check_confirm(grid_op, i + j) - 1) 198 | else: 199 | for j in range(1, hw - 1): 200 | if 1 & (grid_me >> confirm_lst[i][j]): 201 | confirm_me += 1 202 | elif 1 & (grid_op >> confirm_lst[i][j]): 203 | confirm_op += 1 204 | confirm_me += 1 & grid_me 205 | confirm_me += 1 & (grid_me >> (hw - 1)) 206 | confirm_me += 1 & (grid_me >> (hw2 - hw)) 207 | confirm_me += 1 & (grid_me >> (hw2 - 1)) 208 | confirm_op += 1 & grid_op 209 | confirm_op += 1 & (grid_op >> (hw - 1)) 210 | confirm_op += 1 & (grid_op >> (hw2 - hw)) 211 | confirm_op += 1 & (grid_op >> (hw2 - 1)) 212 | for i in range(hw2): 213 | stone_me += 1 & (grid_me >> i) 214 | stone_op += 1 & (grid_op >> i) 215 | cdef double weight_proc, canput_proc, confirm_proc, stone_proc, open_proc 216 | weight_proc = weight_me / me_cnt - weight_op / op_cnt 217 | canput_proc = (canput_all - canput) / max(1, canput_all) - canput / max(1, canput_all) 218 | confirm_proc = confirm_me / max(1, confirm_me + confirm_op) - confirm_op / max(1, confirm_me + confirm_op) 219 | stone_proc = -stone_me / (stone_me + stone_op) + stone_op / (stone_me + stone_op) 220 | open_proc = max(-1.0, (5 - open_val) / 5) 221 | return weight_proc * weight_weight + canput_proc * canput_weight + confirm_proc * confirm_weight + stone_proc * stone_weight + open_proc * open_weight 222 | 223 | cdef double end_game(unsigned long long grid_me, unsigned long long grid_op): 224 | cdef int res = 0, i 225 | for i in range(hw2): 226 | res += 1 & (grid_me >> i) 227 | res -= 1 & (grid_op >> i) 228 | return res 229 | 230 | def output(grid_me, grid_op, func): 231 | grid = [[-1 for _ in range(hw)] for _ in range(hw)] 232 | for y in range(hw): 233 | for x in range(hw): 234 | i = y * hw + x 235 | if 1 & (grid_me >> (hw2 - i - 1)): 236 | grid[y][x] = ai_player 237 | elif 1 & (grid_op >> (hw2 - i - 1)): 238 | grid[y][x] = 1 - ai_player 239 | func(' ', end='') 240 | for i in range(hw): 241 | func(i, end=' ') 242 | func('') 243 | for y in range(hw): 244 | func(str(y) + '0', end='') 245 | for x in range(hw): 246 | func('○' if grid[y][x] == 0 else '●' if grid[y][x] == 1 else '* ' if grid[y][x] == 2 else '. ', end='') 247 | func('') 248 | 249 | cdef unsigned long long transfer(unsigned long long put, int k): 250 | if k == 0: 251 | return (put << 8) & 0xffffffffffffff00 252 | elif k == 1: 253 | return (put << 7) & 0x7f7f7f7f7f7f7f00 254 | elif k == 2: 255 | return (put >> 1) & 0x7f7f7f7f7f7f7f7f 256 | elif k == 3: 257 | return (put >> 9) & 0x007f7f7f7f7f7f7f 258 | elif k == 4: 259 | return (put >> 8) & 0x00ffffffffffffff 260 | elif k == 5: 261 | return (put >> 7) & 0x00fefefefefefefe 262 | elif k == 6: 263 | return (put << 1) & 0xfefefefefefefefe 264 | elif k == 7: 265 | return (put << 9) & 0xfefefefefefefe00 266 | return 0 267 | 268 | cdef unsigned long long move(unsigned long long grid_me, unsigned long long grid_op, int place): 269 | cdef unsigned long long put, rev1, rev2, mask 270 | cdef int i 271 | put = 1 << place 272 | rev1 = 0 273 | for i in range(hw): 274 | rev2 = 0 275 | mask = transfer(put, i) 276 | while mask != 0 and (mask & grid_op) != 0: 277 | rev2 |= mask 278 | mask = transfer(mask, i) 279 | if (mask & grid_me) != 0: 280 | rev1 |= rev2 281 | return grid_me ^ (put | rev1) 282 | 283 | cdef int calc_open(unsigned long long stones, unsigned long long rev): 284 | cdef int i, res = 0 285 | for i in range(hw2): 286 | if 1 & (rev >> i): 287 | res += 1 - (1 & (stones >> (i + 1))) 288 | res += 1 - (1 & (stones >> (i - 1))) 289 | res += 1 - (1 & (stones >> (i + hw))) 290 | res += 1 - (1 & (stones >> (i - hw))) 291 | res += 1 - (1 & (stones >> (i + hw + 1))) 292 | res += 1 - (1 & (stones >> (i - hw + 1))) 293 | res += 1 - (1 & (stones >> (i + hw - 1))) 294 | res += 1 - (1 & (stones >> (i - hw - 1))) 295 | return res 296 | 297 | cdef int cmp(grid_priority p, grid_priority q): 298 | return (p.priority > q.priority) 299 | 300 | cdef double nega_scout(unsigned long long grid_me, unsigned long long grid_op, int depth, double alpha, double beta, int skip_cnt, int canput, int open_val): 301 | global memo, memo_turn 302 | if max_depth > min_max_depth and time() - strt > tl: 303 | return -100000000.0 304 | #if memo_turn[grid_me] != 0.0: 305 | # return memo_turn[grid_me] 306 | cdef int y, x, i 307 | cdef double val 308 | if skip_cnt == 2: 309 | return end_game(grid_me, grid_op) 310 | elif depth == 0: 311 | return evaluate(grid_me, grid_op, canput, open_val) 312 | cdef int n_canput = 0 313 | cdef unsigned long long mobility = check_mobility(grid_me, grid_op) 314 | cdef unsigned long long n_grid_me, n_grid_op 315 | cdef double priority 316 | cdef vector[grid_priority] lst 317 | cdef pair[unsigned long long, unsigned long long] grid_all, n_grid_all 318 | grid_all.first = grid_me 319 | grid_all.second = grid_op 320 | for i in range(hw2): 321 | if 1 & (mobility >> i): 322 | n_canput += 1 323 | n_grid_me = move(grid_me, grid_op, i) 324 | n_grid_op = (n_grid_me ^ grid_op) & grid_op 325 | n_grid_all.first = n_grid_op 326 | n_grid_all.second = n_grid_me 327 | priority = memo[n_grid_all] 328 | ''' 329 | if vacant_cnt - max_depth + depth < 20: 330 | marked = grid_me | grid_op 331 | if dfs(i) & 1: 332 | priority += 0.5 333 | ''' 334 | open_val = calc_open(n_grid_me | n_grid_op, n_grid_me ^ grid_me) 335 | priority -= open_val * 0.1 336 | lst.push_back(grid_priority(priority, n_grid_me, n_grid_op, open_val)) 337 | if n_canput == 0: 338 | val = -nega_scout(grid_op, grid_me, depth, -beta, -alpha, skip_cnt + 1, 0, 0) 339 | if abs(val) == 100000000.0: 340 | return -100000000.0 341 | return max(alpha, val) 342 | csort(lst.begin(), lst.end(), cmp) 343 | open_val = 0 344 | if depth == 1: 345 | open_val = lst[0].open_val 346 | val = -nega_scout(lst[0].op, lst[0].me, depth - 1, -beta, -alpha, 0, n_canput, open_val) 347 | if abs(val) == 100000000.0: 348 | return -100000000.0 349 | memo[grid_all] = val 350 | #memo_turn[lst[0].op] = -val 351 | alpha = max(alpha, val) 352 | if alpha >= beta: 353 | return alpha 354 | for i in range(1, n_canput): 355 | if depth == 1: 356 | open_val = lst[i].open_val 357 | val = -nega_scout(lst[i].op, lst[i].me, depth - 1, -alpha - window, -alpha, 0, n_canput, open_val) 358 | if abs(val) == 100000000.0: 359 | return -100000000.0 360 | if beta <= val: 361 | return val 362 | if alpha < val: 363 | alpha = val 364 | val = -nega_scout(lst[i].op, lst[i].me, depth - 1, -beta, -alpha, 0, n_canput, open_val) 365 | if abs(val) == 100000000.0: 366 | return -100000000.0 367 | memo[grid_all] = val 368 | #memo_turn[lst[i].op] = -val 369 | alpha = max(alpha, val) 370 | if alpha >= beta: 371 | return alpha 372 | return alpha 373 | 374 | cdef double map_double(double s, double e, double x): 375 | return s + (e - s) * x 376 | 377 | cdef int ai_player 378 | cdef double weight_weight, canput_weight, confirm_weight, stone_weight, open_weight 379 | cdef int max_depth, vacant_cnt 380 | cdef double strt, ratio 381 | cdef cmap[pair[unsigned long long, unsigned long long], double] memo 382 | cdef unsigned long long marked 383 | cdef int min_max_depth 384 | cdef double tl 385 | 386 | cdef void main(): 387 | global ai_player, weight_weight, canput_weight, confirm_weight, stone_weight, open_weight, max_depth, min_max_depth, strt, ratio, vacant_cnt, memo, tl 388 | cdef int y, x, ansy, ansx, outy, outx, i, canput, former_depth = 9, former_vacant = hw2 - 4 389 | cdef double score, max_score 390 | cdef double weight_weight_s, canput_weight_s, confirm_weight_s, stone_weight_s, open_weight_s, weight_weight_e, canput_weight_e, confirm_weight_e, stone_weight_e, open_weight_e 391 | cdef unsigned long long in_grid_me, in_grid_op, in_mobility, grid_me, grid_op 392 | cdef list in_grid 393 | cdef str elem 394 | cdef vector[grid_priority] lst 395 | cdef pair[unsigned long long, unsigned long long] grid_all 396 | ai_player = int(input()) 397 | tl = float(input()) 398 | weight_weight_s = float(input()) 399 | canput_weight_s = float(input()) 400 | confirm_weight_s = float(input()) 401 | stone_weight_s = float(input()) 402 | open_weight_s = float(input()) 403 | weight_weight_e = float(input()) 404 | canput_weight_e = float(input()) 405 | confirm_weight_e = float(input()) 406 | stone_weight_e = float(input()) 407 | open_weight_e = float(input()) 408 | debug('AI initialized AI is', 'Black' if ai_player == 0 else 'White') 409 | while True: 410 | outy = -1 411 | outx = -1 412 | vacant_cnt = 0 413 | in_grid = [] 414 | in_grid = [[int(elem) for elem in input().split()] for _ in range(hw)] 415 | in_grid_me = 0 416 | in_grid_op = 0 417 | in_mobility = 0 418 | canput = 0 419 | for y in range(hw): 420 | for x in range(hw): 421 | vacant_cnt += (in_grid[y][x] == -1 or in_grid[y][x] == 2) 422 | in_mobility <<= 1 423 | in_mobility += (in_grid[y][x] == 2) 424 | canput += (in_grid[y][x] == 2) 425 | in_grid_me <<= 1 426 | in_grid_op <<= 1 427 | in_grid_me += (in_grid[y][x] == ai_player) 428 | in_grid_op += (in_grid[y][x] == ai_player ^ 1) 429 | if vacant_cnt > 15: 430 | min_max_depth = former_depth + vacant_cnt - former_vacant 431 | else: 432 | min_max_depth = 15 433 | debug('start depth', min_max_depth) 434 | max_depth = min_max_depth 435 | former_vacant = vacant_cnt 436 | lst = [] 437 | for i in range(hw2): 438 | if (1 & (in_mobility >> i)): 439 | grid_me = move(in_grid_me, in_grid_op, i) 440 | grid_op = (grid_me ^ in_grid_op) & in_grid_op 441 | grid_all.first = grid_me 442 | grid_all.second = grid_op 443 | lst.push_back(grid_priority(memo[grid_all], grid_me, grid_op, i)) 444 | memo.clear() 445 | strt = time() 446 | while time() - strt < tl / 2: 447 | csort(lst.begin(), lst.end(), cmp) 448 | ratio = (hw2 - vacant_cnt + max_depth) / hw2 449 | weight_weight = map_double(weight_weight_s, weight_weight_e, ratio) 450 | canput_weight = map_double(canput_weight_s, canput_weight_e, ratio) 451 | confirm_weight = map_double(confirm_weight_s, confirm_weight_e, ratio) 452 | stone_weight = map_double(stone_weight_s, stone_weight_e, ratio) 453 | open_weight = map_double(open_weight_s, open_weight_e, ratio) 454 | max_score = -65.0 455 | for i in range(canput): 456 | grid_me = lst[i].me 457 | grid_op = lst[i].op 458 | score = -nega_scout(grid_op, grid_me, max_depth - 1, -65.0, -max_score, 0, canput, 0) 459 | if abs(score) == 100000000.0: 460 | max_score = -100000000.0 461 | break 462 | lst[i].priority = score 463 | if score > max_score: 464 | max_score = score 465 | ansy = (hw2 - lst[i].open_val - 1) // hw 466 | ansx = (hw2 - lst[i].open_val - 1) % hw 467 | if max_score == -100000000.0: 468 | debug('depth', max_depth, 'timeout') 469 | break 470 | former_depth = max_depth 471 | outy = ansy 472 | outx = ansx 473 | debug('depth', max_depth, 'next', outy, outx, 'score', max_score, time() - strt) 474 | if vacant_cnt < max_depth: 475 | debug('game end') 476 | break 477 | if abs(max_score) >= 1.0: 478 | debug('game end') 479 | break 480 | max_depth += 1 481 | debug(outy, outx) 482 | print(outy, outx) 483 | sys.stdout.flush() 484 | 485 | main() -------------------------------------------------------------------------------- /legacy/AI_Cpp/20210618/ai_fast.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx") 2 | 3 | // Reversi AI C++ version 3 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | //#include 19 | 20 | using namespace std; 21 | 22 | #define hw 8 23 | #define hw_m1 7 24 | #define hw_p1 9 25 | #define hw2 64 26 | #define hw2_m1 63 27 | #define hw2_mhw 56 28 | #define window 0.00001 29 | #define simple_threshold 3 30 | #define inf 100000000.0 31 | #define param_num 12 32 | #define board_index_num 38 33 | #define pattern_num 20 34 | 35 | struct HashPair{ 36 | static size_t m_hash_pair_random; 37 | template 38 | size_t operator()(const pair &p) const { 39 | auto hash1 = hash{}(p.first); 40 | auto hash2 = hash{}(p.second); 41 | size_t seed = 0; 42 | seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2); 43 | seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); 44 | seed ^= m_hash_pair_random + 0x9e3779b9 + (seed << 6) + (seed >> 2); 45 | return seed; 46 | } 47 | }; 48 | 49 | size_t HashPair::m_hash_pair_random = (size_t) random_device()(); 50 | 51 | struct board_param{ 52 | unsigned long long trans[board_index_num][6561][hw]; 53 | bool legal[6561][hw]; 54 | int put[hw2][board_index_num]; 55 | int board_translate[board_index_num][8]; 56 | int board_rev_translate[hw2][4]; 57 | int pattern_space[board_index_num]; 58 | int reverse[6561]; 59 | int pow3[10]; 60 | }; 61 | 62 | struct eval_param{ 63 | double weight_s[hw2], weight_m[hw2], weight_e[hw2]; 64 | double weight[hw2]; 65 | double pattern_weight, cnt_weight, canput_weight; 66 | double cnt_bias; 67 | double weight_sme[param_num]; 68 | double avg_canput[hw2]; 69 | /*= { 70 | 0.00, 0.00, 0.00, 0.00, 4.00, 3.00, 4.00, 2.00, 71 | 9.00, 5.00, 6.00, 6.00, 5.00, 8.38, 5.69, 9.13, 72 | 5.45, 6.98, 6.66, 9.38, 6.98, 9.29, 7.29, 9.32, 73 | 7.37, 9.94, 7.14, 9.78, 7.31, 10.95, 7.18, 9.78, 74 | 7.76, 9.21, 7.33, 8.81, 7.20, 8.48, 7.23, 8.00, 75 | 6.92, 7.57, 6.62, 7.13, 6.38, 6.54, 5.96, 6.18, 76 | 5.62, 5.64, 5.18, 5.18, 4.60, 4.48, 4.06, 3.67, 77 | 3.39, 3.11, 2.66, 2.30, 1.98, 1.53, 1.78, 0.67 78 | }; 79 | */ 80 | double pattern_space[pattern_num]; 81 | double pattern_data[pattern_num][6561]; 82 | int pattern_same[board_index_num]; 83 | int canput[6561]; 84 | int cnt_p[6561], cnt_o[6561]; 85 | }; 86 | 87 | typedef union { 88 | unsigned long long ull[4]; 89 | #ifdef __AVX2__ 90 | __m256i v4; 91 | #endif 92 | __m128i v2[2]; 93 | } V4DI; 94 | 95 | struct move_param{ 96 | V4DI lmask_v4[hw2]; 97 | V4DI rmask_v4[hw2]; 98 | }; 99 | 100 | struct search_param{ 101 | unordered_map, double, HashPair> memo1, memo2; 102 | unordered_map, double, HashPair> memo_lb, memo_ub; 103 | int max_depth; 104 | int min_max_depth; 105 | int strt, tl; 106 | int turn; 107 | }; 108 | 109 | struct board_priority_move{ 110 | int b[board_index_num]; 111 | double priority; 112 | int move; 113 | }; 114 | 115 | struct board_priority{ 116 | int b[board_index_num]; 117 | double priority; 118 | }; 119 | 120 | board_param board_param; 121 | eval_param eval_param; 122 | move_param move_param; 123 | search_param search_param; 124 | 125 | inline int pop_count_ull(unsigned long long x){ 126 | x = x - ((x >> 1) & 0x5555555555555555); 127 | x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); 128 | x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F; 129 | x = (x * 0x0101010101010101) >> 56; 130 | return (int)x; 131 | } 132 | 133 | int tim(){ 134 | return static_cast(chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count()); 135 | } 136 | 137 | void print_board(int* board){ 138 | int i, j, idx, tmp; 139 | for (i = 0; i < hw; i++){ 140 | tmp = board[i]; 141 | for (j = 0; j < hw; j++){ 142 | if (tmp % 3 == 0){ 143 | //cerr << ". "; 144 | }else if (tmp % 3 == 1){ 145 | //cerr << "P "; 146 | }else{ 147 | //cerr << "O "; 148 | } 149 | tmp /= 3; 150 | } 151 | //cerr << endl; 152 | } 153 | //cerr << endl; 154 | } 155 | 156 | int reverse_line(int a) { 157 | int res = 0; 158 | for (int i = 0; i < hw; i++) { 159 | res <<= 1; 160 | res |= 1 & (a >> i); 161 | } 162 | return res; 163 | } 164 | 165 | inline unsigned long long check_mobility(const int p, const int o){ 166 | int p1 = p << 1; 167 | int res = ~(p1 | o) & (p1 + o); 168 | int p_rev = reverse_line(p), o_rev = reverse_line(o); 169 | int p2 = p_rev << 1; 170 | res |= reverse_line(~(p2 | o_rev) & (p2 + o_rev)); 171 | res &= ~(p | o); 172 | // //cerr << bitset<8>(p) << " " << bitset<8>(o) << " " << bitset<8>(res) << endl; 173 | return res; 174 | } 175 | 176 | int trans(int pt, int k) { 177 | if (k == 0) 178 | return pt >> 1; 179 | else 180 | return pt << 1; 181 | } 182 | 183 | int move_line(int p, int o, const int place) { 184 | int rev = 0; 185 | int rev2, mask, tmp; 186 | int pt = 1 << place; 187 | for (int k = 0; k < 2; k++) { 188 | rev2 = 0; 189 | mask = trans(pt, k); 190 | while (mask && (mask & o)) { 191 | rev2 |= mask; 192 | tmp = mask; 193 | mask = trans(tmp, k); 194 | if (mask & p) 195 | rev |= rev2; 196 | } 197 | } 198 | // //cerr << bitset<8>(p) << " " << bitset<8>(o) << " " << bitset<8>(rev | pt) << endl; 199 | return rev | pt; 200 | } 201 | 202 | int create_p(int idx){ 203 | int res = 0; 204 | for (int i = 0; i < hw; ++i){ 205 | if (idx % 3 == 1){ 206 | res |= 1 << i; 207 | } 208 | idx /= 3; 209 | } 210 | return res; 211 | } 212 | 213 | int create_o(int idx){ 214 | int res = 0; 215 | for (int i = 0; i < hw; ++i){ 216 | if (idx % 3 == 2){ 217 | res |= 1 << i; 218 | } 219 | idx /= 3; 220 | } 221 | return res; 222 | } 223 | 224 | int board_reverse(int idx){ 225 | int p = create_p(idx); 226 | int o = create_o(idx); 227 | int res = 0; 228 | for (int i = hw_m1; i >= 0; --i){ 229 | res *= 3; 230 | if (1 & (p >> i)) 231 | res += 2; 232 | else if (1 & (o >> i)) 233 | ++res; 234 | } 235 | return res; 236 | } 237 | 238 | void init(int argc, char* argv[]){ 239 | FILE *fp; 240 | const char* file; 241 | if (argc > 1) 242 | file = argv[1]; 243 | else 244 | file = "param.txt"; 245 | if ((fp = fopen(file, "r")) == NULL){ 246 | printf("param.txt not exist"); 247 | exit(1); 248 | } 249 | char cbuf[1024]; 250 | int translate[hw2] = { 251 | 0, 1, 2, 3, 3, 2, 1, 0, 252 | 1, 4, 5, 6, 6, 5, 4, 1, 253 | 2, 5, 7, 8, 8, 7, 5, 2, 254 | 3, 6, 8, 9, 9, 8, 6, 3, 255 | 3, 6, 8, 9, 9, 8, 6, 3, 256 | 2, 5, 7, 8, 8, 7, 5, 2, 257 | 1, 4, 5, 6, 6, 5, 4, 1, 258 | 0, 1, 2, 3, 3, 2, 1, 0 259 | }; 260 | double weight_buf[10]; 261 | int i, j, k, l; 262 | for (i = 0; i < 10; i++){ 263 | if (!fgets(cbuf, 1024, fp)){ 264 | printf("param file broken"); 265 | exit(1); 266 | } 267 | weight_buf[i] = atof(cbuf); 268 | } 269 | for (i = 0; i < hw2; i++) 270 | eval_param.weight_s[i] = weight_buf[translate[i]]; 271 | for (i = 0; i < 10; i++){ 272 | if (!fgets(cbuf, 1024, fp)){ 273 | printf("param file broken"); 274 | exit(1); 275 | } 276 | weight_buf[i] = atof(cbuf); 277 | } 278 | for (i = 0; i < hw2; i++) 279 | eval_param.weight_m[i] = weight_buf[translate[i]]; 280 | for (i = 0; i < 10; i++){ 281 | if (!fgets(cbuf, 1024, fp)){ 282 | printf("param file broken"); 283 | exit(1); 284 | } 285 | weight_buf[i] = atof(cbuf); 286 | } 287 | for (i = 0; i < hw2; i++) 288 | eval_param.weight_e[i] = weight_buf[translate[i]]; 289 | for (i = 0; i < param_num; i++){ 290 | if (!fgets(cbuf, 1024, fp)){ 291 | printf("param file broken"); 292 | exit(1); 293 | } 294 | eval_param.weight_sme[i] = atof(cbuf); 295 | } 296 | fclose(fp); 297 | if ((fp = fopen("const.txt", "r")) == NULL){ 298 | printf("const.txt not exist"); 299 | exit(1); 300 | } 301 | for (i = 0; i < hw2; i++){ 302 | for (j = 0; j < 4; j++){ 303 | if (!fgets(cbuf, 1024, fp)){ 304 | printf("const.txt broken"); 305 | exit(1); 306 | } 307 | move_param.lmask_v4[i].ull[j] = stoull(cbuf); 308 | } 309 | } 310 | for (i = 0; i < hw2; i++){ 311 | for (j = 0; j < 4; j++){ 312 | if (!fgets(cbuf, 1024, fp)){ 313 | printf("const.txt broken"); 314 | exit(1); 315 | } 316 | move_param.rmask_v4[i].ull[j] = stoull(cbuf); 317 | } 318 | } 319 | for (i = 0; i < hw2; i++){ 320 | if (!fgets(cbuf, 1024, fp)){ 321 | printf("const.txt broken"); 322 | exit(1); 323 | } 324 | eval_param.avg_canput[i] = atof(cbuf); 325 | } 326 | for (i = 0; i < board_index_num; i++){ 327 | if (!fgets(cbuf, 1024, fp)){ 328 | printf("const.txt broken"); 329 | exit(1); 330 | } 331 | board_param.pattern_space[i] = atoi(cbuf); 332 | } 333 | for (i = 0; i < board_index_num; i++){ 334 | for (j = 0; j < board_param.pattern_space[i]; j++){ 335 | if (!fgets(cbuf, 1024, fp)){ 336 | printf("const.txt broken"); 337 | exit(1); 338 | } 339 | board_param.board_translate[i][j] = atoi(cbuf); 340 | } 341 | } 342 | for (i = 0; i < board_index_num; i++){ 343 | if (!fgets(cbuf, 1024, fp)){ 344 | printf("const.txt broken"); 345 | exit(1); 346 | } 347 | eval_param.pattern_same[i] = atoi(cbuf); 348 | } 349 | fclose(fp); 350 | int idx; 351 | for (i = 0; i < hw2; i++){ 352 | idx = 0; 353 | for (j = 0; j < board_index_num; j++){ 354 | for (k = 0; k < board_param.pattern_space[j]; k++){ 355 | if (board_param.board_translate[j][k] == i) 356 | board_param.board_rev_translate[i][idx++] = j; 357 | } 358 | } 359 | } 360 | for (i = 0; i < hw2; i++){ 361 | for (j = 0; j < board_index_num; j++){ 362 | board_param.put[i][j] = -1; 363 | for (k = 0; k < board_param.pattern_space[j]; k++){ 364 | if (board_param.board_translate[j][k] == i) 365 | board_param.put[i][j] = k; 366 | } 367 | } 368 | } 369 | for (i = 0; i < board_index_num; i++) 370 | eval_param.pattern_space[eval_param.pattern_same[i]] = board_param.pattern_space[i]; 371 | if ((fp = fopen("param_pattern.txt", "r")) == NULL){ 372 | printf("param_pattern.txt not exist"); 373 | exit(1); 374 | } 375 | for (i = 0; i < pattern_num; ++i){ 376 | for (j = 0; j < (int)pow(3, eval_param.pattern_space[i]); ++j){ 377 | if (!fgets(cbuf, 1024, fp)){ 378 | printf("param_pattern.txt broken"); 379 | exit(1); 380 | } 381 | eval_param.pattern_data[i][j] = atof(cbuf); 382 | } 383 | } 384 | fclose(fp); 385 | int p, o, mobility, canput_num, rev; 386 | for (i = 0; i < 6561; ++i){ 387 | board_param.reverse[i] = board_reverse(i); 388 | p = reverse_line(create_p(i)); 389 | o = reverse_line(create_o(i)); 390 | eval_param.cnt_p[i] = 0; 391 | eval_param.cnt_o[i] = 0; 392 | for (j = 0; j < hw; ++j){ 393 | eval_param.cnt_p[i] += 1 & (p >> j); 394 | eval_param.cnt_o[i] += 1 & (o >> j); 395 | } 396 | mobility = check_mobility(p, o); 397 | canput_num = 0; 398 | for (j = 0; j < hw; ++j){ 399 | if (1 & (mobility >> (hw_m1 - j))){ 400 | rev = move_line(p, o, hw_m1 - j); 401 | canput_num += 1; 402 | board_param.legal[i][j] = true; 403 | for (k = 0; k < board_index_num; ++k){ 404 | board_param.trans[k][i][j] = 0; 405 | for (l = 0; l < board_param.pattern_space[k]; ++l) 406 | board_param.trans[k][i][j] |= (unsigned long long)(1 & (rev >> (7 - l))) << board_param.board_translate[k][l]; 407 | } 408 | } else 409 | board_param.legal[i][j] = false; 410 | } 411 | eval_param.canput[i] = canput_num; 412 | } 413 | for (i = 0; i < 10; ++i) 414 | board_param.pow3[i] = (int)pow(3, i); 415 | } 416 | 417 | inline double pattern_eval(const int *board){ 418 | int i; 419 | double res = 0.0, tmp_res; 420 | for (i = 0; i < board_index_num; ++i) 421 | res += eval_param.pattern_data[eval_param.pattern_same[i]][board[i]]; 422 | return res; 423 | } 424 | 425 | inline double canput_eval(const int *board){ 426 | int i; 427 | int res = 0.0; 428 | for (i = 0; i < pattern_num; ++i) 429 | res += eval_param.canput[board[i]]; 430 | return ((double)res - eval_param.avg_canput[search_param.turn]) / ((double)res + eval_param.avg_canput[search_param.turn]); 431 | } 432 | 433 | inline double cnt_eval(const int *board){ 434 | int i; 435 | int res_p = 0.0, res_o = 0.0; 436 | for (i = 0; i < pattern_num; ++i){ 437 | res_p += eval_param.cnt_p[board[i]]; 438 | res_o += eval_param.cnt_o[board[i]]; 439 | } 440 | return (double)(res_p * eval_param.cnt_bias - res_o) / (res_p * eval_param.cnt_bias + res_o); 441 | } 442 | 443 | inline double evaluate(const int *board){ 444 | double pattern = pattern_eval(board); 445 | double cnt = cnt_eval(board); 446 | double canput = canput_eval(board); 447 | return 448 | pattern * eval_param.pattern_weight + 449 | cnt * eval_param.cnt_weight + 450 | canput * eval_param.canput_weight; 451 | } 452 | 453 | inline double end_game(const int *board){ 454 | int res = 0, i, j, p, o; 455 | for (i = 0; i < hw; ++i){ 456 | res += eval_param.cnt_p[board[i]]; 457 | res -= eval_param.cnt_o[board[i]]; 458 | } 459 | return (double)res * 1000.0; 460 | } 461 | 462 | void move(int *board, int (&res)[board_index_num], int coord){ 463 | int i, j, tmp; 464 | unsigned long long rev = 0; 465 | for (i = 0; i < board_index_num; ++i){ 466 | res[i] = board_param.reverse[board[i]]; 467 | if (board_param.put[coord][i] != -1) 468 | rev |= board_param.trans[i][board[i]][board_param.put[coord][i]]; 469 | } 470 | for (i = 0; i < board_index_num; ++i){ 471 | for (j = 0; j < board_param.pattern_space[i]; ++j){ 472 | if (1 & (rev >> board_param.board_translate[i][j])) 473 | res[i] += board_param.pow3[j] * (2 - (res[i] / board_param.pow3[j]) % 3); 474 | } 475 | } 476 | } 477 | 478 | int cmp(board_priority p, board_priority q){ 479 | return p.priority > q.priority; 480 | } 481 | 482 | double nega_alpha(int *board, const int& depth, double alpha, double beta, const int& skip_cnt){ 483 | if (skip_cnt == 2) 484 | return end_game(board); 485 | else if (depth == 0){ 486 | return evaluate(board); 487 | } 488 | bool is_pass = true; 489 | int i, j, k, put; 490 | double val = -inf, v; 491 | int n_board[board_index_num]; 492 | for (j = 0; j < hw2; ++j){ 493 | for (i = 0; i < board_index_num; ++i){ 494 | if (board_param.put[j][i] != -1){ 495 | if (board_param.legal[board[i]][board_param.put[j][i]]){ 496 | is_pass = false; 497 | put = i * hw + j; 498 | move(board, n_board, j); 499 | v = -nega_alpha(n_board, depth - 1, -beta, -alpha, 0); 500 | if (fabs(v) == inf) 501 | return -inf; 502 | if (beta <= v) 503 | return v; 504 | alpha = max(alpha, v); 505 | if (val < v) 506 | val = v; 507 | break; 508 | } 509 | } 510 | } 511 | } 512 | if (is_pass){ 513 | for (i = 0; i < board_index_num; ++i) 514 | n_board[i] = board_param.reverse[board[i]]; 515 | return -nega_alpha(n_board, depth - 1, -beta, -alpha, skip_cnt + 1); 516 | } 517 | return val; 518 | } 519 | 520 | double nega_scout(int *board, const int& depth, double alpha, double beta, const int& skip_cnt){ 521 | if (search_param.max_depth > search_param.min_max_depth && tim() - search_param.strt > search_param.tl) 522 | return -inf; 523 | if (skip_cnt == 2) 524 | return end_game(board); 525 | /* 526 | double ub, lb; 527 | lb = search_param.memo_lb[board]; 528 | if (lb != 0.0){ 529 | if (lb >= beta) 530 | return lb; 531 | alpha = max(alpha, lb); 532 | } 533 | ub = search_param.memo_ub[board]; 534 | if (ub != 0.0){ 535 | if (alpha >= ub || ub == lb) 536 | return ub; 537 | beta = min(beta, ub); 538 | } 539 | if (alpha >= beta) 540 | return alpha; 541 | */ 542 | int i, j, k, canput = 0; 543 | double val = -inf, v; 544 | vector lst; 545 | for (j = 0; j < hw2; ++j){ 546 | for (i = 0; i < board_index_num; ++i){ 547 | if (board_param.put[j][i] != -1){ 548 | if (board_param.legal[board[i]][board_param.put[j][i]]){ 549 | ++canput; 550 | int n_board[board_index_num]; 551 | board_priority tmp; 552 | move(board, tmp.b, j); 553 | tmp.priority = evaluate(tmp.b); 554 | lst.push_back(tmp); 555 | break; 556 | } 557 | } 558 | } 559 | } 560 | if (canput == 0){ 561 | int n_board[board_index_num]; 562 | for (i = 0; i < board_index_num; ++i) 563 | n_board[i] = board_param.reverse[board[i]]; 564 | return -nega_scout(n_board, depth - 1, -beta, -alpha, skip_cnt + 1); 565 | } 566 | if (canput > 1) 567 | sort(lst.begin(), lst.end(), cmp); 568 | if (depth > simple_threshold) 569 | v = -nega_scout(lst[0].b, depth - 1, -beta, -alpha, 0); 570 | else 571 | v = -nega_alpha(lst[0].b, depth - 1, -beta, -alpha, 0); 572 | val = v; 573 | if (fabs(v) == inf) 574 | return -inf; 575 | if (beta <= v) 576 | return v; 577 | alpha = max(alpha, v); 578 | for (i = 1; i < canput; ++i){ 579 | if (depth > simple_threshold) 580 | v = -nega_scout(lst[i].b, depth - 1, -alpha - window, -alpha, 0); 581 | else 582 | v = -nega_alpha(lst[i].b, depth - 1, -alpha - window, -alpha, 0); 583 | if (fabs(v) == inf) 584 | return -inf; 585 | if (beta <= v) 586 | return v; 587 | if (alpha < v){ 588 | alpha = v; 589 | if (depth > simple_threshold) 590 | v = -nega_scout(lst[i].b, depth - 1, -beta, -alpha, 0); 591 | else 592 | v = -nega_alpha(lst[i].b, depth - 1, -beta, -alpha, 0); 593 | if (fabs(v) == inf) 594 | return -inf; 595 | if (beta <= v) 596 | return v; 597 | alpha = max(alpha, v); 598 | } 599 | if (val < v) 600 | val = v; 601 | } 602 | /* 603 | if (val <= alpha) 604 | search_param.memo_ub[board] = val; 605 | else if (val >= beta) 606 | search_param.memo_lb[board] = val; 607 | else { 608 | search_param.memo_ub[board] = val; 609 | search_param.memo_lb[board] = val; 610 | } 611 | */ 612 | return val; 613 | } 614 | 615 | double map_double(double y1, double y2, double y3, double x){ 616 | double a, b, c; 617 | double x1 = 4.0, x2 = 32.0, x3 = 64.0; 618 | a = ((y1 - y2) * (x1 - x3) - (y1 - y3) * (x1 - x2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)); 619 | b = (y1 - y2) / (x1 - x2) - a * (x1 + x2); 620 | c = y1 - a * x1 * x1 - b * x1; 621 | return a * x * x + b * x + c; 622 | } 623 | 624 | double map_linar(double s, double e, double x){ 625 | return s + (e - s) * x; 626 | } 627 | 628 | int cmp_main(board_priority_move p, board_priority_move q){ 629 | return p.priority > q.priority; 630 | } 631 | 632 | int main(int argc, char* argv[]){ 633 | int ansy, ansx, outy, outx, i, j, k, canput, former_depth = 7, former_vacant = hw2 - 4; 634 | double score, max_score; 635 | unsigned long long p, o; 636 | int board[board_index_num]; 637 | int put; 638 | vector lst; 639 | int elem; 640 | int action_count; 641 | double game_ratio; 642 | int vacant_cnt, ai_player; 643 | int board_tmp; 644 | int y, x; 645 | 646 | init(argc, argv); 647 | cin >> ai_player; 648 | cin >> search_param.tl; 649 | 650 | if (ai_player == 0){ 651 | //cerr << "AI initialized AI is Black" << endl; 652 | }else{ 653 | //cerr << "AI initialized AI is White" << endl; 654 | } 655 | while (true){ 656 | outy = -1; 657 | outx = -1; 658 | vacant_cnt = 0; 659 | p = 0; 660 | o = 0; 661 | canput = 0; 662 | for (i = 0; i < hw2; ++i){ 663 | cin >> elem; 664 | vacant_cnt += (int)(elem == -1 || elem == 2); 665 | p |= (unsigned long long)(elem == ai_player) << i; 666 | o |= (unsigned long long)(elem == 1 - ai_player) << i; 667 | } 668 | for (i = 0; i < board_index_num; ++i){ 669 | board_tmp = 0; 670 | for (j = 0; j < board_param.pattern_space[i]; ++j){ 671 | if (1 & (p >> board_param.board_translate[i][j])) 672 | board_tmp += board_param.pow3[j]; 673 | else if (1 & (o >> board_param.board_translate[i][j])) 674 | board_tmp += 2 * board_param.pow3[j]; 675 | } 676 | board[i] = board_tmp; 677 | } 678 | search_param.min_max_depth = 2; 679 | //cerr << "start depth " << search_param.min_max_depth << endl; 680 | search_param.max_depth = search_param.min_max_depth; 681 | former_vacant = vacant_cnt; 682 | lst.clear(); 683 | for (i = 0; i < board_index_num; ++i){ 684 | for (j = 0; j < board_param.pattern_space[i]; ++j){ 685 | if (board_param.legal[board[i]][j]){ 686 | ++canput; 687 | board_priority_move tmp; 688 | move(board, tmp.b, board_param.board_translate[i][j]); 689 | tmp.priority = evaluate(tmp.b); 690 | tmp.move = board_param.board_translate[i][j]; 691 | lst.push_back(tmp); 692 | } 693 | } 694 | } 695 | if (canput > 1) 696 | sort(lst.begin(), lst.end(), cmp_main); 697 | outy = -1; 698 | outx = -1; 699 | search_param.strt = tim(); 700 | while (tim() - search_param.strt < search_param.tl / 2){ 701 | search_param.memo_ub.clear(); 702 | search_param.memo_lb.clear(); 703 | search_param.turn = hw2 - vacant_cnt + search_param.max_depth; 704 | game_ratio = (double)search_param.turn / hw2; 705 | eval_param.pattern_weight = map_double(eval_param.weight_sme[0], eval_param.weight_sme[1], eval_param.weight_sme[2], game_ratio); 706 | eval_param.cnt_weight = map_double(eval_param.weight_sme[3], eval_param.weight_sme[4], eval_param.weight_sme[5], game_ratio); 707 | eval_param.canput_weight = map_double(eval_param.weight_sme[6], eval_param.weight_sme[7], eval_param.weight_sme[8], game_ratio); 708 | eval_param.cnt_bias = map_double(eval_param.weight_sme[9], eval_param.weight_sme[10], eval_param.weight_sme[11], game_ratio); 709 | max_score = -65000.0; 710 | for (i = 0; i < canput; ++i){ 711 | score = -nega_scout(lst[i].b, search_param.max_depth - 1, -65000.0, -max_score, 0); 712 | if (fabs(score) == inf){ 713 | max_score = -inf; 714 | break; 715 | } 716 | lst[i].priority = score; 717 | if (score > max_score){ 718 | max_score = score; 719 | ansy = lst[i].move / hw; 720 | ansx = lst[i].move % hw; 721 | } 722 | } 723 | if (max_score == -inf){ 724 | //cerr << "depth " << search_param.max_depth << " timeoout" << endl; 725 | break; 726 | } 727 | former_depth = search_param.max_depth; 728 | outy = ansy; 729 | outx = ansx; 730 | if (canput > 1) 731 | sort(lst.begin(), lst.end(), cmp_main); 732 | //cerr << "depth " << search_param.max_depth; 733 | for (i = 0; i < 1; ++i){ 734 | //cerr << " " << (lst[i].move / hw) << (lst[i].move % hw) << " " << lst[i].priority; 735 | } 736 | //cerr << " time " << tim() - search_param.strt << endl; 737 | if (vacant_cnt < search_param.max_depth || fabs(max_score) >= 1000.0){ 738 | //cerr << "game end" << endl; 739 | break; 740 | } 741 | break; 742 | ++search_param.max_depth; 743 | } 744 | cout << outy << " " << outx << endl; 745 | } 746 | return 0; 747 | } -------------------------------------------------------------------------------- /legacy/AI_ML/ai_cpp.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx") 2 | 3 | // Reversi AI C++ version 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | 21 | #define hw 8 22 | #define hw2 64 23 | #define window 0.00001 24 | #define simple_threshold 2 25 | 26 | const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1}; 27 | const int dx[8] = {1, 0, -1, 0, 1, -1, 1, -1}; 28 | 29 | int tim(){ 30 | return static_cast(chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count()); 31 | } 32 | 33 | struct HashPair { 34 | static size_t m_hash_pair_random; 35 | template 36 | size_t operator()(const pair &p) const { 37 | auto hash1 = hash{}(p.first); 38 | auto hash2 = hash{}(p.second); 39 | size_t seed = 0; 40 | seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2); 41 | seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); 42 | seed ^= m_hash_pair_random + 0x9e3779b9 + (seed << 6) + (seed >> 2); 43 | return seed; 44 | } 45 | }; 46 | 47 | size_t HashPair::m_hash_pair_random = (size_t) random_device()(); 48 | 49 | const double weight[hw2] = { 50 | 3.2323232323232323, 0.23088023088023088, 1.3852813852813852, 1.0389610389610389, 1.0389610389610389, 1.3852813852813852, 0.23088023088023088, 3.2323232323232323, 51 | 0.23088023088023088, 0.0, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.0, 0.23088023088023088, 52 | 1.3852813852813852, 0.9004329004329005, 1.0389610389610389, 0.9466089466089466, 0.9466089466089466, 1.0389610389610389, 0.9004329004329005, 1.3852813852813852, 53 | 1.0389610389610389, 0.9004329004329005, 0.9466089466089466, 0.9235209235209235, 0.9235209235209235, 0.9466089466089466, 0.9004329004329005, 1.0389610389610389, 54 | 1.0389610389610389, 0.9004329004329005, 0.9466089466089466, 0.9235209235209235, 0.9235209235209235, 0.9466089466089466, 0.9004329004329005, 1.0389610389610389, 55 | 1.3852813852813852, 0.9004329004329005, 1.0389610389610389, 0.9466089466089466, 0.9466089466089466, 1.0389610389610389, 0.9004329004329005, 1.3852813852813852, 56 | 0.23088023088023088, 0.0, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.9004329004329005, 0.0, 0.23088023088023088, 57 | 3.2323232323232323, 0.23088023088023088, 1.3852813852813852, 1.0389610389610389, 1.0389610389610389, 1.3852813852813852, 0.23088023088023088, 3.2323232323232323 58 | }; 59 | 60 | const int confirm_lst[hw][hw] = { 61 | {63, 62, 61, 60, 59, 58, 57, 56}, 62 | {56, 57, 58, 59, 60, 61, 62, 63}, 63 | {63, 55, 47, 39, 31, 23, 15, 7}, 64 | { 7, 15, 23, 31, 39, 47, 55, 63}, 65 | { 7, 6, 5, 4, 3, 2, 1, 0}, 66 | { 0, 1, 2, 3, 4, 5, 6, 7}, 67 | {56, 48, 40 , 32, 24, 16, 8, 0}, 68 | { 0, 8, 16, 24, 32, 40, 48, 56} 69 | }; 70 | 71 | const unsigned long long confirm_num[4] = { 72 | 0b0000000000000000000000000000000000000000000000000000000011111111, 73 | 0b0000000100000001000000010000000100000001000000010000000100000001, 74 | 0b1111111100000000000000000000000000000000000000000000000000000000, 75 | 0b1000000010000000100000001000000010000000100000001000000010000000 76 | }; 77 | 78 | struct grid_priority{ 79 | unsigned long long me; 80 | unsigned long long op; 81 | int open_val; 82 | }; 83 | 84 | struct grid_priority_main{ 85 | double priority; 86 | unsigned long long me; 87 | unsigned long long op; 88 | int move; 89 | }; 90 | 91 | int ai_player; 92 | double weight_weight, canput_weight, confirm_weight, stone_weight, open_weight, out_weight; 93 | int max_depth, vacant_cnt; 94 | double game_ratio; 95 | unordered_map, double, HashPair> memo1, memo2; 96 | unordered_map, double, HashPair> memo_lb, memo_ub; 97 | unsigned long long marked; 98 | int min_max_depth; 99 | int tl, strt; 100 | 101 | #ifdef _MSC_VER 102 | #define mirror_v(x) _byteswap_uint64(x) 103 | #else 104 | #define mirror_v(x) __builtin_bswap64(x) 105 | #endif 106 | 107 | inline unsigned long long check_mobility(const unsigned long long P, const unsigned long long O){ 108 | unsigned long long moves, mO, flip1, pre1, flip8, pre8; 109 | __m128i PP, mOO, MM, flip, pre; 110 | mO = O & 0x7e7e7e7e7e7e7e7eULL; 111 | PP = _mm_set_epi64x(mirror_v(P), P); 112 | mOO = _mm_set_epi64x(mirror_v(mO), mO); 113 | flip = _mm_and_si128(mOO, _mm_slli_epi64(PP, 7)); flip1 = mO & (P << 1); flip8 = O & (P << 8); 114 | flip = _mm_or_si128(flip, _mm_and_si128(mOO, _mm_slli_epi64(flip, 7))); flip1 |= mO & (flip1 << 1); flip8 |= O & (flip8 << 8); 115 | pre = _mm_and_si128(mOO, _mm_slli_epi64(mOO, 7)); pre1 = mO & (mO << 1); pre8 = O & (O << 8); 116 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 14))); flip1 |= pre1 & (flip1 << 2); flip8 |= pre8 & (flip8 << 16); 117 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 14))); flip1 |= pre1 & (flip1 << 2); flip8 |= pre8 & (flip8 << 16); 118 | MM = _mm_slli_epi64(flip, 7); moves = flip1 << 1; moves |= flip8 << 8; 119 | flip = _mm_and_si128(mOO, _mm_slli_epi64(PP, 9)); flip1 = mO & (P >> 1); flip8 = O & (P >> 8); 120 | flip = _mm_or_si128(flip, _mm_and_si128(mOO, _mm_slli_epi64(flip, 9))); flip1 |= mO & (flip1 >> 1); flip8 |= O & (flip8 >> 8); 121 | pre = _mm_and_si128(mOO, _mm_slli_epi64(mOO, 9)); pre1 >>= 1; pre8 >>= 8; 122 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 18))); flip1 |= pre1 & (flip1 >> 2); flip8 |= pre8 & (flip8 >> 16); 123 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 18))); flip1 |= pre1 & (flip1 >> 2); flip8 |= pre8 & (flip8 >> 16); 124 | MM = _mm_or_si128(MM, _mm_slli_epi64(flip, 9)); moves |= flip1 >> 1; moves |= flip8 >> 8; 125 | moves |= _mm_cvtsi128_si64(MM) | mirror_v(_mm_cvtsi128_si64(_mm_unpackhi_epi64(MM, MM))); 126 | return moves & ~(P | O); 127 | } 128 | 129 | inline unsigned long long move(unsigned long long grid_me, unsigned long long grid_op, int place){ 130 | unsigned long long wh, put, m1, m2, m3, m4, m5, m6, rev; 131 | put = (unsigned long long)1 << place; 132 | rev = 0; 133 | wh = grid_op & 0x7e7e7e7e7e7e7e7e; 134 | m1 = put >> 1; 135 | if( (m1 & wh) != 0 ) { 136 | if( ((m2 = m1 >> 1) & wh) == 0 ) { 137 | if( (m2 & grid_me) != 0 ) 138 | rev |= m1; 139 | } else if( ((m3 = m2 >> 1) & wh) == 0 ) { 140 | if( (m3 & grid_me) != 0 ) 141 | rev |= m1 | m2; 142 | } else if( ((m4 = m3 >> 1) & wh) == 0 ) { 143 | if( (m4 & grid_me) != 0 ) 144 | rev |= m1 | m2 | m3; 145 | } else if( ((m5 = m4 >> 1) & wh) == 0 ) { 146 | if( (m5 & grid_me) != 0 ) 147 | rev |= m1 | m2 | m3 | m4; 148 | } else if( ((m6 = m5 >> 1) & wh) == 0 ) { 149 | if( (m6 & grid_me) != 0 ) 150 | rev |= m1 | m2 | m3 | m4 | m5; 151 | } else { 152 | if( ((m6 >> 1) & grid_me) != 0 ) 153 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 154 | } 155 | } 156 | m1 = put << 1; 157 | if( (m1 & wh) != 0 ) { 158 | if( ((m2 = m1 << 1) & wh) == 0 ) { 159 | if( (m2 & grid_me) != 0 ) 160 | rev |= m1; 161 | } else if( ((m3 = m2 << 1) & wh) == 0 ) { 162 | if( (m3 & grid_me) != 0 ) 163 | rev |= m1 | m2; 164 | } else if( ((m4 = m3 << 1) & wh) == 0 ) { 165 | if( (m4 & grid_me) != 0 ) 166 | rev |= m1 | m2 | m3; 167 | } else if( ((m5 = m4 << 1) & wh) == 0 ) { 168 | if( (m5 & grid_me) != 0 ) 169 | rev |= m1 | m2 | m3 | m4; 170 | } else if( ((m6 = m5 << 1) & wh) == 0 ) { 171 | if( (m6 & grid_me) != 0 ) 172 | rev |= m1 | m2 | m3 | m4 | m5; 173 | } else { 174 | if( ((m6 << 1) & grid_me) != 0 ) 175 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 176 | } 177 | } 178 | 179 | wh = grid_op & 0x00FFFFFFFFFFFF00; 180 | m1 = put >> hw; 181 | if( (m1 & wh) != 0 ) { 182 | if( ((m2 = m1 >> hw) & wh) == 0 ) { 183 | if( (m2 & grid_me) != 0 ) 184 | rev |= m1; 185 | } else if( ((m3 = m2 >> hw) & wh) == 0 ) { 186 | if( (m3 & grid_me) != 0 ) 187 | rev |= m1 | m2; 188 | } else if( ((m4 = m3 >> hw) & wh) == 0 ) { 189 | if( (m4 & grid_me) != 0 ) 190 | rev |= m1 | m2 | m3; 191 | } else if( ((m5 = m4 >> hw) & wh) == 0 ) { 192 | if( (m5 & grid_me) != 0 ) 193 | rev |= m1 | m2 | m3 | m4; 194 | } else if( ((m6 = m5 >> hw) & wh) == 0 ) { 195 | if( (m6 & grid_me) != 0 ) 196 | rev |= m1 | m2 | m3 | m4 | m5; 197 | } else { 198 | if( ((m6 >> hw) & grid_me) != 0 ) 199 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 200 | } 201 | } 202 | m1 = put << hw; 203 | if( (m1 & wh) != 0 ) { 204 | if( ((m2 = m1 << hw) & wh) == 0 ) { 205 | if( (m2 & grid_me) != 0 ) 206 | rev |= m1; 207 | } else if( ((m3 = m2 << hw) & wh) == 0 ) { 208 | if( (m3 & grid_me) != 0 ) 209 | rev |= m1 | m2; 210 | } else if( ((m4 = m3 << hw) & wh) == 0 ) { 211 | if( (m4 & grid_me) != 0 ) 212 | rev |= m1 | m2 | m3; 213 | } else if( ((m5 = m4 << hw) & wh) == 0 ) { 214 | if( (m5 & grid_me) != 0 ) 215 | rev |= m1 | m2 | m3 | m4; 216 | } else if( ((m6 = m5 << hw) & wh) == 0 ) { 217 | if( (m6 & grid_me) != 0 ) 218 | rev |= m1 | m2 | m3 | m4 | m5; 219 | } else { 220 | if( ((m6 << hw) & grid_me) != 0 ) 221 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 222 | } 223 | } 224 | 225 | wh = grid_op & 0x007e7e7e7e7e7e00; 226 | m1 = put >> (hw - 1); 227 | if( (m1 & wh) != 0 ) { 228 | if( ((m2 = m1 >> (hw - 1)) & wh) == 0 ) { 229 | if( (m2 & grid_me) != 0 ) 230 | rev |= m1; 231 | } else if( ((m3 = m2 >> (hw - 1)) & wh) == 0 ) { 232 | if( (m3 & grid_me) != 0 ) 233 | rev |= m1 | m2; 234 | } else if( ((m4 = m3 >> (hw - 1)) & wh) == 0 ) { 235 | if( (m4 & grid_me) != 0 ) 236 | rev |= m1 | m2 | m3; 237 | } else if( ((m5 = m4 >> (hw - 1)) & wh) == 0 ) { 238 | if( (m5 & grid_me) != 0 ) 239 | rev |= m1 | m2 | m3 | m4; 240 | } else if( ((m6 = m5 >> (hw - 1)) & wh) == 0 ) { 241 | if( (m6 & grid_me) != 0 ) 242 | rev |= m1 | m2 | m3 | m4 | m5; 243 | } else { 244 | if( ((m6 >> (hw - 1)) & grid_me) != 0 ) 245 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 246 | } 247 | } 248 | m1 = put << (hw - 1); 249 | if( (m1 & wh) != 0 ) { 250 | if( ((m2 = m1 << (hw - 1)) & wh) == 0 ) { 251 | if( (m2 & grid_me) != 0 ) 252 | rev |= m1; 253 | } else if( ((m3 = m2 << (hw - 1)) & wh) == 0 ) { 254 | if( (m3 & grid_me) != 0 ) 255 | rev |= m1 | m2; 256 | } else if( ((m4 = m3 << (hw - 1)) & wh) == 0 ) { 257 | if( (m4 & grid_me) != 0 ) 258 | rev |= m1 | m2 | m3; 259 | } else if( ((m5 = m4 << (hw - 1)) & wh) == 0 ) { 260 | if( (m5 & grid_me) != 0 ) 261 | rev |= m1 | m2 | m3 | m4; 262 | } else if( ((m6 = m5 << (hw - 1)) & wh) == 0 ) { 263 | if( (m6 & grid_me) != 0 ) 264 | rev |= m1 | m2 | m3 | m4 | m5; 265 | } else { 266 | if( ((m6 << (hw - 1)) & grid_me) != 0 ) 267 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 268 | } 269 | } 270 | 271 | m1 = put >> (hw + 1); 272 | if( (m1 & wh) != 0 ) { 273 | if( ((m2 = m1 >> (hw + 1)) & wh) == 0 ) { 274 | if( (m2 & grid_me) != 0 ) 275 | rev |= m1; 276 | } else if( ((m3 = m2 >> (hw + 1)) & wh) == 0 ) { 277 | if( (m3 & grid_me) != 0 ) 278 | rev |= m1 | m2; 279 | } else if( ((m4 = m3 >> (hw + 1)) & wh) == 0 ) { 280 | if( (m4 & grid_me) != 0 ) 281 | rev |= m1 | m2 | m3; 282 | } else if( ((m5 = m4 >> (hw + 1)) & wh) == 0 ) { 283 | if( (m5 & grid_me) != 0 ) 284 | rev |= m1 | m2 | m3 | m4; 285 | } else if( ((m6 = m5 >> (hw + 1)) & wh) == 0 ) { 286 | if( (m6 & grid_me) != 0 ) 287 | rev |= m1 | m2 | m3 | m4 | m5; 288 | } else { 289 | if( ((m6 >> (hw + 1)) & grid_me) != 0 ) 290 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 291 | } 292 | } 293 | m1 = put << (hw + 1); 294 | if( (m1 & wh) != 0 ) { 295 | if( ((m2 = m1 << (hw + 1)) & wh) == 0 ) { 296 | if( (m2 & grid_me) != 0 ) 297 | rev |= m1; 298 | } else if( ((m3 = m2 << (hw + 1)) & wh) == 0 ) { 299 | if( (m3 & grid_me) != 0 ) 300 | rev |= m1 | m2; 301 | } else if( ((m4 = m3 << (hw + 1)) & wh) == 0 ) { 302 | if( (m4 & grid_me) != 0 ) 303 | rev |= m1 | m2 | m3; 304 | } else if( ((m5 = m4 << (hw + 1)) & wh) == 0 ) { 305 | if( (m5 & grid_me) != 0 ) 306 | rev |= m1 | m2 | m3 | m4; 307 | } else if( ((m6 = m5 << (hw + 1)) & wh) == 0 ) { 308 | if( (m6 & grid_me) != 0 ) 309 | rev |= m1 | m2 | m3 | m4 | m5; 310 | } else { 311 | if( ((m6 << (hw + 1)) & grid_me) != 0 ) 312 | rev |= m1 | m2 | m3 | m4 | m5 | m6; 313 | } 314 | } 315 | return grid_me ^ (put | rev); 316 | } 317 | 318 | inline int check_confirm(unsigned long long grid, int idx){ 319 | int i, res = 0; 320 | for (i = 0; i < hw; i++){ 321 | if (1 & (grid >> confirm_lst[idx][i])) 322 | res++; 323 | else 324 | break; 325 | } 326 | return res; 327 | } 328 | 329 | inline double evaluate(unsigned long long grid_me, unsigned long long grid_op, int canput, int open_val){ 330 | int canput_all = canput; 331 | double weight_me = 0.0, weight_op = 0.0; 332 | int me_cnt = 0, op_cnt = 0; 333 | int confirm_me = 0, confirm_op = 0; 334 | int stone_me = 0, stone_op = 0; 335 | int out_me = 0, out_op = 0; 336 | unsigned long long mobility, stones; 337 | int i, j; 338 | for (i = 0; i < hw2; i++){ 339 | if (1 & (grid_me >> (hw2 - i - 1))){ 340 | weight_me += weight[i]; 341 | me_cnt++; 342 | } else if (1 & (grid_op >> (hw2 - i - 1))){ 343 | weight_op += weight[i]; 344 | op_cnt++; 345 | } 346 | } 347 | mobility = check_mobility(grid_me, grid_op); 348 | for (i = 0; i < hw2; i++) 349 | canput_all += 1 & (mobility >> i); 350 | stones = grid_me | grid_op; 351 | for (i = 0; i < hw; i += 2){ 352 | if (stones ^ confirm_num[i / 2]){ 353 | for (j = 0; j < 2; j++){ 354 | confirm_me += max(0, check_confirm(grid_me, i + j) - 1); 355 | confirm_op += max(0, check_confirm(grid_op, i + j) - 1); 356 | } 357 | } else { 358 | for (j = 1; j < hw - 1; j++){ 359 | if (1 & (grid_me >> confirm_lst[i][j])) 360 | confirm_me++; 361 | else if (1 & (grid_op >> confirm_lst[i][j])) 362 | confirm_op++; 363 | } 364 | } 365 | } 366 | confirm_me += 1 & grid_me; 367 | confirm_me += 1 & (grid_me >> (hw - 1)); 368 | confirm_me += 1 & (grid_me >> (hw2 - hw)); 369 | confirm_me += 1 & (grid_me >> (hw2 - 1)); 370 | confirm_op += 1 & grid_op; 371 | confirm_op += 1 & (grid_op >> (hw - 1)); 372 | confirm_op += 1 & (grid_op >> (hw2 - hw)); 373 | confirm_op += 1 & (grid_op >> (hw2 - 1)); 374 | for (i = 0; i < hw2; i++){ 375 | stone_me += 1 & (grid_me >> i); 376 | stone_op += 1 & (grid_op >> i); 377 | } 378 | for (i = 0; i < hw2; i++){ 379 | if (1 & (stones >> i)) 380 | continue; 381 | out_me += 1 & (grid_me >> (i + 1)); 382 | out_me += 1 & (grid_me >> (i - 1)); 383 | out_me += 1 & (grid_me >> (i + hw)); 384 | out_me += 1 & (grid_me >> (i - hw)); 385 | out_me += 1 & (grid_me >> (i + hw + 1)); 386 | out_me += 1 & (grid_me >> (i - hw + 1)); 387 | out_me += 1 & (grid_me >> (i + hw - 1)); 388 | out_me += 1 & (grid_me >> (i - hw - 1)); 389 | out_op += 1 & (grid_op >> (i + 1)); 390 | out_op += 1 & (grid_op >> (i - 1)); 391 | out_op += 1 & (grid_op >> (i + hw)); 392 | out_op += 1 & (grid_op >> (i - hw)); 393 | out_op += 1 & (grid_op >> (i + hw + 1)); 394 | out_op += 1 & (grid_op >> (i - hw + 1)); 395 | out_op += 1 & (grid_op >> (i + hw - 1)); 396 | out_op += 1 & (grid_op >> (i - hw - 1)); 397 | } 398 | double weight_proc, canput_proc, confirm_proc, stone_proc, open_proc, out_proc; 399 | weight_proc = weight_me / me_cnt - weight_op / op_cnt; 400 | canput_proc = (double)(canput_all - canput) / max(1, canput_all) - (double)canput / max(1, canput_all); 401 | confirm_proc = (double)confirm_me / max(1, confirm_me + confirm_op) - (double)confirm_op / max(1, confirm_me + confirm_op); 402 | stone_proc = -(double)stone_me / (stone_me + stone_op) + (double)stone_op / (stone_me + stone_op); 403 | open_proc = max(-1.0, (double)(5 - open_val) / 5); 404 | out_proc = -(double)out_me / max(1, out_me + out_op) + (double)out_op / max(1, out_me + out_op); 405 | return weight_proc * weight_weight + canput_proc * canput_weight + confirm_proc * confirm_weight + stone_proc * stone_weight + open_proc * open_weight + out_proc * out_weight; 406 | } 407 | 408 | inline double end_game(unsigned long long grid_me, unsigned long long grid_op){ 409 | int res = 0, i; 410 | for (i = 0; i < hw2; i++){ 411 | res += 1 & (grid_me >> i); 412 | res -= 1 & (grid_op >> i); 413 | } 414 | return (double)res; 415 | } 416 | 417 | inline int calc_open(unsigned long long stones, unsigned long long rev){ 418 | int i, res = 0; 419 | for (i = 0; i < hw2; i++){ 420 | if (1 & (rev >> i)){ 421 | res += 1 - (1 & (stones >> (i + 1))); 422 | res += 1 - (1 & (stones >> (i - 1))); 423 | res += 1 - (1 & (stones >> (i + hw))); 424 | res += 1 - (1 & (stones >> (i - hw))); 425 | res += 1 - (1 & (stones >> (i + hw + 1))); 426 | res += 1 - (1 & (stones >> (i - hw + 1))); 427 | res += 1 - (1 & (stones >> (i + hw - 1))); 428 | res += 1 - (1 & (stones >> (i - hw - 1))); 429 | } 430 | } 431 | return res; 432 | } 433 | 434 | int cmp(grid_priority p, grid_priority q){ 435 | return p.open_val < q.open_val; 436 | } 437 | 438 | inline int pop_count_ull(unsigned long long x){ 439 | x = x - ((x >> 1) & 0x5555555555555555); 440 | x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); 441 | x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F; 442 | x = (x * 0x0101010101010101) >> 56; 443 | return (int)x; 444 | } 445 | 446 | double nega_alpha(unsigned long long grid_me, unsigned long long grid_op, int depth, double alpha, double beta, int skip_cnt, int canput, int open_val){ 447 | if (skip_cnt == 2) 448 | return end_game(grid_me, grid_op); 449 | else if (depth == 0) 450 | return evaluate(grid_me, grid_op, canput, open_val); 451 | double val, v, ub, lb; 452 | int i, n_canput; 453 | unsigned long long mobility = check_mobility(grid_me, grid_op); 454 | unsigned long long n_grid_me, n_grid_op, x; 455 | double priority; 456 | val = -65.0; 457 | n_canput = pop_count_ull(mobility); 458 | if (n_canput == 0) 459 | return -nega_alpha(grid_op, grid_me, depth, -beta, -alpha, skip_cnt + 1, 0, 0); 460 | for (i = 0; i < hw2; i++){ 461 | if (1 & (mobility >> i)){ 462 | n_grid_me = move(grid_me, grid_op, i); 463 | n_grid_op = (n_grid_me ^ grid_op) & grid_op; 464 | v = -nega_alpha(n_grid_op, n_grid_me, depth - 1, -beta, -alpha, 0, n_canput, calc_open(n_grid_me | n_grid_op, n_grid_me ^ grid_me)); 465 | if (fabs(v) == 100000000.0) 466 | return -100000000.0; 467 | if (beta <= v) 468 | return v; 469 | alpha = max(alpha, v); 470 | if (val < v) 471 | val = v; 472 | } 473 | } 474 | return val; 475 | } 476 | 477 | double nega_scout(unsigned long long grid_me, unsigned long long grid_op, int depth, double alpha, double beta, int skip_cnt){ 478 | if (max_depth > min_max_depth && tim() - strt > tl) 479 | return -100000000.0; 480 | if (skip_cnt == 2) 481 | return end_game(grid_me, grid_op); 482 | double val, v, ub, lb; 483 | pair grid_all; 484 | grid_all.first = grid_me; 485 | grid_all.second = grid_op; 486 | lb = memo_lb[grid_all]; 487 | if (lb != 0.0){ 488 | if (lb >= beta) 489 | return lb; 490 | alpha = max(alpha, lb); 491 | } 492 | ub = memo_ub[grid_all]; 493 | if (ub != 0.0){ 494 | if (alpha >= ub || ub == lb) 495 | return ub; 496 | beta = min(beta, ub); 497 | } 498 | int i, n_canput = 0, open_val; 499 | unsigned long long mobility = check_mobility(grid_me, grid_op); 500 | unsigned long long n_grid_me, n_grid_op; 501 | double priority; 502 | vector lst; 503 | for (i = 0; i < hw2; i++){ 504 | if (1 & (mobility >> i)){ 505 | n_canput++; 506 | n_grid_me = move(grid_me, grid_op, i); 507 | n_grid_op = (n_grid_me ^ grid_op) & grid_op; 508 | grid_priority tmp; 509 | tmp.open_val = calc_open(n_grid_me | n_grid_op, n_grid_me ^ grid_me); 510 | tmp.me = n_grid_me; 511 | tmp.op = n_grid_op; 512 | lst.push_back(tmp); 513 | } 514 | } 515 | if (n_canput == 0) 516 | return -nega_scout(grid_op, grid_me, depth, -beta, -alpha, skip_cnt + 1); 517 | if (n_canput > 1) 518 | sort(lst.begin(), lst.end(), cmp); 519 | if (depth > simple_threshold) 520 | v = -nega_scout(lst[0].op, lst[0].me, depth - 1, -beta, -alpha, 0); 521 | else 522 | v = -nega_alpha(lst[0].op, lst[0].me, depth - 1, -beta, -alpha, 0, n_canput, lst[0].open_val); 523 | val = v; 524 | if (fabs(v) == 100000000.0) 525 | return -100000000.0; 526 | if (beta <= v) 527 | return v; 528 | alpha = max(alpha, v); 529 | for (i = 1; i < n_canput; i++){ 530 | if (depth > simple_threshold) 531 | v = -nega_scout(lst[i].op, lst[i].me, depth - 1, -alpha - window, -alpha, 0); 532 | else 533 | v = -nega_alpha(lst[i].op, lst[i].me, depth - 1, -alpha - window, -alpha, 0, n_canput, lst[i].open_val); 534 | if (fabs(v) == 100000000.0) 535 | return -100000000.0; 536 | if (beta <= v) 537 | return v; 538 | if (alpha < v){ 539 | alpha = v; 540 | if (depth > simple_threshold) 541 | v = -nega_scout(lst[i].op, lst[i].me, depth - 1, -beta, -alpha, 0); 542 | else 543 | v = -nega_alpha(lst[i].op, lst[i].me, depth - 1, -beta, -alpha, 0, n_canput, lst[i].open_val); 544 | if (fabs(v) == 100000000.0) 545 | return -100000000.0; 546 | if (beta <= v) 547 | return v; 548 | alpha = max(alpha, v); 549 | } 550 | if (val < v) 551 | val = v; 552 | } 553 | if (val <= alpha) 554 | memo_ub[grid_all] = val; 555 | else if (val >= beta) 556 | memo_lb[grid_all] = val; 557 | else { 558 | memo_ub[grid_all] = val; 559 | memo_lb[grid_all] = val; 560 | } 561 | return val; 562 | } 563 | 564 | double map_double(double s, double e, double x){ 565 | return s + (e - s) * x; 566 | } 567 | 568 | int cmp_main(grid_priority_main p, grid_priority_main q){ 569 | return p.priority > q.priority; 570 | } 571 | 572 | int main(){ 573 | int ansy, ansx, outy, outx, i, canput, former_depth = 9, former_vacant = hw2 - 4; 574 | double score, max_score; 575 | double weight_weight_s, canput_weight_s, confirm_weight_s, stone_weight_s, open_weight_s, out_weight_s, weight_weight_e, canput_weight_e, confirm_weight_e, stone_weight_e, open_weight_e, out_weight_e; 576 | unsigned long long in_grid_me, in_grid_op, in_mobility, grid_me, grid_op; 577 | vector lst; 578 | pair grid_all; 579 | int elem; 580 | cin >> ai_player; 581 | cin >> tl; 582 | cin >> weight_weight_s; 583 | cin >> canput_weight_s; 584 | cin >> confirm_weight_s; 585 | cin >> stone_weight_s; 586 | cin >> open_weight_s; 587 | cin >> out_weight_s; 588 | cin >> weight_weight_e; 589 | cin >> canput_weight_e; 590 | cin >> confirm_weight_e; 591 | cin >> stone_weight_e; 592 | cin >> open_weight_e; 593 | cin >> out_weight_e; 594 | /* 595 | if (ai_player == 0) 596 | //cerr << "AI initialized AI is Black" << endl; 597 | else 598 | //cerr << "AI initialized AI is White" << endl; 599 | */ 600 | while (true){ 601 | outy = -1; 602 | outx = -1; 603 | vacant_cnt = 0; 604 | in_grid_me = 0; 605 | in_grid_op = 0; 606 | in_mobility = 0; 607 | canput = 0; 608 | for (i = 0; i < hw2; i++){ 609 | cin >> elem; 610 | vacant_cnt += (int)(elem == -1 || elem == 2); 611 | in_mobility <<= 1; 612 | in_mobility += (int)(elem == 2); 613 | canput += (int)(elem == 2); 614 | in_grid_me <<= 1; 615 | in_grid_op <<= 1; 616 | in_grid_me += (int)(elem == ai_player); 617 | in_grid_op += (int)(elem == 1 - ai_player); 618 | } 619 | /* 620 | if (vacant_cnt > 14) 621 | min_max_depth = max(5, former_depth + vacant_cnt - former_vacant); 622 | else 623 | min_max_depth = 15; 624 | */ 625 | min_max_depth = 2; 626 | //cerr << "start depth " << min_max_depth << endl; 627 | max_depth = min_max_depth; 628 | former_vacant = vacant_cnt; 629 | lst.clear(); 630 | for (i = 0; i < hw2; i++){ 631 | if (1 & (in_mobility >> i)){ 632 | grid_me = move(in_grid_me, in_grid_op, i); 633 | grid_op = (grid_me ^ in_grid_op) & in_grid_op; 634 | grid_all.first = grid_me; 635 | grid_all.second = grid_op; 636 | grid_priority_main tmp; 637 | tmp.priority = -0.1 * calc_open(grid_me | grid_op, grid_me ^ in_grid_me); 638 | tmp.me = grid_me; 639 | tmp.op = grid_op; 640 | tmp.move = i; 641 | lst.push_back(tmp); 642 | } 643 | } 644 | if (canput > 1) 645 | sort(lst.begin(), lst.end(), cmp_main); 646 | strt = tim(); 647 | while (tim() - strt < tl / 2){ 648 | memo_ub.clear(); 649 | memo_lb.clear(); 650 | game_ratio = (double)(hw2 - vacant_cnt + max_depth) / hw2; 651 | weight_weight = map_double(weight_weight_s, weight_weight_e, game_ratio); 652 | canput_weight = map_double(canput_weight_s, canput_weight_e, game_ratio); 653 | confirm_weight = map_double(confirm_weight_s, confirm_weight_e, game_ratio); 654 | stone_weight = map_double(stone_weight_s, stone_weight_e, game_ratio); 655 | open_weight = map_double(open_weight_s, open_weight_e, game_ratio); 656 | out_weight = map_double(out_weight_s, out_weight_e, game_ratio); 657 | max_score = -65.0; 658 | for (i = 0; i < canput; i++){ 659 | score = -nega_scout(lst[i].op, lst[i].me, max_depth - 1, -65.0, -max_score, 0); 660 | if (fabs(score) == 100000000.0){ 661 | max_score = -100000000.0; 662 | break; 663 | } 664 | lst[i].priority = score; 665 | if (score > max_score){ 666 | max_score = score; 667 | ansy = (hw2 - lst[i].move - 1) / hw; 668 | ansx = (hw2 - lst[i].move - 1) % hw; 669 | } 670 | } 671 | if (max_score == -100000000.0){ 672 | //cerr << "depth " << max_depth << " timeoout" << endl; 673 | break; 674 | } 675 | former_depth = max_depth; 676 | outy = ansy; 677 | outx = ansx; 678 | if (canput > 1) 679 | sort(lst.begin(), lst.end(), cmp_main); 680 | //cerr << "depth " << max_depth; 681 | for (i = 0; i < canput; i++) 682 | //cerr << " " << ((hw2 - lst[i].move - 1) / hw) << ((hw2 - lst[i].move - 1) % hw) << " " << lst[i].priority; 683 | //cerr << " time " << tim() - strt << endl; 684 | if (vacant_cnt < max_depth || fabs(max_score) >= 1.0){ 685 | //cerr << "game end" << endl; 686 | break; 687 | } 688 | max_depth++; 689 | break; 690 | } 691 | cout << outy << " " << outx << endl; 692 | } 693 | return 0; 694 | } -------------------------------------------------------------------------------- /legacy/AI_Cpp/ai_mcts.cpp: -------------------------------------------------------------------------------- 1 | #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx") 2 | 3 | // Reversi AI C++ version 2 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace std; 21 | 22 | int xorx=123456789, xory=362436069, xorz=521288629, xorw=88675123; 23 | double myrandom(){ 24 | int t = (xorx^(xorx<<11)); 25 | xorx = xory; 26 | xory = xorz; 27 | xorz = xorw; 28 | xorw = xorw=(xorw^(xorw>>19))^(t^(t>>8)); 29 | return (double)(xorw) / 2147483648.0; 30 | } 31 | int randint(int fr, int to){ 32 | return fr + (int)(myrandom() * (to - fr + 1)); 33 | } 34 | 35 | #define hw 8 36 | #define hw_m1 7 37 | #define hw_p1 9 38 | #define hw2 64 39 | #define hw2_m1 63 40 | #define hw2_mhw 56 41 | #define window 0.00001 42 | #define simple_threshold 2 43 | #define inf 1000000000000.0 44 | #define pattern_num 6 45 | #define bias (1.0 * 1.41421356) 46 | #define expand_threshold 10 47 | 48 | struct HashPair { 49 | static size_t m_hash_pair_random; 50 | template 51 | size_t operator()(const pair &p) const { 52 | auto hash1 = hash{}(p.first); 53 | auto hash2 = hash{}(p.second); 54 | size_t seed = 0; 55 | seed ^= hash1 + 0x9e3779b9 + (seed << 6) + (seed >> 2); 56 | seed ^= hash2 + 0x9e3779b9 + (seed << 6) + (seed >> 2); 57 | seed ^= m_hash_pair_random + 0x9e3779b9 + (seed << 6) + (seed >> 2); 58 | return seed; 59 | } 60 | }; 61 | 62 | size_t HashPair::m_hash_pair_random = (size_t) random_device()(); 63 | 64 | struct eval_param{ 65 | double weight_s[hw2]; 66 | double weight_e[hw2]; 67 | double weight[hw2]; 68 | double weight_weight, canput_weight, confirm_weight, stone_weight, open_weight, out_weight, pattern_weight; 69 | double weight_se[14]; 70 | double open_val_threshold; 71 | double weight_pat_s[pattern_num]; 72 | double weight_pat_e[pattern_num]; 73 | double weight_pat[pattern_num]; 74 | unsigned long long pat_mask_h_p[pattern_num], pat_mask_h_o[pattern_num], pat_mask_h_p_m[pattern_num], pat_mask_h_o_m[pattern_num], pat_mask_v_p[pattern_num], pat_mask_v_o[pattern_num], pat_mask_v_p_m[pattern_num], pat_mask_v_o_m[pattern_num]; 75 | }; 76 | 77 | struct confirm_param{ 78 | int lst[hw][hw]; 79 | unsigned long long num[4]; 80 | }; 81 | 82 | typedef union { 83 | unsigned long long ull[4]; 84 | #ifdef __AVX2__ 85 | __m256i v4; 86 | #endif 87 | __m128i v2[2]; 88 | } V4DI; 89 | 90 | struct move_param{ 91 | V4DI lmask_v4[hw2]; 92 | V4DI rmask_v4[hw2]; 93 | }; 94 | 95 | struct grid_eval{ 96 | int n; 97 | int m; 98 | double val; 99 | bool seen; 100 | }; 101 | 102 | struct grid_node{ 103 | unsigned long long p, o; 104 | double priority; 105 | }; 106 | 107 | struct search_param{ 108 | unordered_map, grid_eval, HashPair> win_rate; 109 | int playout_cnt; 110 | int strt, tl; 111 | }; 112 | 113 | struct grid_priority{ 114 | double priority; 115 | unsigned long long p; 116 | unsigned long long o; 117 | }; 118 | 119 | eval_param eval_param; 120 | confirm_param confirm_param; 121 | move_param move_param; 122 | search_param search_param; 123 | 124 | #ifdef _MSC_VER 125 | #define mirror_v(x) _byteswap_uint64(x) 126 | #else 127 | #define mirror_v(x) __builtin_bswap64(x) 128 | #endif 129 | 130 | unsigned long long transpose(unsigned long long x) { 131 | unsigned long long t; 132 | const unsigned long long k1 = 0xaa00aa00aa00aa00; 133 | const unsigned long long k2 = 0xcccc0000cccc0000; 134 | const unsigned long long k4 = 0xf0f0f0f00f0f0f0f; 135 | t = x ^ (x << 36) ; 136 | x ^= k4 & (t ^ (x >> 36)); 137 | t = k2 & (x ^ (x << 18)); 138 | x ^= t ^ (t >> 18) ; 139 | t = k1 & (x ^ (x << 9)); 140 | x ^= t ^ (t >> 9) ; 141 | return x; 142 | } 143 | 144 | int tim(){ 145 | return static_cast(chrono::duration_cast(chrono::steady_clock::now().time_since_epoch()).count()); 146 | } 147 | 148 | void print_board(unsigned long long p, unsigned long long o){ 149 | int i, j, idx; 150 | for (i = 0; i < hw; i++){ 151 | for (j = 0; j < hw; j++){ 152 | idx = hw2 - i * hw + j; 153 | if (1 & (p >> idx)){ 154 | cerr << "P "; 155 | } else if (1 & (o >> idx)){ 156 | cerr << "O "; 157 | } else { 158 | cerr << ". "; 159 | } 160 | } 161 | cerr << endl; 162 | } 163 | cerr << endl; 164 | } 165 | 166 | void init(int argc, char* argv[]){ 167 | FILE *fp; 168 | const char* file; 169 | if (argc > 1) 170 | file = argv[1]; 171 | else 172 | file = "param.txt"; 173 | if ((fp = fopen(file, "r")) == NULL){ 174 | printf("param.txt not exist"); 175 | exit(1); 176 | } 177 | char cbuf[1024]; 178 | int translate[hw2] = { 179 | 0, 1, 2, 3, 3, 2, 1, 0, 180 | 1, 4, 5, 6, 6, 5, 4, 1, 181 | 2, 5, 7, 8, 8, 7, 5, 2, 182 | 3, 6, 8, 9, 9, 8, 6, 3, 183 | 3, 6, 8, 9, 9, 8, 6, 3, 184 | 2, 5, 7, 8, 8, 7, 5, 2, 185 | 1, 4, 5, 6, 6, 5, 4, 1, 186 | 0, 1, 2, 3, 3, 2, 1, 0 187 | }; 188 | double weight_buf[10]; 189 | int i, j; 190 | for (i = 0; i < 10; i++){ 191 | if (!fgets(cbuf, 1024, fp)){ 192 | printf("param file broken"); 193 | exit(1); 194 | } 195 | weight_buf[i] = atof(cbuf); 196 | } 197 | for (i = 0; i < hw2; i++) 198 | eval_param.weight_s[i] = weight_buf[translate[i]]; 199 | for (i = 0; i < 10; i++){ 200 | if (!fgets(cbuf, 1024, fp)){ 201 | printf("param file broken"); 202 | exit(1); 203 | } 204 | weight_buf[i] = atof(cbuf); 205 | } 206 | for (i = 0; i < hw2; i++) 207 | eval_param.weight_e[i] = weight_buf[translate[i]]; 208 | for (i = 0; i < 14; i++){ 209 | if (!fgets(cbuf, 1024, fp)){ 210 | printf("param file broken"); 211 | exit(1); 212 | } 213 | eval_param.weight_se[i] = atof(cbuf); 214 | } 215 | for (i = 0; i < pattern_num; i++){ 216 | if (!fgets(cbuf, 1024, fp)){ 217 | printf("param file broken"); 218 | exit(1); 219 | } 220 | eval_param.weight_pat_s[i] = atof(cbuf); 221 | } 222 | for (i = 0; i < pattern_num; i++){ 223 | if (!fgets(cbuf, 1024, fp)){ 224 | printf("param file broken"); 225 | exit(1); 226 | } 227 | eval_param.weight_pat_e[i] = atof(cbuf); 228 | } 229 | fclose(fp); 230 | if ((fp = fopen("const.txt", "r")) == NULL){ 231 | printf("const.txt not exist"); 232 | exit(1); 233 | } 234 | for (i = 0; i < hw; i++){ 235 | for (j = 0; j < hw; j++){ 236 | if (!fgets(cbuf, 1024, fp)){ 237 | printf("const.txt broken"); 238 | exit(1); 239 | } 240 | confirm_param.lst[i][j] = atoi(cbuf); 241 | } 242 | } 243 | for (i = 0; i < 4; i++){ 244 | if (!fgets(cbuf, 1024, fp)){ 245 | printf("const.txt broken"); 246 | exit(1); 247 | } 248 | confirm_param.num[i] = stoull(cbuf); 249 | } 250 | for (i = 0; i < hw2; i++){ 251 | for (j = 0; j < 4; j++){ 252 | if (!fgets(cbuf, 1024, fp)){ 253 | printf("const.txt broken"); 254 | exit(1); 255 | } 256 | move_param.lmask_v4[i].ull[j] = stoull(cbuf); 257 | } 258 | } 259 | for (i = 0; i < hw2; i++){ 260 | for (j = 0; j < 4; j++){ 261 | if (!fgets(cbuf, 1024, fp)){ 262 | printf("const.txt broken"); 263 | exit(1); 264 | } 265 | move_param.rmask_v4[i].ull[j] = stoull(cbuf); 266 | } 267 | } 268 | for (i = 0; i < pattern_num; i++){ 269 | if (!fgets(cbuf, 1024, fp)){ 270 | printf("const.txt broken"); 271 | exit(1); 272 | } 273 | eval_param.pat_mask_h_p[i] = stoull(cbuf); 274 | } 275 | for (i = 0; i < pattern_num; i++){ 276 | if (!fgets(cbuf, 1024, fp)){ 277 | printf("const.txt broken"); 278 | exit(1); 279 | } 280 | eval_param.pat_mask_h_o[i] = stoull(cbuf); 281 | } 282 | fclose(fp); 283 | for (i = 0; i < pattern_num; i++){ 284 | eval_param.pat_mask_h_p_m[i] = mirror_v(eval_param.pat_mask_h_p[i]); 285 | eval_param.pat_mask_h_o_m[i] = mirror_v(eval_param.pat_mask_h_o[i]); 286 | eval_param.pat_mask_v_p[i] = transpose(eval_param.pat_mask_h_p[i]); 287 | eval_param.pat_mask_v_o[i] = transpose(eval_param.pat_mask_h_o[i]); 288 | eval_param.pat_mask_v_p_m[i] = transpose(eval_param.pat_mask_h_p_m[i]); 289 | eval_param.pat_mask_v_o_m[i] = transpose(eval_param.pat_mask_h_o_m[i]); 290 | } 291 | } 292 | 293 | inline unsigned long long check_mobility(const unsigned long long P, const unsigned long long O){ 294 | unsigned long long moves, mO, flip1, pre1, flip8, pre8; 295 | __m128i PP, mOO, MM, flip, pre; 296 | mO = O & 0x7e7e7e7e7e7e7e7eULL; 297 | PP = _mm_set_epi64x(mirror_v(P), P); 298 | mOO = _mm_set_epi64x(mirror_v(mO), mO); 299 | flip = _mm_and_si128(mOO, _mm_slli_epi64(PP, 7)); flip1 = mO & (P << 1); flip8 = O & (P << 8); 300 | flip = _mm_or_si128(flip, _mm_and_si128(mOO, _mm_slli_epi64(flip, 7))); flip1 |= mO & (flip1 << 1); flip8 |= O & (flip8 << 8); 301 | pre = _mm_and_si128(mOO, _mm_slli_epi64(mOO, 7)); pre1 = mO & (mO << 1); pre8 = O & (O << 8); 302 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 14))); flip1 |= pre1 & (flip1 << 2); flip8 |= pre8 & (flip8 << 16); 303 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 14))); flip1 |= pre1 & (flip1 << 2); flip8 |= pre8 & (flip8 << 16); 304 | MM = _mm_slli_epi64(flip, 7); moves = flip1 << 1; moves |= flip8 << 8; 305 | flip = _mm_and_si128(mOO, _mm_slli_epi64(PP, 9)); flip1 = mO & (P >> 1); flip8 = O & (P >> 8); 306 | flip = _mm_or_si128(flip, _mm_and_si128(mOO, _mm_slli_epi64(flip, 9))); flip1 |= mO & (flip1 >> 1); flip8 |= O & (flip8 >> 8); 307 | pre = _mm_and_si128(mOO, _mm_slli_epi64(mOO, 9)); pre1 >>= 1; pre8 >>= 8; 308 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 18))); flip1 |= pre1 & (flip1 >> 2); flip8 |= pre8 & (flip8 >> 16); 309 | flip = _mm_or_si128(flip, _mm_and_si128(pre, _mm_slli_epi64(flip, 18))); flip1 |= pre1 & (flip1 >> 2); flip8 |= pre8 & (flip8 >> 16); 310 | MM = _mm_or_si128(MM, _mm_slli_epi64(flip, 9)); moves |= flip1 >> 1; moves |= flip8 >> 8; 311 | moves |= _mm_cvtsi128_si64(MM) | mirror_v(_mm_cvtsi128_si64(_mm_unpackhi_epi64(MM, MM))); 312 | return moves & ~(P | O); 313 | } 314 | 315 | inline unsigned long long move(const unsigned long long p, const unsigned long long o, const int& pos){ 316 | __m256i PP, OO, flip, outflank, mask; 317 | __m128i flip2, OP; 318 | const __m256 exp_mask = _mm256_castsi256_ps(_mm256_set1_epi32(0xff800000)); 319 | const __m256i minusone = _mm256_set1_epi64x(-1); 320 | 321 | OP = _mm_set_epi64x(o, p); 322 | PP = _mm256_broadcastq_epi64(OP); 323 | OO = _mm256_permute4x64_epi64(_mm256_castsi128_si256(OP), 0x55); 324 | 325 | mask = move_param.rmask_v4[pos].v4; 326 | outflank = _mm256_andnot_si256(OO, mask); 327 | outflank = _mm256_cvtps_epi32(_mm256_and_ps(_mm256_cvtepi32_ps(outflank), exp_mask)); 328 | outflank = _mm256_andnot_si256(_mm256_srli_epi32(_mm256_srai_epi32(outflank, 31), 1), outflank); 329 | outflank = _mm256_and_si256(outflank, _mm256_cmpeq_epi32(_mm256_srli_epi64(outflank, 32), _mm256_setzero_si256())); 330 | outflank = _mm256_and_si256(outflank, PP); 331 | flip = _mm256_and_si256(_mm256_sub_epi64(_mm256_setzero_si256(), _mm256_add_epi64(outflank, outflank)), mask); 332 | mask = move_param.lmask_v4[pos].v4; 333 | outflank = _mm256_andnot_si256(OO, mask); 334 | outflank = _mm256_andnot_si256(_mm256_add_epi64(outflank, minusone), outflank); 335 | outflank = _mm256_and_si256(outflank, PP); 336 | outflank = _mm256_add_epi64(outflank, minusone); 337 | outflank = _mm256_add_epi64(outflank, _mm256_srli_epi64(outflank, 63)); 338 | flip = _mm256_or_si256(flip, _mm256_and_si256(outflank, mask)); 339 | flip2 = _mm_or_si128(_mm256_castsi256_si128(flip), _mm256_extracti128_si256(flip, 1)); 340 | flip2 = _mm_or_si128(flip2, _mm_shuffle_epi32(flip2, 0x4e)); 341 | 342 | unsigned long long put, rev; 343 | put = 1ULL << pos; 344 | rev = _mm_cvtsi128_si64(flip2); 345 | return p ^ (put | rev); 346 | } 347 | 348 | inline int check_confirm(const unsigned long long& grid, const int& idx){ 349 | int i, res = 0; 350 | for (i = 0; i < hw; ++i){ 351 | if (1 & (grid >> confirm_param.lst[idx][i])) 352 | res++; 353 | else 354 | break; 355 | } 356 | return res; 357 | } 358 | 359 | inline double evaluate(const unsigned long long p, const unsigned long long o, int canput, int open_val){ 360 | int canput_all = canput; 361 | double weight_me = 0.0, weight_op = 0.0; 362 | int me_cnt = 0, op_cnt = 0; 363 | int confirm_me = 0, confirm_op = 0; 364 | int out_me = 0, out_op = 0; 365 | double pattern_me = 0.0, pattern_op = 0.0; 366 | unsigned long long mobility, stones; 367 | unsigned long long p1, p2, o1, o2; 368 | int i, j; 369 | p1 = p << hw2_mhw; 370 | p2 = p >> hw_m1; 371 | o1 = o << hw2_mhw; 372 | o2 = o >> hw_m1; 373 | for (i = 0; i < hw2; ++i){ 374 | if (1 & (p >> (hw2 - i - 1))){ 375 | weight_me += eval_param.weight[i]; 376 | me_cnt++; 377 | } else if (1 & (o >> (hw2 - i - 1))){ 378 | weight_op += eval_param.weight[i]; 379 | op_cnt++; 380 | } 381 | } 382 | mobility = check_mobility(p, o); 383 | for (i = 0; i < hw2; ++i) 384 | canput_all += 1 & (mobility >> i); 385 | stones = p | o; 386 | for (i = 0; i < hw; i += 2){ 387 | if (stones ^ confirm_param.num[i / 2]){ 388 | for (j = 0; j < 2; ++j){ 389 | confirm_me += max(0, check_confirm(p, i + j) - 1); 390 | confirm_op += max(0, check_confirm(o, i + j) - 1); 391 | } 392 | } else { 393 | for (j = 1; j < hw - 1; ++j){ 394 | if (1 & (p >> confirm_param.lst[i][j])) 395 | confirm_me++; 396 | else if (1 & (o >> confirm_param.lst[i][j])) 397 | confirm_op++; 398 | } 399 | } 400 | } 401 | confirm_me += 1 & p; 402 | confirm_me += 1 & p2; 403 | confirm_me += 1 & (p >> hw2_mhw); 404 | confirm_me += 1 & (p >> hw2_m1); 405 | confirm_op += 1 & o; 406 | confirm_op += 1 & o2; 407 | confirm_op += 1 & (o >> hw2_mhw); 408 | confirm_op += 1 & (o >> hw2_m1); 409 | for (i = 0; i < hw2; ++i){ 410 | if (1 & (stones >> i)) 411 | continue; 412 | out_me += 1 & (p >> (i + 1)); 413 | out_me += 1 & (p >> (i - 1)); 414 | out_me += 1 & (p >> (i + hw)); 415 | out_me += 1 & (p >> (i - hw)); 416 | out_me += 1 & (p >> (i + hw_p1)); 417 | out_me += 1 & (p >> (i - hw_m1)); 418 | out_me += 1 & (p >> (i + hw_m1)); 419 | out_me += 1 & (p >> (i - hw_p1)); 420 | out_op += 1 & (o >> (i + 1)); 421 | out_op += 1 & (o >> (i - 1)); 422 | out_op += 1 & (o >> (i + hw)); 423 | out_op += 1 & (o >> (i - hw)); 424 | out_op += 1 & (o >> (i + hw_p1)); 425 | out_op += 1 & (o >> (i - hw_m1)); 426 | out_op += 1 & (o >> (i + hw_m1)); 427 | out_op += 1 & (o >> (i - hw_p1)); 428 | } 429 | for (i = 0; i < pattern_num; i++){ 430 | if ((p & eval_param.pat_mask_h_p[i]) == eval_param.pat_mask_h_p[i] && (o & eval_param.pat_mask_h_o[i]) == eval_param.pat_mask_h_o[i]) 431 | pattern_me += eval_param.weight_pat[i]; 432 | if ((p & eval_param.pat_mask_h_p_m[i]) == eval_param.pat_mask_h_p_m[i] && (o & eval_param.pat_mask_h_o_m[i]) == eval_param.pat_mask_h_o_m[i]) 433 | pattern_me += eval_param.weight_pat[i]; 434 | if ((p & eval_param.pat_mask_v_p[i]) == eval_param.pat_mask_v_p[i] && (o & eval_param.pat_mask_v_o[i]) == eval_param.pat_mask_v_o[i]) 435 | pattern_me += eval_param.weight_pat[i]; 436 | if ((p & eval_param.pat_mask_v_p_m[i]) == eval_param.pat_mask_v_p_m[i] && (o & eval_param.pat_mask_v_o_m[i]) == eval_param.pat_mask_v_o_m[i]) 437 | pattern_me += eval_param.weight_pat[i]; 438 | if ((p1 & eval_param.pat_mask_h_p[i]) == eval_param.pat_mask_h_p[i] && (o1 & eval_param.pat_mask_h_o[i]) == eval_param.pat_mask_h_o[i]) 439 | pattern_me += eval_param.weight_pat[i]; 440 | if ((p1 & eval_param.pat_mask_h_p_m[i]) == eval_param.pat_mask_h_p_m[i] && (o1 & eval_param.pat_mask_h_o_m[i]) == eval_param.pat_mask_h_o_m[i]) 441 | pattern_me += eval_param.weight_pat[i]; 442 | if ((p2 & eval_param.pat_mask_v_p[i]) == eval_param.pat_mask_v_p[i] && (o2 & eval_param.pat_mask_v_o[i]) == eval_param.pat_mask_v_o[i]) 443 | pattern_me += eval_param.weight_pat[i]; 444 | if ((p2 & eval_param.pat_mask_v_p_m[i]) == eval_param.pat_mask_v_p_m[i] && (o2 & eval_param.pat_mask_v_o_m[i]) == eval_param.pat_mask_v_o_m[i]) 445 | pattern_me += eval_param.weight_pat[i]; 446 | if ((o & eval_param.pat_mask_h_p[i]) == eval_param.pat_mask_h_p[i] && (p & eval_param.pat_mask_h_o[i]) == eval_param.pat_mask_h_o[i]) 447 | pattern_op += eval_param.weight_pat[i]; 448 | if ((o & eval_param.pat_mask_h_p_m[i]) == eval_param.pat_mask_h_p_m[i] && (p & eval_param.pat_mask_h_o_m[i]) == eval_param.pat_mask_h_o_m[i]) 449 | pattern_op += eval_param.weight_pat[i]; 450 | if ((o & eval_param.pat_mask_v_p[i]) == eval_param.pat_mask_v_p[i] && (p & eval_param.pat_mask_v_o[i]) == eval_param.pat_mask_v_o[i]) 451 | pattern_op += eval_param.weight_pat[i]; 452 | if ((o & eval_param.pat_mask_v_p_m[i]) == eval_param.pat_mask_v_p_m[i] && (p & eval_param.pat_mask_v_o_m[i]) == eval_param.pat_mask_v_o_m[i]) 453 | pattern_op += eval_param.weight_pat[i]; 454 | if ((o1 & eval_param.pat_mask_h_p[i]) == eval_param.pat_mask_h_p[i] && (p1 & eval_param.pat_mask_h_o[i]) == eval_param.pat_mask_h_o[i]) 455 | pattern_op += eval_param.weight_pat[i]; 456 | if ((o1 & eval_param.pat_mask_h_p_m[i]) == eval_param.pat_mask_h_p_m[i] && (p1 & eval_param.pat_mask_h_o_m[i]) == eval_param.pat_mask_h_o_m[i]) 457 | pattern_op += eval_param.weight_pat[i]; 458 | if ((o2 & eval_param.pat_mask_v_p[i]) == eval_param.pat_mask_v_p[i] && (p2 & eval_param.pat_mask_v_o[i]) == eval_param.pat_mask_v_o[i]) 459 | pattern_op += eval_param.weight_pat[i]; 460 | if ((o2 & eval_param.pat_mask_v_p_m[i]) == eval_param.pat_mask_v_p_m[i] && (p2 & eval_param.pat_mask_v_o_m[i]) == eval_param.pat_mask_v_o_m[i]) 461 | pattern_op += eval_param.weight_pat[i]; 462 | } 463 | double weight_proc, canput_proc, confirm_proc, open_proc, out_proc, pattern_proc; 464 | weight_proc = weight_me / max(1, me_cnt) - weight_op / max(1, op_cnt); 465 | canput_proc = (double)(canput_all - canput) / max(1, canput_all) - (double)canput / max(1, canput_all); 466 | confirm_proc = (double)confirm_me / max(1, confirm_me + confirm_op) - (double)confirm_op / max(1, confirm_me + confirm_op); 467 | open_proc = 1.0 - eval_param.open_val_threshold * open_val; 468 | out_proc = -(double)out_me / max(1, out_me + out_op) + (double)out_op / max(1, out_me + out_op); 469 | pattern_proc = pattern_me - pattern_op; 470 | return weight_proc * eval_param.weight_weight + 471 | canput_proc * eval_param.canput_weight + 472 | confirm_proc * eval_param.confirm_weight + 473 | open_proc * eval_param.open_weight + 474 | out_proc * eval_param.out_weight + 475 | pattern_proc * eval_param.pattern_weight; 476 | } 477 | 478 | inline int end_game(const unsigned long long p, const unsigned long long o){ 479 | int res = 0, i; 480 | for (i = 0; i < hw2; ++i){ 481 | res += 1 & (p >> i); 482 | res -= 1 & (o >> i); 483 | } 484 | //return (double)res * 1000.0; 485 | if (res > 0) 486 | return 1; 487 | else if (res == 0) 488 | return 0; 489 | else 490 | return -1; 491 | } 492 | 493 | inline int calc_open(unsigned long long stones, unsigned long long rev){ 494 | int i, res = 0; 495 | for (i = 0; i < hw2; ++i){ 496 | if (1 & (rev >> i)){ 497 | res += 1 - (1 & (stones >> (i + 1))); 498 | res += 1 - (1 & (stones >> (i - 1))); 499 | res += 1 - (1 & (stones >> (i + hw))); 500 | res += 1 - (1 & (stones >> (i - hw))); 501 | res += 1 - (1 & (stones >> (i + hw_p1))); 502 | res += 1 - (1 & (stones >> (i - hw_m1))); 503 | res += 1 - (1 & (stones >> (i + hw_m1))); 504 | res += 1 - (1 & (stones >> (i - hw_p1))); 505 | } 506 | } 507 | return res; 508 | } 509 | 510 | int cmp(grid_priority p, grid_priority q){ 511 | return p.priority > q.priority; 512 | } 513 | 514 | inline int pop_count_ull(unsigned long long x){ 515 | x = x - ((x >> 1) & 0x5555555555555555); 516 | x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); 517 | x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F; 518 | x = (x * 0x0101010101010101) >> 56; 519 | return (int)x; 520 | } 521 | 522 | void expand(const unsigned long long p, const unsigned long long o, const unsigned long long mobility){ 523 | unsigned long long np, no; 524 | int i; 525 | pair grid; 526 | for (i = 0; i < hw2; ++i){ 527 | if (1 & (mobility >> i)){ 528 | np = move(p, o, i); 529 | no = (np ^ o) & o; 530 | grid.first = no; 531 | grid.second = np; 532 | search_param.win_rate[grid].seen = true; 533 | search_param.win_rate[grid].n = 0; 534 | search_param.win_rate[grid].m = 0; 535 | //search_param.win_rate[grid].val = -evaluate(no, np, n_canput, calc_open(np | no, np ^ p)); 536 | } 537 | } 538 | } 539 | 540 | int playout(const unsigned long long p, const unsigned long long o, const int skip_cnt){ 541 | if (skip_cnt == 2) 542 | return -end_game(p, o); 543 | unsigned long long mobility = check_mobility(p, o); 544 | int n_canput = pop_count_ull(mobility); 545 | if (n_canput == 0) 546 | return -playout(o, p, skip_cnt + 1); 547 | unsigned long long np, no; 548 | int i; 549 | vector lst; 550 | for (i = 0; i < hw2; ++i){ 551 | if (1 & (mobility >> i)){ 552 | np = move(p, o, i); 553 | no = (np ^ o) & o; 554 | grid_priority tmp; 555 | tmp.p = np; 556 | tmp.o = no; 557 | tmp.priority = -evaluate(no, np, n_canput, calc_open(np | no, np ^ p)) + myrandom() * 0.2 - 0.1; 558 | lst.push_back(tmp); 559 | } 560 | } 561 | double max_score = -inf; 562 | for (i = 0; i < n_canput; i++){ 563 | if (lst[i].priority > max_score){ 564 | max_score = lst[i].priority; 565 | no = lst[i].o; 566 | np = lst[i].p; 567 | } 568 | } 569 | return -playout(no, np, 0); 570 | } 571 | 572 | int mcts(const unsigned long long p, const unsigned long long o, const int skip_cnt){ 573 | pair grid_now; 574 | int res; 575 | grid_now.first = p; 576 | grid_now.second = o; 577 | ++search_param.win_rate[grid_now].n; 578 | if (skip_cnt == 2){ 579 | res = -end_game(p, o); 580 | search_param.win_rate[grid_now].m += res; 581 | return res; 582 | } 583 | pair grid_new; 584 | unsigned long long mobility = check_mobility(p, o); 585 | int n_canput = pop_count_ull(mobility); 586 | if (n_canput == 0){ 587 | res = -playout(o, p, skip_cnt + 1); 588 | search_param.win_rate[grid_now].m += res; 589 | return res; 590 | } 591 | if (search_param.win_rate[grid_now].n == expand_threshold) 592 | expand(p, o, mobility); 593 | unsigned long long np, no; 594 | vector lst; 595 | int i; 596 | for (i = 0; i < hw2; ++i){ 597 | if (1 & (mobility >> i)){ 598 | np = move(p, o, i); 599 | no = (np ^ o) & o; 600 | grid_new.first = no; 601 | grid_new.second = np; 602 | grid_priority tmp; 603 | tmp.p = np; 604 | tmp.o = no; 605 | if (search_param.win_rate[grid_new].seen){ 606 | if (search_param.win_rate[grid_new].n > 0) 607 | tmp.priority = (double)search_param.win_rate[grid_new].m / search_param.win_rate[grid_new].n + bias * sqrt(log((double)search_param.win_rate[grid_now].n) / (double)search_param.win_rate[grid_new].n); //bias * search_param.win_rate[grid].val; 608 | else 609 | tmp.priority = inf; 610 | } else 611 | tmp.priority = myrandom(); 612 | lst.push_back(tmp); 613 | } 614 | } 615 | double max_priority = -inf; 616 | for (i = 0; i < n_canput; ++i){ 617 | if (lst[i].priority > max_priority){ 618 | max_priority = lst[i].priority; 619 | grid_new.first = lst[i].o; 620 | grid_new.second = lst[i].p; 621 | } 622 | } 623 | if (search_param.win_rate[grid_new].seen) 624 | res = -mcts(grid_new.first, grid_new.second, 0); 625 | else 626 | res = -playout(grid_new.first, grid_new.second, 0); 627 | search_param.win_rate[grid_now].m += res; 628 | return res; 629 | } 630 | 631 | double map_double(double s, double e, double x){ 632 | return s + (e - s) * x; 633 | } 634 | 635 | int main(int argc, char* argv[]){ 636 | int ansy, ansx, outy, outx, i, canput, former_depth = 7, former_vacant = hw2 - 4; 637 | double score, max_score; 638 | double weight_weight_s, canput_weight_s, confirm_weight_s, stone_weight_s, open_weight_s, out_weight_s, weight_weight_e, canput_weight_e, confirm_weight_e, stone_weight_e, open_weight_e, out_weight_e; 639 | unsigned long long in_mobility; 640 | unsigned long long p, o, np, no; 641 | pair grid; 642 | int elem; 643 | int action_count; 644 | double game_ratio; 645 | int vacant_cnt, ai_player; 646 | 647 | init(argc, argv); 648 | cin >> ai_player; 649 | cin >> search_param.tl; 650 | 651 | if (ai_player == 0){ 652 | cerr << "AI initialized AI is Black" << endl; 653 | }else{ 654 | cerr << "AI initialized AI is White" << endl; 655 | } 656 | while (true){ 657 | outy = -1; 658 | outx = -1; 659 | vacant_cnt = 0; 660 | p = 0; 661 | o = 0; 662 | in_mobility = 0; 663 | canput = 0; 664 | for (i = 0; i < hw2; ++i){ 665 | cin >> elem; 666 | vacant_cnt += (int)(elem == -1 || elem == 2); 667 | in_mobility <<= 1; 668 | in_mobility += (int)(elem == 2); 669 | canput += (int)(elem == 2); 670 | p <<= 1; 671 | o <<= 1; 672 | p += (int)(elem == ai_player); 673 | o += (int)(elem == 1 - ai_player); 674 | } 675 | former_vacant = vacant_cnt; 676 | outy = -1; 677 | outx = -1; 678 | search_param.strt = tim(); 679 | game_ratio = (double)(hw2 - vacant_cnt) / hw2; 680 | eval_param.weight_weight = map_double(eval_param.weight_se[0], eval_param.weight_se[1], game_ratio); 681 | eval_param.canput_weight = map_double(eval_param.weight_se[2], eval_param.weight_se[3], game_ratio); 682 | eval_param.confirm_weight = map_double(eval_param.weight_se[4], eval_param.weight_se[5], game_ratio); 683 | eval_param.open_weight = map_double(eval_param.weight_se[6], eval_param.weight_se[7], game_ratio); 684 | eval_param.out_weight = map_double(eval_param.weight_se[8], eval_param.weight_se[9], game_ratio); 685 | eval_param.open_val_threshold = map_double(eval_param.weight_se[10], eval_param.weight_se[11], game_ratio); 686 | eval_param.pattern_weight = map_double(eval_param.weight_se[12], eval_param.weight_se[13], game_ratio); 687 | for (i = 0; i < hw2; i++) 688 | eval_param.weight[i] = map_double(eval_param.weight_s[i], eval_param.weight_e[i], game_ratio); 689 | search_param.playout_cnt = 0; 690 | search_param.win_rate.clear(); 691 | search_param.win_rate[make_pair(p, o)].seen = true; 692 | expand(p, o, in_mobility); 693 | while (tim() - search_param.strt < search_param.tl){ 694 | ++search_param.playout_cnt; 695 | mcts(p, o, 0); 696 | } 697 | max_score = -inf; 698 | for (i = 0; i < hw2; i++){ 699 | if (1 & (in_mobility >> i)){ 700 | np = move(p, o, i); 701 | no = (np ^ o) & o; 702 | grid.first = no; 703 | grid.second = np; 704 | score = (double)search_param.win_rate[grid].m / max(1, search_param.win_rate[grid].n); 705 | //cerr << search_param.win_rate[grid].n << " " << score << " "; 706 | cerr << search_param.win_rate[grid].n << " "; 707 | if (score > max_score){ 708 | max_score = score; 709 | ansy = (hw2 - i - 1) / hw; 710 | ansx = (hw2 - i - 1) % hw; 711 | } 712 | } 713 | } 714 | cerr << endl; 715 | outy = ansy; 716 | outx = ansx; 717 | cerr << ansy << ansx << " " << max_score << " " << search_param.playout_cnt << " time " << tim() - search_param.strt << endl; 718 | cout << outy << " " << outx << endl; 719 | } 720 | return 0; 721 | } --------------------------------------------------------------------------------