コンテンツにスキップ

組み込みの道具

あなたの担当 bot から呼んで使う道具です。計算そのものはエンジンと同じ実装が引き受けます。

import は要りません。update の中で、いつでも使えます。 (import は、math も含めて書けませんmath は、最初から使えます)

関数返すもの使いどころ
angle_to(ax, ay, bx, by)度(0〜359.99)a から b を向く角度
distance(ax, ay, bx, by)マス2 点の距離
angle_diff(a, b)度(−180〜180)2 つの向きの差(最短の回りかた)
line_of_sight(grid, ax, ay, bx, by)真偽2 点のあいだに壁がないか
find_path_bfs(grid, start, goal)マスのリスト最短経路(行けなければ []
find_path_astar(grid, start, goal)マスのリスト同じ。A* 版
predict_lead(enemy, 弾の速さ, 自分x, 自分y)(x, y)動く敵に当てる狙い点
clamp(v, lo, hi)値を範囲におさめる
stable_sort(リスト, key=関数)リスト順序が安定した並べかえ
rand() / randint(a, b) / choice(リスト)数・要素乱数(試合ごとに同じ目が出る)
print(...)実行ログに出す(対戦画面の下に出る)

座標はマスで、画面の左上が (0, 0) です。下に行くほど y が大きくなります。

want = angle_to(state.me.x, state.me.y, state.enemy.x, state.enemy.y)

自分から敵を向く角度が、0〜359.99 の度で返ります。0 が右で、時計回りに増えます。 steer に、そのまま入れられます。

d = distance(state.me.x, state.me.y, state.enemy.x, state.enemy.y)

マス単位の距離です。「近づく」「離れる」の判断に使います。

diff = angle_diff(want, state.me.angle) # want - me.angle を、-180〜180 に収める

「あと何度まわればいいか」が分かります。正なら時計回り、負なら反時計回りです。 abs(diff) < 5 なら「ほぼ向きが合っている」と言えます。

want - me.angle をそのまま引き算してはいけません。 350 度と 10 度の差は 20 度ですが、引き算すると 340 になります。

line_of_sight — 壁ごしに見えるか

Section titled “line_of_sight — 壁ごしに見えるか”
見える = line_of_sight(state.map.grid, me.x, me.y, en.x, en.y)

あいだに壁(木箱・鉄)がなければ True です。水たまりは、弾が上を通るので、視線をさえぎりません。 くわしい計算は 視線判定と DDA にあります。

find_path_bfs / find_path_astar — 道さがし

Section titled “find_path_bfs / find_path_astar — 道さがし”
path = find_path_bfs(state.map.grid, (me.grid_x, me.grid_y), (en.grid_x, en.grid_y))

スタートとゴールはマスの番号 (x, y) で渡します。返るのは、通るマスの番号のリストです。 path[0] は、いま自分がいるマスなので、進むべきは path[1] です。行けないときは [] です。

重い道具です。 広げたマスの数だけ、命令数が使われます。毎回探し直さず、覚えておきましょう。 → 経路探索と計算量

tx, ty = predict_lead(state.enemy, 8.0, state.me.x, state.me.y)
want = angle_to(state.me.x, state.me.y, tx, ty)

弾が届くころに敵がいる場所 (tx, ty) を返します。まっすぐ進む敵なら、そこを向いて撃てば当たります。 向きを変えつづける敵には、効かないことがあります(動く敵に当てる)。 当てられない場合は、敵のいまの位置が返ります。 中身の計算は 偏差射撃 にあります。

rand() # 0.0 以上 1.0 未満
randint(1, 6) # 1 以上 6 以下の整数
choice(["a", "b", "c"])

random モジュールは使えません。同じ試合なら、同じ目が出ます。 試合を再生し直しても、同じ結果になるためです。 理由は 決定論と固定小数点 にあります。

print("いまの距離", distance(state.me.x, state.me.y, state.enemy.x, state.enemy.y))

対戦画面の下の実行ログに出ます。値がおかしいときに、確かめるのに使います。