🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.tcl
Article #131

Temat akademicki

#131
From: Wojciech Kocjan
Date: Sun, 17 Jul 2005 10:55
144 lines
6582 bytes
Hej,

W związku z tym, że tu jest za cicho, postanowiłem podrzucić temat do 
dyskusji. Mianowicie chciałbym w ramach nadmiaru luzu w pracy stworzyć 
gierkę strategiczną. Pomijam narazie jaką, bo pewnie się poddam i 
pomyślę o czymś znacznie prostszym (chyba, że są chętni do robienia 
razem :-).

Jednakże najbardziej podobał mi się kiedyś pomysł takiej gierki "When 2 
Worlds War" z Amigi (ostatnio widzialem "Pocket War" na pocketpc, ale 
nie sprawdzałem jak to wygląda tam). Mianowicie gra polegała na 
napisaniu poleceń dla jednostek, potem dla baz i bardzo często potem 
piło się piwo/wino/kawę/herbatę/whatever, a one same sobie walczyły. Tam 
trzeba było głównie dzielić produkcję nowych na "squads" i sprawdzać na 
ile tam jest problemów z tym. Ale pomysł miodny i na mocnej Amidze 
(czyli 40MHz :) nieraz miało się tysiące jednostek. Tradycyjny klikacz 
myszką by sobie nie dał rady - chociaż można je było ręcznie też 
obsługiwać. No ale sytuacja, gdzie trzeba było spaceshipami 
transportował lądowe/lotnicze/morskie, eskortować je innymi spaceshipami 
etc to byłoby sadyzmem robić to ręcznie.

W każdym razie bardzo korci mnie napisanie jakiejkolwiek gierki 
napędzanej skryptami. No i myślałem sobie jak do tego Tcl wykorzystać. 
Jedyny myk jest taki, że nie chciałbym żeby jeden skrypt był w stanie 
wykorzystywać za dużo czasu (taki mini RTOS :), a też nie chciałbym 
odpalać milionów wątków dla każdej jednostki z osobna. Aha, skoro 
miałaby to być gra dla siedzących w pracy, zakładam, że tura byłaby i 
tak proporcjonalna do średniej ilości jednostki/gracz - z początku 
krótko, jak już się każdy rozwinie to dużo dłużej (co sprzyja czasowi 
wyznaczania działań).

Przyszło mi do głowy kilka pomysłow, ale może ktoś ma inny:

1/ Podmiana funkcji pętlowych - for, foreach, while i inne
To zaproponowali goście z comp.lang.tcl, ale ma duży minus - jak już 
przerwę pętlę to do niej nie wrócę. Nawet jeśli zapamiętam stan i 
wykonam później iterację, to sprawdza się to w:

for {set i 0} {$i < 30} {incr i} {
     puts X
}

ale nie sprawdzi się w:

for {set i 0} {$i < 3} {incr i} {
     for {set j 0} {$j < 10} {incr j} {
         puts X
     }
}

nie mógłbym przerwać wewn. pętli i jakoś wrócić do głównej. A może 
mógłbym, ale ilość magii przekraczałaby pisanie debuggera do Tcl chyba.

2/ Każdy gracz to jeden wątek
To daje w miare sprawiedliwy podział czasu, raczej załatwiany przez 
system (nie wiem co z tzw userspace threads, chyba BSD ma/miał takie). 
Ale jest jeden minus - jeden infinite loop pozwoli zabić całą ekipę. Co 
byłoby ciekawe, bo znając błędy w skryptach można byłoby exploitować 
wroga ;-)

Można połączyć 1/ z 2/ i np żaden loop nie mógłby trwać więcej niż 
określony czas.

3/ Napisanie od nowa
To jest najciekawsze, ale nie wiem ile niesie ze sobą babraniny.

Stworzyłbym safe interpreter, w którym zdefiniowałbym pętle i wszystko 
jako własne polecenia. To wiąże się z kilkoma obejściami, na przykład 
nie można byłoby bezpośrednio wykonywać poleceń i wyliczać, ale w znośny 
sposób dałoby się to obejść. Pozbyłbym się części poleceń Tcl, a 
stosował prostsze (np for/foreach/while), ale trudno.

Większość można zrobić parsując [info complete], natomiast nie mam 
pojęcia ile jest z tym zabawy. Na pewno parsowanie szukając ";" oraz \n 
i sprawdzanie [info complete] działa dobrze, ale potem każda 
pętla/warunek musi sobie rozbijać swoje polecenia i boję się o czas tego.

4/ Zdarzenia
To z kolei da największy hardcore dla piszących skrypty.

Teoretycznie to najbardziej pasuje do Tcla, ale bardziej naturalne 
wydaje się zapisanie:

while {1} {
     while {[damage] < 0.6} {
         set pos [me nearest_enemy]
         move_to_weapons_range $pos
         attack $pos
     }
     go_to_base
}

Eventami:

proc repairmode {} {
     on newturn {}
     on idle {repairmode2}
}

proc repairmode2 {} {
     start_repair
     on newturn {}
     on idle {sop}
}

proc sop {} {
     on newturn {
         if {[damage] >= 0.6} {repairmode}
     }
     on idle {
         set pos [me nearest_enemy]
         move_to_weapons_range $pos
         attack $pos
     }
}

Chociaż to drugie jest faktycznie ciekawe :) No i prostsze do 
zaimplementowania. Plus nie wyrzuciłbym na śmietnik optymalizacji do 
bytecode.

Analizowałem też problem interpretatorów. Stworzenie 10000 
interpretatorów ([interp create -safe] + 50 interp alias) zżera 400MB 
pamięci. Natomiast interp dla każdej kombinacji gracz,rodzaj_obiektu 
plus namespace dla każdej instancji (dla zmiennych lokalnych etc) to już 
dobre rozwiązanie. 20000 jednostek + 10 zmiennych lokalnych każda (i 50 
interp alias dla każdego interpa) zajmuje 30MB. To jest do 
zaakceptowania bez problemu.

Oczywiście każdy team musi mieć innego interpa, żeby nie czytać sobie 
wzajemnie zmiennych :-) To by był dopiero hardcore - mimo, że [info] nie 
będzie ;-)

Czy ktoś chciałby podyskutować co tu można ciekawego wymyślić? Albo ktoś 
chciałby się dołączyć?

ps. Na studiach miałem "najkrótszą drogę", ale tu już za dużo nie 
pamiętam, a też podręcznikowe metody pewnie mają się kiepsko do realiów 
i optymalizacji kodu. Ma ktoś dobry algorytm na to? Chodzi głównie o 
mapy np 160x80, gdzie podane są "koszty" ścieżki (wolę nie bawić się w 
drogi jak w civ/freeciv, bo to utrudnia alrogytm AFAIR). Tu akurat 
chętnie wsparłbym się kodem w C, żeby było szybciej.

-- 
WK
Technical Details
Message-ID: <dbddek$9qb$1@atlantis.news.tpi.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.onet.pl!newsfeed.tpinternet.pl!nemesis.news.tpi.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mail

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.onet.pl!newsfeed.tpinternet.pl!nemesis.news.tpi.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mail
From: Wojciech Kocjan <hceicjow.backward@kocjan.org>
Newsgroups: pl.comp.lang.tcl
Subject: Temat akademicki
Date: Sun, 17 Jul 2005 12:55:14 +0200
Organization: tp.internet - http://www.tpi.pl/
Lines: 144
Message-ID: <dbddek$9qb$1@atlantis.news.tpi.pl>
NNTP-Posting-Host: bpi135.neoplus.adsl.tpnet.pl
Mime-Version: 1.0
X-Trace: atlantis.news.tpi.pl 1121597717 10059 83.29.50.135 (17 Jul 2005 10:55:17 GMT)
X-Complaints-To: usenet@tpi.pl
NNTP-Posting-Date: Sun, 17 Jul 2005 10:55:17 +0000 (UTC)
User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206)
X-Accept-Language: pl, en-us, en
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit