Tablica symboli parsera, dynamiczne rzutowanie typów 9079 27

O temacie

Autor Demonical Monk

Zaczęty 29.12.2011 roku

Wyświetleń 9079

Odpowiedzi 27

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
Przepraszam bardzo, Hlp_GetNpc nie zwraca przypadkiem wskaźnika?

[mod=Avallach]Posty wydzielone z dyskusji o porównywaniu npc[/mod]
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
Przecież możesz porównywać npc po ich parserowych identyfikatorach (wspominałem o nich w jednym tutorialu: http://themodders.org/index.php?/topic/13579-identyfikatory-jako-indeksy-tablicy-symboli-parsera) skoro "obaj" są ci znani bezpośrednio (jako instancje, a nie reprezentujące ich zmienne)(a tak naprawdę nie jako instancje, tylko jako symbole parsera które mają swoje indeksy liczbowe):
var INT oponent; oponent = Nov_1331_BaalTaran;    
if (oponent == Nov_1331_BaalTaran)
W tym przypadku "Nov_1331_BaalTaran" to NIE c_npc, tylko liczba. Otóż parser czytając skrypty, każdemu identyfikatorowi (nie tylko obiektów, ale także każdej klasy, zmiennej, stałej, tablicy, prototypu itd) przypisuje kolejne numery, które są indeksami w jego tablicy symboli.Przykładowo, gdyby
instance Nov_1331_BaalTaran (c_npc)Było pierwszą rzeczą w pierwszym skrypcie którą przeczyta gra, to
Nov_1331_BaalTaran = 1Jednak oczywiście pierwszą taką rzeczą nie jest i być nie może, ma swój własny i prawdopodobnie bardzo wysoki numer.
W każdym razie po tych numerkach możesz spokojnie sprawdzać czy dane COŚ jest tym czymś o co ci chodzi :D

Bogdan Zwei

Bogdan Zwei

Użytkownicy
Wulgarny skurwiel pierdolony.
posty1864
Propsy541
Profesjabrak
  • Użytkownicy
  • Wulgarny skurwiel pierdolony.
Każdy może zgadywać, a wkrótce może zgadnąć. ;p

A intem na NPC to troszkę dziwne jest, raczej to nie zadziała, bo będziesz miał dwa razy Nov_1331_BaalTaran jako NPC i jako numer/liczbę.
 
:ok: zachęca do dalszej pomocy. Nie zapominaj o tym!

Prywatne wiadomości typu "Ej, pomocy" kasuję od razu. Od tego jest forum, a nie PW.

To me, defeat in anything is merely temporary, and its punishment is but an urge for me to greater effort to achieve my goal. Defeat simply tells me that something is wrong in my doing; it is a path leading to success and truth.

In order to realize our true self we must be willing to live without being dependent upon the opinion of others.

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
A intem na NPC to troszkę dziwne jest, raczej to nie zadziała, bo będziesz miał dwa razy Nov_1331_BaalTaran jako NPC i jako numer/liczbę.
To taki enginowy myk. Identyfikatory mogą być przez parser traktowane zarówno jako odniesienia do obiektów jak i ich indeksów. Nie potrafię dokładnie powiedzieć od czego to zależy, ale zdecydowanie przeważa ta druga, dziwniejsza interpretacja, tylko po prostu zwykle nie zdajemy sobie z tego sprawy. Zobacz choćby na funkcję hlp_getnpc. Wydaje ci się że jako argument podajesz c_npc, ale przecież to nie miało by nawet sensu. Tak naprawdę argumentem tej funkcji jest int, który stanowi właśnie indeks symbolu z tablicy parsera, a dopiero ta funkcja zwraca odniesienie do prawdziwego obiektu.

Bogdan Zwei

Bogdan Zwei

Użytkownicy
Wulgarny skurwiel pierdolony.
posty1864
Propsy541
Profesjabrak
  • Użytkownicy
  • Wulgarny skurwiel pierdolony.
Cytuj
To taki enginowy myk. "Symbole" mogą być przez parser zależnie od kontekstu traktowane jako odniesienia do obiektów bądź indeksów. Nie potrafię dokładnie powiedzieć od czego to zależy, ale zdecydowanie przeważa ta druga, dziwniejsza interpretacja, tylko po prostu zwykle nie zdajemy sobie z tego sprawy. Zobacz choćby na funkcję hlp_getnpc. Wydaje ci się że jako argument podajesz c_npc, ale przecież to nie miało by nawet sensu. Tak naprawdę argumentem tej funkcji jest int, który stanowi właśnie indeks symbolu z tablicy parsera, a dopiero ta funkcja zwraca odniesienie do prawdziwego obiektu.

Ahaa. Jestem znowu mądrzejszy. xD
 
:ok: zachęca do dalszej pomocy. Nie zapominaj o tym!

Prywatne wiadomości typu "Ej, pomocy" kasuję od razu. Od tego jest forum, a nie PW.

To me, defeat in anything is merely temporary, and its punishment is but an urge for me to greater effort to achieve my goal. Defeat simply tells me that something is wrong in my doing; it is a path leading to success and truth.

In order to realize our true self we must be willing to live without being dependent upon the opinion of others.

Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
A intem na NPC to troszkę dziwne jest, raczej to nie zadziała, bo będziesz miał dwa razy Nov_1331_BaalTaran jako NPC i jako numer/liczbę.
To taki enginowy myk. Symbole mogą być przez parser zależnie od kontekstu traktowane jako odniesienia do obiektów bądź indeksów. Nie potrafię dokładnie powiedzieć od czego to zależy, ale zdecydowanie przeważa ta druga, dziwniejsza interpretacja, tylko po prostu zwykle nie zdajemy sobie z tego sprawy.
To po prostu zawsze jest liczba - numer instancji, z wyjątkiem sytuacji, gdy pisze się wprost:
NAZWA_INSTANCJI.pole
Tak mi się przynajmniej wydaje.
 

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
A intem na NPC to troszkę dziwne jest, raczej to nie zadziała, bo będziesz miał dwa razy Nov_1331_BaalTaran jako NPC i jako numer/liczbę.
To taki enginowy myk. Symbole mogą być przez parser zależnie od kontekstu traktowane jako odniesienia do obiektów bądź indeksów. Nie potrafię dokładnie powiedzieć od czego to zależy, ale zdecydowanie przeważa ta druga, dziwniejsza interpretacja, tylko po prostu zwykle nie zdajemy sobie z tego sprawy.
To po prostu zawsze jest liczba - numer instancji, z wyjątkiem sytuacji, gdy pisze się wprost:
NAZWA_INSTANCJI.pole
Tak mi się przynajmniej wydaje.
Tabela symboli ma własne, inkrementacyjne indeksowanie.
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
Sprawdziłem i wychodzi na to że jest to po prostu "inteligentne" (cudzysłów celowy, na gg Monk już mnie poprawił że "dynamicznie rzutuje typy"). Działa zarówno:
if (Npc_IsDead(NONE_100_Xardas))(mimo że argumentem jest c_npc a nie int)
jak i prawidłowe:
var c_npc xardasek; xardasek = Hlp_GetNpc(NONE_100_Xardas);
if (Npc_IsDead(xardasek))

Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
Jesteś zupełnie pewien, że to pierwsze działa zupełnie dobrze w każdej sytuacji? Wygląda na błąd. Mamy przecież:
FUNC INT    Npc_IsDead                (VAR C_NPC n0 )
a nie:
FUNC INT    Npc_IsDead                (VAR INT n0 )
Co by to właściwie miało znaczyć?

Jestem przekonany, że żadnego rzutowania typów w tej grze nie było.
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
Specjalnie dla ciebie trzy razy sprawdziłem, działa ;d
Właśnie o tym były wszystkie te moje posty, że parser może zamiennie traktować identyfikatory obiektów jako odniesienia do nich samych lub ich liczbowych indeksów.

Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
nie może. jak to niby działa, gdy masz więcej niż jeden byt o danym instance?
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
Z praktycznego punktu widzenia każdy identyfikator może odnosić się do indeksu w tablicy symboli parsera lub do obiektu.

Z drugiej strony technicznie, o ile rozumiem, za każdym razem "po prostu wpisane" instance będzie tak naprawdę indeksem, ale parser potrafi wykryć kiedy jest to zastosowane błędnie i dynamicznie podmienić na odniesienie do odpowiedniego obiektu. Jestem prawie pewien że NicoDE kiedyś o tym pisał, miało to z założenia po prostu ułatwić pracę skrypterom.

Demonical Monk

Demonical Monk

Użytkownicy
posty145
Propsy152
  • Użytkownicy
Typy się dynamicznie rzutują (o ile się da) w momencie wyciągnięcia ze stosu parsera po stronie silnika.

To:
var c_npc xardasek; xardasek = Hlp_GetNpc(NONE_100_Xardas);
Jest jak najbardziej poprawne. Hlp_GetNpc rzuci wskaźnikiem na fizyczną instancję oCNPC, parser opakuje ten wskaźnik w symbol. Brzmi zabawnie, ale wychodzi swego rodzaju pointer w Deadalusie. (Korzystamy z własności, że każdy, czy większość symboli parsera to ładnie opakowane wskaźniki i kilka zmiennych może być w praktyce tą samą zmienną)

Eksperyment do wykonania w domu z gtoolsem:
http://monk.4programmers.net/gtools/index.php?title=gtl_getInstanceByPtr

var oCGame game;
game = gtl_getInstanceByPtr(11208836);
var oCGame game2;
game2 = gtl_getInstanceByPtr(11208836);

game2.initial_minute = 10;
game.initial_minute = 20;
if (game.initial_minute == game2.initial_minute) {
   Print("lol wtf");
}

Ten warunek zawsze będzie spełniony. Mamy dwie zmienne które odwołują się do tego samego obiektu, w obu więc w momencie wykonywania testu initial_minute wyniesie 20.
 

Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
Może powinieneś ograniczyć używanie technicznych terminów, nie sprzyjają zrozumieniu i chyba nie stosujejesz ich do końca precyzyjnie. np. parser to część programu, która zamienia tekst w usystematyzowaną strukturę do dalszej obróbki.
var c_npc xardasek; xardasek = Hlp_GetNpc(NONE_100_Xardas);jest jak najbardziej poprawne, bo Hlp_GetNpc jest:
FUNC C_NPC Hlp_GetNpc (VAR INT instanceName)i nie ma tu potrzeby żadnych rzutowań, o ile pamiętamy, że nazwy instancji są intami. Aliasing - dwie zmienne wskazują ten sam obiekt, to zupełnie inna sprawa. Ciekawe jest jednak zachowanie funkcji Npc_IsDead(...) o ile Avallach mówi prawdę.

Mógłby ktoś kto ma Gothica sprawdzić poniższy kod (i uproszczenia, jeśli nie działa), w sytuacjach, gdy Xardas jest żywy i gdy martwy:
const int CX = NONE_100_Xardas;
func void test() {
var string b;
b = "Test:";
var c_npc xard0;
xard0 = Hlp_GetNpc(NONE_100_Xardas);
if(!Npc_IsDead(xard0)) {
b=concatstrings(b, "Good");
};
print(b);
if(!Npc_IsDead(NONE_100_Xardas)) {
b=concatstrings(b, "Inst");
};
if(!Npc_IsDead(CX)) {
b=concatstrings(b, "Const");
};
var int vx;
vx = NONE_100_Xardas;
if(!Npc_IsDead(vx)) {
b=concatstrings(b, "Var");
};
var c_npc xard1;
xard1 = NONE_100_Xardas;
if(!Npc_IsDead(xard1)) {
b=concatstrings(b, "C_NPC");
};
print(b);
};
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
Terminu "parser" użyłem celowo, wydaje mi się że do tej "zamiany" dochodzi właśnie na tym etapie (choć mogę się mylić).


Ciekawe jest jednak zachowanie funkcji Npc_IsDead(...) o ile Avallach mówi prawdę.
:|
Dlaczego miałbym kłamać że jest tak, a nie inaczej? Naprawdę sprawdziłem to kilka razy i za każdym razem działa. Twoja funkcja już niestety nie, przy reparsowaniu wywalany jest błąd:
Error-Message: U:PAR: Func does not return an instancew linijce:xard1 = NONE_100_Xardas;Próbujesz przypisać wartość liczbową do zmiennej c_npc. Parser przy przypisywaniu wartości oczekuje albo wartości tego samego typu, albo funkcji która ją zwróci.
Kolejny błąd po zakomentowaniu tej części funkcji toError-Message: U:PAR: Wrong type : CXPo wykomentowaniu i tego warunku, kolejnym błędem jestError-Message: U:PAR: Wrong type : vxO ile dobrze rozumiem, oba te błędy potwierdzają że do "podmiany" wpisanej instancji (która reprezentuje indeks) na obiekt dochodzi już na etapie parsera, a nie przy wykonywaniu kodu.
Po wykomentowaniu i tego, zostaje ostatnia część kodu, która już działa:
Spoiler
func void test() {
var string b;
b = "Test:";
var c_npc xard0;
xard0 = Hlp_GetNpc(NONE_100_Xardas);
if(!Npc_IsDead(xard0)) {
b=concatstrings(b, "Good");
};
print(b);
if(!Npc_IsDead(NONE_100_Xardas)) {
b=concatstrings(b, "Inst");
};
print(b);
Kiedy Xardas jest żywy, funkcja wypisuje dwa napisy jeden pod drugim: "Test:GoodInst" i "Test:Good" (bo dałeś w różnych miejscach dwa printy, nie wiem czy celowo). Kiedy jest martwy, już tylko podwójne "Test:".

To nie jest co prawda jednoznaczny dowód mojej prawdomówności ale zawsze jakiś :D
Spoiler

Jak widzisz funkcja działa bez zarzutu :D
Twoje dwa poprzednie eksperymenty nie wypaliły, bo przypisywałeś ten indeks do zwykłej zmiennej. Parser potrafi "zgadywać" tylko kiedy dostaje bezpośrednio odpowiednią nazwę.

Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
Dobra tu się dzieją jakieś dziwne rzeczy. To, czy coś się dzieje na etapie parsera, czy "analizy semantycznej", czy czegokolwiek jest mało istotne. Ważna jest semantyka - znaczenie języka.

W każdym razie cały czas myślałem o G1, co pewnie nie ma znaczenia, ale o G2 wiem nie wiele.

Swoją drogą ciekawe, jak to działa, gdy jest 0, >1 Xardasów.

Nie spodziewam się, żebyś kłamał, ale mogłem przypuszczać, że robisz coś źle.

Ale może przestanę się wymądrzać, bo już pewnie nie wiele pamiętam.
 


Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
sprawdzić, jak funkcja npc_isDead działa, gdy podasz instance, dla którego nie ma wstawionych npców.

sprawdzić, jak funkcja npc_isDead działa, gdy podasz instance, dla którego jest wiele npców, niektórzy żywi inni martwi.
 

inż. Avallach

inż. Avallach

Administrator
posty7661
Propsy5239
NagrodyV
ProfesjaProgramista
  • Administrator
Cytuj
instance, dla którego jest wiele npców
O właśnie tego nie rozumiem. WTF? Przy próbie zdefiniowania drugiego npc o danym instance parser wywala błąd "Redefinied identifier" i przerywa.

Zysk

Zysk

Użytkownicy
posty606
Propsy451
  • Użytkownicy
wld_insertNpc, czy coś w ten deseń. Nie ma problemu, żeby wstawiać wielu npców o tym samym instance. Tak są zrobione niemal wszystkie potwory dementorzy i inne.
 


0 użytkowników i 1 Gość przegląda ten wątek.
0 użytkowników
Do góry