游戏对抗中的路径与搜索

公司技术节搞了个 tank ai 比赛, 喜获冠军, 奖品是5000块的大疆无人机.
这也是我第一次写AI机器人. 一些技术分享一下.

绕石转圈

这里写图片描述
figure 绕石头顺时针转圈

当场上只有自己时, 对手会随机位置带护盾复活, 所以想到绕石转圈, 既能躲又能打. 约定 O O 为石头圆心, r 为石头半径, A A 为tank圆心.
做法有两个:

方程组求切点

设切点为B.

(1){0=OBABr2=(B.xO.x)2+(B.yO.y)2

使用scipy.optimize import fsolve求解.
问题是切点有两个, 我们又想按照固定的顺时针 方向走,那就必须分情况讨论, 选择合适的迭代初始点 x0 x 0 :

def get_point_of_contact(O: Point, A: Point, r: float):
    """
    拿切点
    :param O: 圆心
    :param A: 圆外一点
    :param r: 圆的半径
    :return: 切点坐标
    """
    x0 = (A.x, A.y)
    # 第一象限
    if A.x > O.x and A.y < O.y:
        x0 = (O.x, O.y - 1)
    # 第二象限
    elif A.x < O.x and A.y < O.y:
        x0 = (O.x - 1, O.y)
    # 第三象限
    elif A.x < O.x and A.y > O.y:
        x0 = (O.x, O.y + 1)
    # 第四象限
    else:
        x0 = (O.x + 1, O.y)
    x, y = fsolve(func=equations, x0=x0, args=(O, A, r))
    return Point(x, y)

走到石头后沿垂线行进

走到石头后计算 OA O A → 在地图中的角度, 然后 +90 度为接下来一步(100 ms)的行进方向.
该方法听起来很美好, 不用解二次方程组求切点. 但试验下来就会发现, 因为tank走了一步, 会远离石头, 那么接下来的垂线方向与真实的切线方向就有偏差了. 多走几步, 就是棒棒糖花纹这样的效果:
这里写图片描述
figure 像棒棒糖的花纹一样, 路径会逐渐远离圆心

路径搜索

用来逃生.
这里写图片描述
figure 搜索躲子弹效果演示

思想

这里写图片描述
figure ppt截图

代码

记忆化回溯逃生的代码见下:

# state_arr[step][x][y] 在step步后, 若tank位于(x,y)位置, 是否存在一条生路
# -> ,↓,←,↑,keep
DIRECTION_INDEX = [(1, 0), (0, 1), (-1, 0), (0, -1), (0, 0)]
def _search_path(self, map: Map, state_arr, x: int, y: int, step: int, path: List[float]) -> int:
    # 找到路啦
    if step > MAX_STEP:
        return SAFE
    # 记忆化搜索
    if state_arr[step][OFFSET_AXIS + x][OFFSET_AXIS + y] != UN_REACHED:
        return state_arr[step][OFFSET_AXIS + x][OFFSET_AXIS + y]
    # 越界/障碍物/是否会被子弹打中
    if not is_valid or not is_safe:
        state_arr[step][OFFSET_AXIS + x][OFFSET_AXIS + y] = DANGER
        return DANGER
    final_state = DANGER
    for i in range(len(DIRECTION_INDEX)):
        # 动态评估优先的逃生方向
        delta_x,delta_y = get_best_survive_direction(DIRECTION_INDEX)
        state = self._search_path(map, state_arr, x + delta_x, y + delta_y, step + 1, get_new_path(delta_x,delta_y))
        if state == SAFE:
            final_state = SAFE
    state_arr[step][OFFSET_AXIS + x][OFFSET_AXIS + y] = final_state
    return final_state

打出来的日志是这个样子:

2018-04-20 12:28:07,937 - yichu_survive_utils - INFO - ('survive_angle_path is: ', [3.141592653589793, 4.71238898038469, 3.141592653589793, 4.71238898038469, -1, -1, -1, -1, -1, -1, -1, -1, 4.71238898038469])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值