aW1wb3J0IHN5cwoKIyDnsKHmmJPjgrLjg7zjg6Djg4Tjg6rjg7zjg47jg7zjg4kKY2xhc3MgTm9kZToKICAgIGRlZiBfX2luaXRfXyhzZWxmLCB2YWx1ZT1Ob25lLCBjaGlsZHJlbj1Ob25lLCBuYW1lPScnKToKICAgICAgICBzZWxmLnZhbHVlID0gdmFsdWUKICAgICAgICBzZWxmLmNoaWxkcmVuID0gY2hpbGRyZW4gb3IgW10KICAgICAgICBzZWxmLm5hbWUgPSBuYW1lCgojIENTMuODqeOCpuODs+ODieaIpueVpeOBruewoeaYk+ODhOODquODvOani+eviQojIOODrOODmeODqzE6IFTlgbTjga7ooYzli5UgLSBSdXNoIEEsIFJ1c2ggQiwgU3BsaXQKIyDjg6zjg5njg6syOiBDVOWBtOOBruWvvuW/nCAtIERlZmVuZCBBIGhlYXZ5LCBEZWZlbmQgQiBoZWF2eSwgQmFsYW5jZWQKIyDokYk6IOS7ruaDs+eahOOCueOCs+OCoiAoVOWBtOOBjOmrmOOBhOOBu+OBqeiJr+OBhCkKZGVmIGJ1aWxkX3RyZWUoKToKICAgICMg54q25rOB44Gr5b+c44GY44Gm44GT44GT44KS5aSJ5pu077yI5L6LOiDos4fph5HlsJHjgarjgYTmmYLjga/jgrnjgrPjgqLoqr/mlbTvvIkKICAgIGxlYXZlcyA9IFsKICAgICAgICBOb2RlKDgwLCBuYW1lPSdXaW4gdnMgRGVmIEEnKSwgTm9kZSgyMCwgbmFtZT0nTG9zcyB2cyBEZWYgQicpLCBOb2RlKDUwLCBuYW1lPSdUaWUgdnMgQmFsJyksCiAgICAgICAgTm9kZSgzMCwgbmFtZT0nTG9zcyB2cyBEZWYgQScpLCBOb2RlKDcwLCBuYW1lPSdXaW4gdnMgRGVmIEInKSwgTm9kZSg1MCwgbmFtZT0nVGllIHZzIEJhbCcpLAogICAgICAgIE5vZGUoNjAsIG5hbWU9J1dpbiB2cyBEZWYgQScpLCBOb2RlKDYwLCBuYW1lPSdXaW4gdnMgRGVmIEInKSwgTm9kZSg0MCwgbmFtZT0nTG9zcyB2cyBCYWwnKQogICAgXQogICAgCiAgICBjdF9yZXNwb25zZXMgPSBbCiAgICAgICAgTm9kZShOb25lLCBsZWF2ZXNbMDozXSwgJ0RlZmVuZCBBIGhlYXZ5JyksCiAgICAgICAgTm9kZShOb25lLCBsZWF2ZXNbMzo2XSwgJ0RlZmVuZCBCIGhlYXZ5JyksCiAgICAgICAgTm9kZShOb25lLCBsZWF2ZXNbNjo5XSwgJ0JhbGFuY2VkJykKICAgIF0KICAgIAogICAgcm9vdCA9IE5vZGUoTm9uZSwgWwogICAgICAgIE5vZGUoTm9uZSwgY3RfcmVzcG9uc2VzLCAnUnVzaCBBJyksCiAgICAgICAgTm9kZShOb25lLCBjdF9yZXNwb25zZXMsICdSdXNoIEInKSwKICAgICAgICBOb2RlKE5vbmUsIGN0X3Jlc3BvbnNlcywgJ1NwbGl0JykKICAgIF0sICdUIFN0cmF0ZWdpZXMnKQogICAgCiAgICByZXR1cm4gcm9vdAoKIyBNaW5pbWF4IHdpdGggQWxwaGEtQmV0YSBQcnVuaW5nCmRlZiBtaW5pbWF4KG5vZGUsIGRlcHRoLCBhbHBoYSwgYmV0YSwgbWF4aW1pemluZyk6CiAgICBpZiBub2RlLnZhbHVlIGlzIG5vdCBOb25lOiAgIyDokYnjg47jg7zjg4kKICAgICAgICByZXR1cm4gbm9kZS52YWx1ZQogICAgCiAgICBpZiBtYXhpbWl6aW5nOiAgIyBU5YG0IChNYXgpCiAgICAgICAgbWF4X2V2YWwgPSAtc3lzLm1heHNpemUKICAgICAgICBmb3IgY2hpbGQgaW4gbm9kZS5jaGlsZHJlbjoKICAgICAgICAgICAgZXZhbF92YWwgPSBtaW5pbWF4KGNoaWxkLCBkZXB0aCAtIDEsIGFscGhhLCBiZXRhLCBGYWxzZSkKICAgICAgICAgICAgbWF4X2V2YWwgPSBtYXgobWF4X2V2YWwsIGV2YWxfdmFsKQogICAgICAgICAgICBhbHBoYSA9IG1heChhbHBoYSwgZXZhbF92YWwpCiAgICAgICAgICAgIGlmIGJldGEgJmx0Oz0gYWxwaGE6CiAgICAgICAgICAgICAgICBicmVhayAgIyDmnp3liIjjgooKICAgICAgICByZXR1cm4gbWF4X2V2YWwKICAgIGVsc2U6ICAjIENU5YG0IChNaW4pCiAgICAgICAgbWluX2V2YWwgPSBzeXMubWF4c2l6ZQogICAgICAgIGZvciBjaGlsZCBpbiBub2RlLmNoaWxkcmVuOgogICAgICAgICAgICBldmFsX3ZhbCA9IG1pbmltYXgoY2hpbGQsIGRlcHRoIC0gMSwgYWxwaGEsIGJldGEsIFRydWUpCiAgICAgICAgICAgIG1pbl9ldmFsID0gbWluKG1pbl9ldmFsLCBldmFsX3ZhbCkKICAgICAgICAgICAgYmV0YSA9IG1pbihiZXRhLCBldmFsX3ZhbCkKICAgICAgICAgICAgaWYgYmV0YSAmbHQ7PSBhbHBoYToKICAgICAgICAgICAgICAgIGJyZWFrICAjIOaeneWIiOOCigogICAgICAgIHJldHVybiBtaW5fZXZhbAoKIyDlrp/ooYzkvosKdHJlZSA9IGJ1aWxkX3RyZWUoKQpiZXN0X3ZhbHVlID0gbWluaW1heCh0cmVlLCAzLCAtc3lzLm1heHNpemUsIHN5cy5tYXhzaXplLCBUcnVlKQpwcmludChmJnF1b3Q7VOWBtOOBruacgOmBqeWApDoge2Jlc3RfdmFsdWV9JnF1b3Q7KQoKIyDmnIDpganmiKbnlaXjga7pgbjmip4KYmVzdF9tb3ZlID0gTm9uZQpiZXN0X3Njb3JlID0gLXN5cy5tYXhzaXplCmZvciBjaGlsZCBpbiB0cmVlLmNoaWxkcmVuOgogICAgc2NvcmUgPSBtaW5pbWF4KGNoaWxkLCAyLCAtc3lzLm1heHNpemUsIHN5cy5tYXhzaXplLCBGYWxzZSkKICAgIGlmIHNjb3JlICZndDsgYmVzdF9zY29yZToKICAgICAgICBiZXN0X3Njb3JlID0gc2NvcmUKICAgICAgICBiZXN0X21vdmUgPSBjaGlsZC5uYW1lCgpwcmludChmJnF1b3Q75pyA6YGp5oim55WlOiB7YmVzdF9tb3ZlfSAo44K544Kz44KiOiB7YmVzdF9zY29yZX0pJnF1b3Q7KQ==
import sys
# 簡易ゲームツリーノード
class Node:
def __init__(self, value=None, children=None, name=''):
self.value = value
self.children = children or []
self.name = name
# CS2ラウンド戦略の簡易ツリー構築
# レベル1: T側の行動 - Rush A, Rush B, Split
# レベル2: CT側の対応 - Defend A heavy, Defend B heavy, Balanced
# 葉: 仮想的スコア (T側が高いほど良い)
def build_tree():
# 状況に応じてここを変更(例: 資金少ない時はスコア調整)
leaves = [
Node(80, name='Win vs Def A'), Node(20, name='Loss vs Def B'), Node(50, name='Tie vs Bal'),
Node(30, name='Loss vs Def A'), Node(70, name='Win vs Def B'), Node(50, name='Tie vs Bal'),
Node(60, name='Win vs Def A'), Node(60, name='Win vs Def B'), Node(40, name='Loss vs Bal')
]
ct_responses = [
Node(None, leaves[0:3], 'Defend A heavy'),
Node(None, leaves[3:6], 'Defend B heavy'),
Node(None, leaves[6:9], 'Balanced')
]
root = Node(None, [
Node(None, ct_responses, 'Rush A'),
Node(None, ct_responses, 'Rush B'),
Node(None, ct_responses, 'Split')
], 'T Strategies')
return root
# Minimax with Alpha-Beta Pruning
def minimax(node, depth, alpha, beta, maximizing):
if node.value is not None: # 葉ノード
return node.value
if maximizing: # T側 (Max)
max_eval = -sys.maxsize
for child in node.children:
eval_val = minimax(child, depth - 1, alpha, beta, False)
max_eval = max(max_eval, eval_val)
alpha = max(alpha, eval_val)
if beta <= alpha:
break # 枝刈り
return max_eval
else: # CT側 (Min)
min_eval = sys.maxsize
for child in node.children:
eval_val = minimax(child, depth - 1, alpha, beta, True)
min_eval = min(min_eval, eval_val)
beta = min(beta, eval_val)
if beta <= alpha:
break # 枝刈り
return min_eval
# 実行例
tree = build_tree()
best_value = minimax(tree, 3, -sys.maxsize, sys.maxsize, True)
print(f"T側の最適値: {best_value}")
# 最適戦略の選択
best_move = None
best_score = -sys.maxsize
for child in tree.children:
score = minimax(child, 2, -sys.maxsize, sys.maxsize, False)
if score > best_score:
best_score = score
best_move = child.name
print(f"最適戦略: {best_move} (スコア: {best_score})")