はね返りで撃つ
やりたいこと
Section titled “やりたいこと”まっすぐには見えない敵に、壁ではね返らせて弾を届かせます。
上の壁を鏡だと思います。敵を、鏡のむこうに映します。 映った敵(鏡像)をまっすぐ狙うと、弾は壁で折れ曲がって、本物の敵に届きます。
上の壁の面は y = 1.0 にあります。横の壁なら x を折り返します。
くわしい説明と図は跳弾のしくみにあります。
Python で書く(そのまま動く bot)
Section titled “Python で書く(そのまま動く bot)”def update(state): me = state.me en = state.enemy grid = state.map.grid
# まっすぐ見えるなら、ふつうに撃つ if line_of_sight(grid, me.x, me.y, en.x, en.y): want = angle_to(me.x, me.y, en.x, en.y) 合っている = abs(angle_diff(want, me.angle)) < 3 return {"drive": "stop", "steer": want, "fire": 合っている, "barrier": False}
# 見えないとき:上の壁(y = 1.0)を鏡にして、敵の鏡像をねらう mx = en.x my = 2 * 1.0 - en.y
# 自分 → 鏡像 の線が、壁 y = 1.0 と交わる点(はね返る場所) t = (me.y - 1.0) / (me.y - my) px = me.x + (mx - me.x) * t py = 1.5 # 壁のすぐ手前(マスの中)で調べる
# 2 本の線が、どちらも通っているときだけ撃つ 通る = line_of_sight(grid, me.x, me.y, px, py) and line_of_sight(grid, px, py, en.x, en.y)
want = angle_to(me.x, me.y, mx, my) 合っている = abs(angle_diff(want, me.angle)) < 3 return {"drive": "stop", "steer": want, "fire": 通る and 合っている, "barrier": False}- 見えるなら、ふつうに撃ちます。 はね返りは、まっすぐ届かないときの手段です
- 見えないときは、敵の鏡像
(mx, my)を計算します - はね返る場所
(px, py)を出します - 2 本の線(自分 → 反射点、反射点 → 敵)を
line_of_sightで調べて、どちらも通るときだけ撃ちます
広場の真ん中に縦の鉄の壁(x = 9 の列、y = 3 〜 13)を立てて、そのむこう(x = 15)にいる止まっている敵を撃たせました。
| 撃った弾 | 結果 | |
|---|---|---|
| この bot(上の壁で 1 回はね返らせる) | 5 発 | 3 発が敵に当たった(敵は倒れた) |
| 敵のほうを向く(そのまま撃つ) | 4 発 | 敵には 0 発。はね返った弾が自分に 3 発当たって、負けた |
試してみよう
Section titled “試してみよう”- 下の壁(
y = 14.0)や、横の壁(x = 1.0、x = 19.0)でも、同じ考えかたで書けます。式の2 * 1.0の部分を、壁の位置に変えます - 「はね返りがうまくいく場面」を、試合画面を 1 コマずつ見て探してみましょう
うまくいかないとき
Section titled “うまくいかないとき”- 当たらない。 敵は動いています。鏡像も、先まわりした位置(
predict_lead)にできるでしょうか - 自爆する。 壁に近すぎる位置から撃っていませんか
- 計算の中身 → 跳弾のしくみ
- 縮小エリアで生き残る