A * Thuật toán cho game nhập vai chiến thuật?


15

Tôi đang loay hoay với việc viết một game nhập vai chiến thuật thực sự kém trong C ++. Cho đến nay tôi có một bản đồ ô 2D và chỉ có thuật toán A * hoạt động dựa trên mã giả trong wikipedia .

Nhưng những game nhập vai chiến thuật thực sự không chỉ tìm thấy con đường tốt nhất trên một mặt phẳng và di chuyển đến đó. Chúng thường có phạm vi di chuyển hạn chế và phải leo lên hoặc xuống. Nếu bạn đã từng chơi Final Fantasy Tactics, những thứ này sẽ bị ảnh hưởng bởi các chỉ số Di chuyển và Nhảy. Đây là nơi tôi bị lạc. Làm cách nào để thay đổi thuật toán A * để nó tìm thấy đường dẫn tốt nhất tới mục tiêu, nhưng đường dẫn chỉ dài quá nhiều gạch? Làm thế nào tôi nên lấy chênh lệch chiều cao và nhảy số liệu thống kê? Làm thế nào để tôi thực hiện nhảy qua một khoảng cách?

Nếu nó giúp, ngay bây giờ bản đồ của tôi được đại diện bởi một đối tượng Vector of Tile. Mỗi ô có các con trỏ về phía Bắc, Nam, Đông và Tây, được đặt thành nullptr nếu không có ô nào tồn tại ở đó, chẳng hạn như dọc theo cạnh của bản đồ hoặc nếu một ô được đặt thành không thể vượt qua.


5
Tôi không biết tại sao di chuyển phạm vi là một vấn đề. Tìm con đường ngắn nhất và sau đó, di chuyển các ô vuông 'tốc độ' dọc theo con đường đó.
Vịt mướp

Câu trả lời:


33

Leo núi, và khoảng trống, chỉ là các chức năng chi phí khác nhau. Đối với một đơn vị có thể nhảy khoảng cách có chi phí (?) Bình thường, trong khi đối với một đơn vị không nhảy, nó có chi phí cao tùy ý. Leo núi tốn thêm chi phí, cũng như địa hình khó khăn, v.v ... Thuật toán A * có khả năng xử lý tốt các hàm chi phí, vì vậy nếu việc triển khai của bạn chưa thực hiện được, chỉ cần google để biết cách triển khai A * với hàm chi phí.

Tuy nhiên, có nói rằng, tôi không nghĩ A * là một cách tiếp cận đặc biệt tốt cho một game nhập vai chiến thuật. Hay chính xác hơn, nó không phải là một câu chuyện hoàn chỉnh. Bạn không muốn các đơn vị của mình mù quáng nhắm vào mục tiêu của họ, bạn muốn họ định vị bản thân để khai thác vỏ bọc, vùng đất cao, bất cứ điều gì, trong khi tiến tới mục tiêu cuối cùng và tìm cách đánh bại đối thủ, v.v. Vì vậy, giá trị chiến thuật của điểm cuối của mỗi lần di chuyển có tầm quan trọng rất lớn, không chỉ là mục tiêu của nó gần đến mức nào. Điều này đòi hỏi giải quyết vấn đề sâu hơn so với chỉ tìm đường.


10
Điểm hay về 'định vị chiến thuật', nhưng những quyết định đó có thể được áp dụng ở cấp độ cao hơn so với tìm đường cơ bản. Mặt khác, áp dụng chi phí cho các nút trong thuật toán tìm đường được tạo bởi một số loại phân tích chiến thuật có thể là một lựa chọn tốt. Ví dụ: nếu kẻ thù có đường ngắm ngang với địa hình thì làm cho các nút trên địa hình đó có chi phí rất cao.
DrMcCleod

1
@DrMcCleod: Thật vậy, và đó là ý của tôi bởi "Hay chính xác hơn, nó không phải là một câu chuyện hoàn chỉnh". Bạn chắc chắn có thể đang sử dụng A * hoặc một thuật toán khác để thực hiện một phần của quá trình xử lý, tuy nhiên tôi nghĩ rằng tôi sẽ tránh các cách tiếp cận như cố gắng tránh các nút được theo dõi thông qua chi phí di chuyển do di chuyển qua địa hình nơi một đơn vị có thể bị hỏa hoạn được xử lý tốt hơn vì tính toán rủi ro / phần thưởng, IMO.
Jack Aidley

13

Khi bạn muốn tất cả các tùy chọn chuyển động có thể có của một đơn vị, hãy sử dụng Thuật toán Dijkstra .

Sự khác biệt giữa A * và Dijkstra là Dijkstra cung cấp cho bạn tất cả các tuyến đường ngắn nhất có thể đạt được với một chi phí nhất định và nếu chưa có điểm nào đến đích, nó sẽ tăng chi phí thêm một lần và tiếp tục. A *, mặt khác, thích tính toán các tuyến đường đó trước tiên có cơ hội tốt để đến đích.

Vì vậy, khi bạn chỉ muốn con đường ngắn nhất từ ​​điểm A đến điểm B, thì A * là một lựa chọn tốt. Nhưng nếu bạn muốn tất cả các tùy chọn di chuyển có thể và con đường ngắn nhất đến từng người trong số họ, thì Dijkstra chính xác là những gì bạn muốn.

Tất cả những gì bạn cần làm là chạy Thuật toán của Dijksta không có nút đích cụ thể, nhưng với chi phí tối đa không được vượt quá (phạm vi di chuyển của đơn vị). Khi đi đến một nút sẽ vượt quá chi phí tối đa, đừng truy cập nó. Khi thuật toán chấm dứt do thiếu các cạnh không được chú ý, mỗi nút trong tập đã truy cập là một đích có thể và các điểm đánh dấu nút trước đó của các nút tạo thành một danh sách được liên kết đại diện cho đường dẫn trở lại nút ban đầu.

Về các bước nhảy: Chúng có thể được thể hiện dưới dạng một cạnh khác trong cả A * và Dijkstra. Chúng có thể có cùng chi phí như đi qua một cạnh thông thường hoặc một cạnh khác. Bạn cũng có thể truyền tham số "jump_height" cho thuật toán để thuật toán bỏ qua các cạnh nhảy vượt quá độ cao cho trước.


9
Đáng nói ở đây A*thực sự chỉ là một khái quát của Dijkstra, vì vậy nếu bạn hiểu cái này thì không nên quá khó để hiểu cái kia.
Khối

8
Thật vậy, nếu bạn có một heuristic chỉ trả về 0 trong thuật toán A * của bạn, xin chúc mừng! Bạn vừa viết thuật toán của Dijkstra.
Yann

9
"Dijkstra cung cấp cho bạn tất cả các tuyến ngắn nhất có thể đạt được với một chi phí nhất định và nếu chưa có tuyến nào đến đích của bạn, nó sẽ tăng chi phí thêm một và tiếp tục" - Đó không phải là cách nó hoạt động cũng như những gì nó tạo ra. Nó thực sự chỉ là một khái quát của tìm kiếm đầu tiên theo chiều rộng cho các biểu đồ có trọng số. Nó tìm thấy một con đường ngắn nhất. A * chỉ là một khái quát về điều đó, vì khi bạn có sẵn một khoảng cách heuristic.
BlueRaja - Daniel Pflughoeft

1
Không chắc chắn tại sao điều này được nâng cấp. Từ quan điểm thực dụng, Dijkstra đã lỗi thời. Nó được dạy trong CS vì lý do giáo dục và lịch sử. Ngay cả A * cũng lỗi thời đối với công việc nghiêm túc; Google Maps chắc chắn không sử dụng nó. Bạn sẽ nhìn vào các biến thể ArcGraph ngày nay.
MSalters

2
@MSalters Dijkstra và A * là những thuật toán hoàn toàn tốt cho các vấn đề đơn giản như game nhập vai chiến thuật. Có một phạm vi rất hẹp của các chuyển động hợp lệ (gạch) và số lượng rất hạn chế để di chuyển qua các ô đã nói (hình vuông, đôi khi là đường chéo) và thường là một đường dẫn tối đa khá ngắn: SQRT (ArenaWidth² * ArenaHeight²). Về mặt tính toán, sự khác biệt là không đáng kể trên một máy hiện đại với những giá trị khá nhỏ, vậy tại sao phải bận tâm với việc triển khai phức tạp hơn khi một đơn giản là đủ cho các mục đích được nêu ở đây?
Valthek

2

Các câu trả lời khác có một số thông tin tốt, vì vậy hãy chắc chắn đọc chúng.

Tuy nhiên, để trả lời câu hỏi của bạn: dựa trên mã giả mà bạn đã liên kết đến, bạn có một số loại chức năng heuristic_cost_estimatemà bạn đang tính toán chi phí từ gạchA đến gạchB (giả sử chúng nằm liền kề). Thay vì sử dụng căn hộ (1) cho chi phí đó, bạn sẽ phải điều chỉnh nó để bao gồm các số liệu thống kê và đơn vị thống kê và có thể cả các số liệu thống kê cạnh.

Ví dụ:

if (edge == JUMP && !unit.canJump()) 
    return INF;
if (tile.Type == Forest && unit.moveType == HORSE) 
    return 2;
//Other cases here
//-----
else 
    return 1;

Điều này sẽ cung cấp cho bạn con đường của bạn. Sau đó, bạn chỉ cần di chuyển thiết bị dọc theo đường đi của chúng trong khi tiêu thụ các điểm di chuyển và dừng chúng khi còn lại Điểm <edgeCost. Lưu ý rằng điều này có thể không hoàn toàn tối ưu nếu bạn kết thúc với phần còn lại = 1, nhưng nó sẽ đủ tốt cho một game nhập vai thực hành. Trên thực tế, bạn muốn có nhiều chiến thuật hơn, như Jack Aidley đã chỉ ra!

Thử thách:
Nếu bạn muốn nâng cao hơn, có lẽ bạn muốn sử dụng Djikstras như được đề xuất để tìm tất cả các khoảng trống trong khoảng cách X, sau đó bạn muốn đánh giá từng khoảng trống trong danh sách đó cho một vị trí "tốt nhất", dựa trên sự gần gũi với mục tiêu, phòng thủ sức mạnh, cho dù bạn có thể bị tấn công từ vị trí đó hay không, v.v. Dựa trên thông tin đó, bạn sẽ chọn một ô, sau đó di chuyển đến đó theo con đường bạn vừa tính bằng Djikstras.


1

Leo núi và khoảng trống là khá nhỏ vì chúng chỉ sửa đổi chi phí. Pathfinding (và hầu hết AI chiến thuật) là tất cả về việc tổng hợp chi phí cho tất cả các nút được truy cập và giảm thiểu điều đó. Một vách đá không thể vượt qua sẽ có chi phí vô hạn (rất, rất cao), dốc sẽ có chi phí cao hơn bình thường, v.v.

Tuy nhiên, điều này tìm thấy con đường tối ưu toàn cầu không phải là giải pháp tốt nhất bởi vì các đối thủ thực sự thường không tìm thấy đường dẫn tối ưu. Điều đó rất phi thực tế, đôi khi đến mức rõ ràng đối với người chơi và gây khó chịu (đặc biệt là khi AI như vậy về cơ bản là bất khả chiến bại vì nó cũng chọn tối ưu).

Mô phỏng tốt có chủ ý không tìm thấy con đường tốt nhất. Một thuật toán tốt hơn nhiều có thể là thực hiện tìm đường phân cấp - nếu không có gì khác, bằng cách vẽ một đường thẳng trên bản đồ và lấy 4-5 điểm tham chiếu, sau đó tìm đường từ điểm này sang điểm tiếp theo, chỉ xem xét các trọng số nút cho đến nay đã biết và đặt tất cả các nút khác thành "không quan tâm". Ngoài ra, bạn có thể chạy A * trên lưới thô hơn trước, sau đó tìm đường dẫn từ một nút lớn sang nút tiếp theo (nhưng tôi đoán rằng việc vẽ một đường trên bản đồ cũng tốt).

Điều này thực tế hơn nhiều (và cũng tiêu tốn một phần công suất xử lý vì biểu đồ nhỏ hơn nhiều ). Vâng, điều đó có thể có nghĩa là một đơn vị di chuyển về phía một vách đá chỉ để biết rằng nó không thể vượt qua. Điều đó cũng tốt, nó cũng xảy ra với những kẻ thù thực sự. Lần sau, nó sẽ không xảy ra lần nữa (vì bây giờ chi phí vô hạn đã được biết).


1
Nhắc bạn, rằng "tìm đường phân cấp đơn giản" có thể trông khá ngu ngốc. Bạn nhận được các đơn vị đi thẳng đến một sườn núi, chỉ để phát hiện ra rằng con đường bị chặn. Sau đó, họ đi qua đèo núi đến điểm tiếp theo, và từ đó đến đích của họ - ngay cả khi điểm cuối đó là con đường không phù hợp với họ. Tiền xử lý sẽ xác định được ngọn núi vượt lên phía trước và điểm qua đó. Nhưng ngay cả khi bạn không làm điều đó, một khi bạn ở quá xa khóa học đã lên kế hoạch, bạn nên lập kế hoạch lại phần còn lại.
MSalters

@MSalters: Điều đó có thể xảy ra với phương pháp "vẽ đường thẳng" ngay cả sau lần thử đầu tiên, vâng. Không thể xảy ra nhiều hơn một lần với phương pháp phân cấp lưới thô (ví dụ: lấy trung bình hoặc trung bình hoặc thậm chí giá trị chi phí tối đa của các nút bên trong). Đó chính xác là cách mà một kẻ thù của con người sẽ chơi - tránh những chướng ngại vật lớn mà bạn biết hoặc có thể nhìn thấy từ xa như một chuỗi núi, và nếu không thì lên kế hoạch cho một con đường thô sơ hầu như thẳng và cắn theo cách của bạn. Trừ khi bạn biết rằng có một ngọn núi, bạn sẽ đi thẳng tới đó.
Damon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.