Có cách nào để thủ tục tạo ra lịch sử của một thế giới?


28

Tôi hơi bị thu hút bởi sơ đồ tìm thấy ở đây đại diện cho 1800 năm lịch sử văn hóa trong một thế giới tưởng tượng mà một người nào đó tạo ra.

nhập mô tả hình ảnh ở đây

Loại điều này dường như sẽ có các ứng dụng mạnh mẽ để phát triển trò chơi, trong chừng mực như thiết kế thế giới.

Có vẻ như anh ấy đã làm sơ đồ này bằng tay. Điều tôi quan tâm là xem liệu có cách nào để tạo ra loại sơ đồ này theo chương trình hay không.

Nếu bạn được giao nhiệm vụ tạo sơ đồ theo kiểu trên từ các giá trị ngẫu nhiên, bạn sẽ làm thế nào về nó? Có bất kỳ cấu trúc dữ liệu cụ thể hoặc thuật toán mà bạn sẽ xem xét?


5
Hãy xem xét việc xem Pháo đài Lùn . Nguồn không có sẵn và quá trình tạo thế giới không có giấy tờ (mà tôi tại sao tôi không đưa ra câu trả lời này) nhưng bạn có thể kiểm tra lịch sử thế giới đã tạo mà không cần phải học chơi trò chơi và nó có thể cho bạn ý tưởng về loại này những điều bạn có thể làm.
Josh

Một tài nguyên khác, và không phải là một câu trả lời có thể được tìm thấy tại: www-cs-students.stanford.edu/~amitp/game-programming/ trộm Đây là một bài viết để tạo ra một môi trường nhưng nó tiếp tục chạm vào cách môi trường có thể được sử dụng để xác định ranh giới khu vực cho các vương quốc dựa trên các tài nguyên (như nước, đất có thể sống, v.v.) có thể bị ném vào hỗn hợp khi mọi người đi chiến tranh về những gì và ở đâu hoặc như thế nào .. Một lần nữa, chỉ là một tài nguyên, không phải là một câu trả lời.
James

1
Sơ đồ này trông rất giống với biểu đồ sức mạnh trong Civilization 3. Bạn có thể muốn xem loạt bài đó cho một số ý tưởng.
WildWeazel

Câu trả lời:


15

Làm thế nào chính xác mà bạn muốn được? Một lựa chọn tốt nhưng phức tạp sẽ mô phỏng tất cả lịch sử đó:

  1. Tạo một danh sách khu vực ngẫu nhiên và kề giữa các khu vực này.
  2. Tạo ra các nền văn minh ngẫu nhiên với các đặc điểm như dân số, hiếu chiến, công nghệ ... và dân cư trong khu vực.
  3. Mô phỏng bao nhiêu năm lịch sử như bạn muốn, xác định kết quả dựa trên đặc điểm văn minh.

Ví dụ: hai nền văn minh hiếu chiến liền kề có xác suất bắt đầu chiến tranh với nhau cao hơn, dẫn đến dân số thấp hơn theo thời gian. Các nền văn minh thương gia có tài nguyên cao hơn, nhưng là một mục tiêu lớn cho các cuộc xâm lược. Những người đông dân sẽ phát triển nhanh hơn nhưng cũng có nhiều cơ hội đói hơn. Những công dân không đồng nhất về mặt văn hóa có cơ hội chiến tranh nội bộ thấp hơn (có thể dẫn đến sự tan vỡ.) Và như vậy ... Kết quả cũng sẽ sửa đổi các đặc điểm văn minh: công nghệ cao hơn dẫn đến giao dịch tốt hơn, vũ khí mạnh hơn, v.v.

Điều này cũng cho phép một số cách kể chuyện theo thủ tục: bạn có thể xuất ra không chỉ sơ đồ lãnh thổ, mà cả các mô tả văn bản về lịch sử xuyên thời gian. Bạn có thể làm cho hệ thống này phức tạp như bạn muốn.


EDIT: thách thức ở đây không phải là một kỹ thuật, mà là điều chỉnh các heuristic để tạo ra lịch sử thực tế và thú vị. Hãy xem xét kỹ hơn và suy nghĩ về 3 điểm đã nói ở trên ... đó là khá nhiều giải thích kỹ thuật của bạn! Dịch nó thành một vòng lặp (mỗi lần lặp có thể biểu thị bao nhiêu thời gian bạn muốn, 1 năm, nửa năm, 1 tháng ...) và đó là điều đó. Bạn sẽ phải làm việc với các phần tử bên trong (cấu trúc dữ liệu, phương pháp phỏng đoán) và điều chỉnh nó phù hợp với vấn đề và nhu cầu cụ thể của bạn. Đó là phần khó ở đây và không ai có thể giúp bạn, vì đó là về trí tưởng tượng, thử nghiệm và lỗi.

Không có cấu trúc dữ liệu chung cho vấn đề này ngoài những cấu trúc bạn sẽ sử dụng cho hầu hết mọi vấn đề: danh sách, hàng đợi, cây ... và chúng sẽ được gắn với việc triển khai cụ thể của bạn (tôi có cần một cây phả hệ không? trong chiến tranh? một hàng nhiệm vụ cho mỗi công dân?) Tất nhiên bạn cũng cần một danh sách các nền văn minh. Các lựa chọn là hiển nhiên và khá nhiều ý nghĩa phổ biến.

Mô phỏng là một vấn đề về cơ hội / xác suất và bạn có thể biến nó thành một ngàn cách khác nhau với các số ngẫu nhiên. Hãy nghĩ về bất kỳ trò chơi nào khác có mô phỏng như người quản lý bóng đá, game nhập vai (xét cho cùng, điểm nhấn / chỉ số chỉ là mô phỏng chiến đấu ), trò chơi chiến lược ... Đó chỉ là đặc điểm (vì vậy bạn sẽ cần một cách để lưu trữ dữ liệu và đặc điểm văn minh) và kết quả ngẫu nhiên theo thống kê dựa trên chúng (vì vậy bạn sẽ phải thay đổi ngẫu nhiên trạng thái mô phỏng dựa trên các đặc điểm này.)

Đó là bản chất của thuật toán của bạn: khó điều chỉnh các heuristic: cách phân phối các đặc điểm khi bắt đầu mô phỏng cho mỗi nền văn minh và cách thay đổi thống kê trạng thái mô phỏng dựa trên chúng.

Nói tóm lại: thuật toán của bạn chỉ là một vòng lặp trong khoảng thời gian mô phỏng với bất kỳ mức tăng mong muốn nào. Gia số ngắn hơn dẫn đến mô phỏng lịch sử tốt hơn, nhưng rõ ràng sẽ mất nhiều thời gian hơn. Trong vòng lặp của bạn sẽ có một loạt các heuristic như (đại khái):

for each civilization
  if civ.isAtWar
    civ.population -= civ.population * 0.05;
    civ.wealth -= 1000.0;
    civ.belligerence += 1.0;
  if civ.population < 100
    civ.negotiatePeace()

Sau khi tất cả công việc này (hoặc trong khi bạn không muốn lưu trữ dữ liệu), bạn phải diễn giải tất cả trạng thái mô phỏng thành định dạng có thể đọc được như văn bản, hình ảnh hoặc bất cứ điều gì bạn muốn. Đây là bản dùng thử và lỗi quá và rất cụ thể cho việc thực hiện của bạn.

Cụ thể cho câu hỏi của bạn: để tạo một sơ đồ giống như trong câu hỏi của bạn, bạn sẽ phải theo dõi các khu vực trên thế giới (trên cùng của sơ đồ, trục x, đó là điểm 1: tạo danh sách khu vực trong câu trả lời của tôi) và nền văn minh của họ (màu sắc trong sơ đồ, điểm 2 ) qua thời gian (trục y, vòng lặp mô phỏng ở điểm 3. )

Máy nhà nướckhá giỏi trong việc mô phỏng các chủ đề rộng (mẫu mã ở trên là xấp xỉ của máy trạng thái được mã hóa cứng) - vì vậy bạn có thể bắt đầu bằng cách triển khai khung máy trạng thái đơn giản, dễ điều chỉnh. Mỗi nền văn minh sẽ bắt đầu với một trong những máy trạng thái này và mô phỏng sẽ chạy từng máy trạng thái cho mỗi lượt. Mỗi bộ máy nhà nước sẽ cần có khả năng tương tác với bộ máy nhà nước khác: ví dụ: bắt đầu một cuộc chiến tranh sẽ ảnh hưởng đến bộ máy nhà nước của một nền văn minh khác, có thể với các kết quả khác nhau dựa trên trạng thái bên trong của họ - ví dụ nếu họ ở trong tình trạng 'nạn đói' thì họ sẽ có khả năng muốn đàm phán hòa bình, nhưng một nền văn minh 'tìm kiếm rắc rối' có thể sẽ trả đũa. Mỗi trạng thái trong máy sẽ có tác dụng có ý nghĩa đối với nền văn minh ' số liệu được nêu ở trên trong mỗi 'khung' (sự giàu có, hiếu chiến, dân số, v.v.). Quan trọng nhất là bạn không cần phải chuyển trạng thái trên mọi khung - ngay khi cơ hội và / hoặc cơ hội ngẫu nhiên xuất hiện: điều này cho phép các sự kiện kéo dài (như chiến tranh) xảy ra.


Cảm ơn vì một câu trả lời rất hay, mặc dù nó không liên quan đến các khía cạnh kỹ thuật mà tôi quan tâm
pdusen

@pdusen bình luận đã khá lâu nên tôi đã cập nhật câu trả lời của mình với nó dưới dấu "EDIT".
kaoD

2
Tôi sẽ thêm vào câu trả lời này, nếu bạn không phiền?
Jonathan Dickinson

@JonathanDickinson chắc chắn, hãy tiếp tục :)
kaoD

@pdusen Tôi đã thêm một số chi tiết cụ thể thực hiện.
Jonathan Dickinson

8

Có, có. Đây là một trình tạo lịch sử đơn giản:

#!/usr/bin/env python
# to create a visualisation, run like this:
#    ./timeline.py --dot | dot -Tpng > filename.png
import sys
import random
from pprint import pprint
# Names is a newline separated list of nation names.
file = "names.txt"
names = open(file, "r").read().split("\n") 
history = []
dot = False
if len(sys.argv) > 1 and sys.argv[1] == "--dot":
  dot = True

def wrap(str, wrap='"'):
  return wrap+str+wrap

def merge(states, names):
  number = random.randint(2,3)
  mergers = [] 
  if number < len(states):
    mergers = random.sample(states, number)
    new_name = random.choice(names)
    states = list(set(states).difference(set(mergers)))
    states.append(new_name)
    names.remove(new_name)
    if dot:
      for state in mergers:
        print '"%s" -> "%s"'%(state, new_name)
      print '{rank=same; %s }'%wrap(new_name)
    else:
      print "MERGE %s ==> '%s'"%( ", ".join(map(wrap,mergers)), new_name)
  return states, names 


def split(states, names):
  number = random.randint(2,3)
  if number < len(names):
    splitter = random.choice(states)
    states.remove(splitter)
    new_states = random.sample(names, number)
    names = list(set(names).difference(set(new_states)))
    states = list(set(states).union(set(new_states)))
    if dot:
      for state in new_states:
        print '"%s" -> "%s"'%(splitter, state)
      print '{rank=same; %s }'%("; ".join(map(wrap, new_states)))
    else:
      print "SPLIT '%s' ==> %s"%(splitter, ", ".join(map(wrap,new_states)))
  return states, names

def revolt(states, names):
  old = random.choice(states)
  new = random.choice(names)
  names.remove(new)
  states.remove(old)
  states.append(new)
  if dot:
    print '"%s" -> "%s"'%(old, new)
    print '{rank=same; "%s"}'%new
  else:
    print "REVOLT '%s' ==> '%s'"%(old, new)
  return states, names

def conquest(states, names):
  if len(states) > 1:
    loser = random.choice(states)
    states.remove(loser)
    winner = random.choice(states)
    if dot:
      print '"%s" -> "%s" [label="conquered by"]'%(loser, winner)
    else:
      print "CONQUEST '%s' conquered '%s'"%(winner, loser)
  return states, names


#ignore empty names
names = [name for name in names if name] #yes, really.

origin = random.sample(names, random.randint(1,3))
names = list(set(names).difference(set(origin)))
history.append(origin) #random starting states

if dot:
  print "digraph g {"
  print "{rank=same; %s}"%("; ".join(map(wrap,origin)))
else:
  print("BEGIN %s"%(", ".join(map(wrap,history[0]))))

while names:
  func = random.choice([merge, split, revolt, conquest])
  states, names = func(history[-1], names)
  history.append(states)

if dot:
  print '{rank=same; %s}'%("; ".join(map(wrap,history[-1])))
  print "}"
else:
  print "END %s"%(", ".join(map(wrap,history[-1])))

Mà tạo ra đầu ra như thế này:

nhập mô tả hình ảnh ở đây

Điều chỉnh các heuristic để tạo các biểu đồ khác nhau.

Cách đơn giản nhất để làm điều này là thay đổi func = random.choice([merge, split, revolt, conquest])dòng để có nhiều hơn một chức năng cùng tên. Ví dụ func = random.choice([merge, split, revolt, conquest, merge, merge])sẽ dẫn đến các quốc gia sáp nhập thường xuyên hơn.

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.