見えない敵を探す
やりたいこと
Section titled “やりたいこと”敵が壁のむこうにいて見えないときは、道をさがして近づきます。見えたら、止まって撃ちます。
Python で書く(そのまま動く bot)
Section titled “Python で書く(そのまま動く bot)”path = []残り = 0
def update(state): global path, 残り me = state.me en = state.enemy
want = angle_to(me.x, me.y, en.x, en.y) 見える = line_of_sight(state.map.grid, me.x, me.y, en.x, en.y)
# 見えているあいだは、止まって狙って撃つ if 見える: 合っている = abs(angle_diff(want, me.angle)) < 5 return {"drive": "stop", "steer": want, "fire": 合っている, "barrier": False}
# 見えないとき:10 回に 1 回だけ、道を探し直す if 残り <= 0 or len(path) < 2: path = find_path_bfs(state.map.grid, (me.grid_x, me.grid_y), (en.grid_x, en.grid_y)) 残り = 10 残り = 残り - 1
if len(path) < 2: return {"drive": "stop", "steer": me.angle, "fire": False, "barrier": False}
# すでに着いたマスは、道からはずす nx, ny = path[1] if me.grid_x == nx and me.grid_y == ny: path = path[1:] if len(path) < 2: return {"drive": "stop", "steer": me.angle, "fire": False, "barrier": False} nx, ny = path[1]
# マスの中心(+ 0.5)へ向かう go = angle_to(me.x, me.y, nx + 0.5, ny + 0.5) return {"drive": "forward", "steer": go, "fire": False, "barrier": False}- まず
line_of_sight。 見えているなら、道をさがす必要はありません - 見えないときだけ
find_path_bfsで、通るマスのリストを出します path[0]はいま自分がいるマスです。進む先はpath[1]です- マスの中心は
(x + 0.5, y + 0.5)。+ 0.5を忘れると、マスの角に向かってしまいます
アリーナの CPU「スナイパー」(動かずに、見えた相手だけを撃つ)と、いつものマップで 40 試合(左右を入れかえて 20 マップぶん)戦わせました。
| 勝ち | |
|---|---|
| 敵のほうを向いて、その場から撃つだけ(敵のほうを向く、向きの許容 3 度) | 6 / 40 |
| この bot(見えないときは道を探して近づく) | 34 / 40 |
「CPU カード」の「くせ」(あいだに壁があるあいだは撃ってこない)を知って、近づいて見えるようにする作戦です。
命令数を軽くする
Section titled “命令数を軽くする”道さがしは重い処理です。毎回やると、そのぶん命令数を使います。
そこで、10 回に 1 回だけ探し直して、あとは覚えておきます。
path と 残り が、その覚えておく変数です。global の宣言を忘れると、毎回まっさらになります(bot のかたち)。
命令数の測りかたと、書き方による違いは、経路探索と計算量にあります。
試してみよう
Section titled “試してみよう”10を1に変えて、毎回探し直してみましょう。命令数のメーターは、どう変わるでしょうか(命令数の上限)find_path_bfsをfind_path_astarに変えてみましょう。違いは経路探索と計算量にあります
うまくいかないとき
Section titled “うまくいかないとき”- 同じところをぐるぐる回る。
path[1]が、もう着いたマスのままになっていませんか - 道が見つからない(
[])。 敵と自分のあいだが、壁でふさがれているのかもしれません。そのときは、止まって待ちます