FPS Arena의 봇은 일곱 명이 같은 맵에 있어도 완전히 남남이었습니다. 서로의 시야를 전혀 쓰지 않아서, 한 명이 죽어 나가는 동안 5m 옆의 아군은 반대쪽을 보고 있었습니다.

사람이 팀으로 하는 게임에서 봇만 개인전을 하면 그건 난이도가 아니라 다른 게임입니다.

본 것만 공유한다

팀 단위 공유 기억을 만들었습니다. 봇이 적을 보면 위치와 시각을 팀에 올리고, 못 본 봇도 그 정보로 움직입니다. 아군이 죽은 자리도 공유합니다 — 총알이 어디서 날아왔는지 아는 유일한 단서일 때가 많으니까요.

여기에 규칙을 하나 못박아 뒀습니다.

담기는 건 "봤다" 뿐이다. 아무도 못 본 적의 위치는 절대 안 들어간다.

그걸 넣는 순간 봇은 벽을 뚫어보는 존재가 됩니다. 난이도가 아니라 사기가 되고, 지면 억울하기만 합니다. 정보를 공유하는 것과 정보를 만들어 주는 것은 완전히 다른 일입니다.

그래서 남이 준 정보로는 조준 대상을 세우지 않습니다. 위치만 받아서 "가 본다" 까지가 한계입니다.

역할을 나눈다

같은 적에게 둘이 똑같이 정면으로 붙으면 그냥 둘 다 죽습니다. 이미 아군이 붙어 있으면 나는 옆으로 돌게 했습니다. 정면을 묶어 주는 쪽이 있으니까 측면이 성립하는 것이고, 그게 분대가 하는 유일한 일입니다.

방향은 인스턴스 ID 로 갈랐습니다. 안 그러면 둘이 같은 쪽으로 돌아서 결국 또 나란히 서게 됩니다.

그리고 아무도 못 맞히게 됐다

돌려 보니 측면 기동은 잘 돌았습니다. 20초에 63회.

그런데 같은 로그에 이게 있었습니다.

발사194260
명중4318
명중률22%7%

봇들이 총알을 세 배로 낭비하고 있었습니다.

원인은 제가 반나절 전에 직접 만든 규칙이었습니다. 이 게임에는 움직이면서 쏘면 탄이 퍼지는 규칙이 있고, 그건 봇에게도 똑같이 적용됩니다. 측면 기동을 교전 내내 하게 만들어 놨으니, 봇은 교전 시간 전부를 "달리면서 쏘는 상태" 로 보낸 셈이었습니다.

전술 자체는 맞았습니다. 그 전술이 기존 규칙과 곱해지는 걸 안 본 게 틀렸습니다.

붙는 동안만 돈다

고친 건 한 조건입니다. 사거리 안에 들어오면 측면 기동을 그만두고 멈춰서 쏩니다.

var in_band: bool = distance >= ideal * 0.6 and distance <= ideal * 1.4
if _flank_side != 0.0 and not in_band:
    # ... 측면으로 이동 ...
    if global_position.distance_to(spot) > 2.5:
        return spot
    _flank_side = 0.0   # 도착했다. 이제부터는 서서 쏜다.

측면 기동은 붙는 동안 하는 것이지 교전 내내 하는 게 아닙니다. 명중률이 22% 로 돌아왔고, 측면 기동 횟수는 오히려 78회로 늘었습니다 — 자리를 잡고 멈추니 다음 기동을 할 여유가 생긴 겁니다.

덤으로 알게 된 것

봇에게 발소리가 아예 없었습니다.

플레이어는 발소리를 내는데 봇은 안 냅니다. 이 장르에서 소리로 상대 위치를 아는 건 시야만큼 중요한 정보인데, 그 채널이 통째로 없었던 겁니다. 몇 달 동안 아무도 (저를 포함해) 눈치채지 못했습니다. 없는 것은 화면에 안 나오니까요.

지금은 엎드리면 거의 안 들리고 달리면 크게 납니다. 그래야 자세를 쓸 이유가 생깁니다.

있는 걸 고치는 건 보고 하면 됩니다. 없는 걸 알아채는 건 목록을 만들어야 합니다.