Community
Message Board

Chat room - users
Game Over
( 394431 downloads)
Work In Progress
( 523201 downloads)
Links

Code Exchange
Downloads
Tutorials
Add to Favourites

Submit news

DIV ARENA FORUMS
Not logged in [Login - Register]
Go To Bottom

Printable Version  
Author: Subject: DIV compiler is giving me an error that's not accurate: "It is not possible to access external PRIVATE data."
Casper
DIV Pro
******




Posts: 31
Registered: 18-10-2017
Member Is Offline


[*] posted on 29-10-2017 at 07:29 AM
DIV compiler is giving me an error that's not accurate: "It is not possible to access external PRIVATE data."


Struct declared in local:

Code:
local struct ai previousState; currentState; struct model knownOpponentCount; knownAllyCount; targetOpponentIndex; struct knownOpponents[MAX_CHARACTERS - 1] x; y; visible; end struct knownAllies[MAX_CHARACTERS - 1] x; y; visible; end end end


Process:
Code:
process AIVisionManager(faction) private allOpponents[MAX_CHARACTERS - 1]; aiCharacters[MAX_CHARACTERS - 1]; knownOpponentIndex; knownOpponent; opponent; aiCharacter; begin allOpponents = GetAllOpponents(faction); aiCharacters = GetFactionList(faction); loop // foreach AI for (x = 0; x < MAX_CHARACTERS; ++x) if (aiCharacters[x] <= 0) continue; end aiCharacter = aiCharacters[x]; // foreach opponent for (y = 0; y < MAX_CHARACTERS; ++y) if (allOpponents[y] <= 0) continue; end opponent = allOpponents[y]; knownOpponentIndex = GetIndexOfValueInTable( aiCharacter.ai.model.knownOpponents, MAX_CHARACTERS - 1, opponent); // this AI character already knows this opponent, only update position if (knownOpponentIndex > -1) knownOpponent = aiCharacter.ai.model.knownOpponents[knownOpponentIndex]; else // if AI can see opponent, update the AIs model if (AILineOfSight(aiCharacter.x, aiCharacter.y, opponent.x, opponent.y)) knownOpponentIndex = FindFreeIndexInTable( aiCharacter.ai.model.knownOpponents, MAX_CHARACTERS - 1); aiCharacter.ai.model.knownOpponents[knownOpponentIndex] = opponent; aiCharacter.ai.model.knownOpponentCount++; end end end end frame; end end


I get this error: "It is not possible to access external PRIVATE data." on this line:
Code:
knownOpponent = aiCharacter.ai.model.knownOpponents[knownOpponentIndex];


This line has the same issue if I comment out the above:
Code:
aiCharacter.ai.model.knownOpponents[knownOpponentIndex] = opponent;


I'm trying to access a local struct, not private... does anyone have a clue what's going wrong here?
View user's profile View All Posts By User
CicTec
DIV Pro
******




Posts: 471
Registered: 6-8-2016
Member Is Offline


[*] posted on 29-10-2017 at 09:41 AM


Hello Casper,

The example seems incorrect.

You have defined the local "ai" structure and a private INT type table named "aiCharacters [MAX_CHARACTERS-1];" in the "AIVisionManager" process.

The statement:
Code:
"aiCharacters = GetFactionList (faction);"

Just assign something to the "aiCharacters[0]" position, the other table locations will always be unassigned, so the statement:
Code:
aiCharacter = aiCharacters [x];

It only assigns a value that is contained in the aCharacters[0], the other values ​​will always be 0.

Lastly, with the statement:
Code:
knownOpponent = aiCharacter.ai.model.knownOpponents [knownOpponentIndex];


What do you think about assigning to knownOpponent?
KnownOpponents is a STRUCT, while knownOpponent is an INT, in theory the compiler should not be able to assign anything because of the incompatibility of the types, but in fact what it does in this case is assigning the value of the first member of the structure (ie, X) then interprets the previous statement as if you had written it:
Code:
knownOpponent = aiCharacter.ai.model.knownOpponents [knownOpponentIndex] .x;


The X member in turn has the same name as a LOCAL variable, so it is likely that the compiler, for some bug or missing implementation, misread this member as LOCAL x variable, which you can not access

If you can explain what you want to do in the example and what you would like to assign to the variables we can see a possible solution.



[Edited on 29-10-2017 by CicTec]
View user's profile View All Posts By User
Casper
DIV Pro
******




Posts: 31
Registered: 18-10-2017
Member Is Offline


[*] posted on 29-10-2017 at 11:01 PM


Hey CicTec,

I'll try to answer best I can:

1)
Code:
aiCharacters = GetFactionList (faction);

Code:
function GetFactionList(faction) begin switch (faction) case FACTION_NEUTRAL: return (&__neutralCharacters); end case FACTION_GOOD: return (&__goodCharacters); end case FACTION_EVIL: return (&__evilCharacters); end end end


I use double underscore __ to indicate global variables, these three are tables that contains process ids or 0/-1. So, I'm trying to return a pointer to a table, as I'd like to iterate over it.

2)
knownOpponent is supposed to hold a (temporary) single entry of the local ai.model.knownOpponents[] struct. I should use a pointer here, but posted this in a hurry. I'm not sure if there's a cleaner syntax I could use, but I managed to get it compiling and working as intended with this code:

Code:
process AIVisionManager(faction) private pointer allOpponents[MAX_CHARACTERS - 1]; pointer aiCharacters[MAX_CHARACTERS - 1]; knownOpponentIndex = -1; pointer opponent; pointer aiCharacter; isVisible = false; begin allOpponents = GetAllOpponents(faction); aiCharacters = GetFactionList(faction); loop // foreach AI for (x = 0; x < MAX_CHARACTERS; ++x) if (*aiCharacters[x] <= 0) continue; end aiCharacter = *aiCharacters[x]; // foreach opponent for (y = 0; y < MAX_CHARACTERS; ++y) if (*allOpponents[y] <= 0) continue; end opponent = *allOpponents[y]; // can AI see opponent? isVisible = AILineOfSight((*aiCharacter).x, (*aiCharacter).y, (*opponent).x, (*opponent).y); knownOpponentIndex = -1; // TODO: Clean this up into a function. // find index of element where processId == opponent for (z = 0; z < MAX_CHARACTERS - 1; ++z) if ((*aiCharacter).ai.model.knownOpponents[z].processId == opponent) knownOpponentIndex = z; break; end end if (knownOpponentIndex < 0 && isVisible) // TODO: Clean this up into a function. // find next free index for (z = 0; z < MAX_CHARACTERS - 1; ++z) if ((*aiCharacter).ai.model.knownOpponents[z].processId <= 0) knownOpponentIndex = z; break; end end // visible but previously unknown opponents are added to AI's model (*aiCharacter).ai.model.knownOpponents[z].processId = opponent; (*aiCharacter).ai.model.knownOpponentCount++; end // if knownOpponentIndex is valid (>= 0), then update x, y and visible properties of AI's model if (knownOpponentIndex >= 0) z = knownOpponentIndex; (*aiCharacter).ai.model.knownOpponents[z].visible = isVisible; if (isVisible) (*aiCharacter).ai.model.knownOpponents[z].x = opponent.x; (*aiCharacter).ai.model.knownOpponents[z].y = opponent.y; end end end end frame; end end


You'll notice I used the local 'z' variable as an index to access the structs... that is a workaround for the error in the title of this thread. If I switch to using knownOpponentIndex directly then it complains that I'm accessing private data - which seems quite wrong to me. I'm using private data in the private scope to access public data... shouldn't give an error...
View user's profile View All Posts By User
CicTec
DIV Pro
******




Posts: 471
Registered: 6-8-2016
Member Is Offline


[*] posted on 30-10-2017 at 10:38 AM


Hello Casper,

I see that you've changed something in the AIManager process:
Code:
process AIVisionManager (faction) private      pointer allOpponents [MAX_CHARACTERS - 1];      pointer aiCharacters [MAX_CHARACTERS - 1];

This code will not work as you think, DIV does not support pointers arrays, the previous statement only tells the compiler an interval control for the runtime, the pointer is always one, so the statement:

Code:
if(*aiCharacters[x] <= 0)

Does not produce the result you expect, and the compiler should produce a compile error, the correct code should be:
Code:
process AIVisionManager(faction) private pointer allOpponents; pointer aiCharacters; knownOpponentIndex = -1; isVisible = false; begin allOpponents = GetAllOpponents(faction); aiCharacters = GetFactionList(faction); loop // foreach AI for (x = 0; x < MAX_CHARACTERS; ++x) if(aiCharacters[x] <= 0) continue; end // foreach opponent for (y = 0; y < MAX_CHARACTERS; ++y) if (allOpponents[y] <= 0) continue; end // can AI see opponent? isVisible = AILineOfSight(aiCharacters[x].x, aiCharacters[x].y, allOpponents[y].x, allOpponents[y].y); knownOpponentIndex = -1; // TODO: Clean this up into a function. // find index of element where processId == opponent for (z = 0; z < MAX_CHARACTERS - 1; ++z) if (aiCharacters[x].ai.model.knownOpponents[z].processId == opponent) knownOpponentIndex = z; break; end end if (knownOpponentIndex < 0 && isVisible) // TODO: Clean this up into a function. // find next free index for (z = 0; z < MAX_CHARACTERS - 1; ++z) if (aiCharacters[x].ai.model.knownOpponents[z].processId <= 0) knownOpponentIndex = z; break; end end // visible but previously unknown opponents are added to AI's model aiCharacter[x].ai.model.knownOpponents[z].processId = opponent; aiCharacters[x].ai.model.knownOpponentCount++; end // if knownOpponentIndex is valid (>= 0), then update x, y and visible properties of AI's model if (knownOpponentIndex >= 0) z = knownOpponentIndex; aiCharacters[x].ai.model.knownOpponents[z].visible = isVisible; if (isVisible) aiCharacters[x].ai.model.knownOpponents[z].x = allOpponent[y].x; aiCharacters[x].ai.model.knownOpponents[z].y = allOpponent[y].y; end end end end frame; end end


This should produce the correct result, but being only a piece of code I can not test it.

[Edited on 30-10-2017 by CicTec]

[Edited on 30-10-2017 by CicTec]
View user's profile View All Posts By User
CicTec
DIV Pro
******




Posts: 471
Registered: 6-8-2016
Member Is Offline


[*] posted on 30-10-2017 at 11:23 AM


I forgot to say that you could however emulate pointer arrays with the structures, for example:
Code:
struct aiManager[MAX_CHARACTERS - 1] pointer opponent; pointer aiCharacter; end
View user's profile View All Posts By User
Casper
DIV Pro
******




Posts: 31
Registered: 18-10-2017
Member Is Offline


[*] posted on 30-10-2017 at 10:22 PM


Hey CicTec,

Thanks for taking your time to look through this code! You can actually test it if you like, the project is available here: https://github.com/cmvanb/faust2/

I know that the code I posted produced the desired output (the AI knows the position of the player and turns to look at them), so something is working... I checked with the debugger, the AI is definitely receiving the player's position, via the global table __goodCharacters.

Maybe there is the issue with the arrays as you pointed out and I just can't see it without testing some more use cases with multiple characters (right now there's only one AI and one player character).

I'm going to bed now, so I will check the code in action tomorrow... I'll get back to you once I know more :)
View user's profile View All Posts By User
CicTec
DIV Pro
******




Posts: 471
Registered: 6-8-2016
Member Is Offline


[*] posted on 31-10-2017 at 05:58 PM


Hello Casper,

Ok thanks for the link.

In this period I'm in Linux, I'll see these days if I can compile the latest build I've developed for windows and try out your game so that I can give you more information/possible solutions.
View user's profile View All Posts By User
CicTec
DIV Pro
******




Posts: 471
Registered: 6-8-2016
Member Is Offline


[*] posted on 5-11-2017 at 10:42 AM


Hello Casper,

I've build the last DIV for Linux, downloaded and tried your game.

I've found the cause of the "private external data" error, it's a bug in the compiler, here's an example:
Code:
program test_substructs_access; global gci = 3, gcj = 2; local struct st a, b, c; struct st2[9] e, f, g; struct st3[MAX_CHARACTERS - 1] pID; x, y; end end end lci = 3, lcj = 2; private pci = 3, pcj = 2; pid; pointer p_pid; begin pid = id; p_pid = &pid; // direct st.st2[3].st3[2].pID = id; // works OK st.st2[3].st3[pcj].pID = id; // works OK st.st2[pci].st3[2].pID = id; // works OK st.st2[pci].st3[pcj].pID = id; // works OK // with ID and PRIVATE var as index pid.st.st2[3].st3[2].pID = id; // works OK pid.st.st2[3].st3[pcj].pID = id; // error external data pid.st.st2[pci].st3[2].pID = id; // error external data pid.st.st2[pci].st3[pcj].pID = id; // error external data // with pointer ID and PRIVATE var as index (*p_pid).st.st2[3].st3[2].pID = id; // works OK (*p_pid).st.st2[3].st3[pcj].pID = id; // error external data (*p_pid).st.st2[pci].st3[2].pID = id; // error external data (*p_pid).st.st2[pci].st3[pcj].pID = id; // error external data // with ID and LOCAL var as index pid.st.st2[3].st3[2].pID = id; // works OK pid.st.st2[3].st3[lcj].pID = id; // works OK pid.st.st2[lci].st3[2].pID = id; // works OK pid.st.st2[lci].st3[lcj].pID = id; // works OK // with pointer ID and LOCAL var as index (*p_pid).st.st2[3].st3[2].pID = id; // works OK (*p_pid).st.st2[3].st3[lcj].pID = id; // works OK (*p_pid).st.st2[lci].st3[2].pID = id; // works OK (*p_pid).st.st2[lci].st3[lcj].pID = id; // works OK // with ID and GLOBAL var as index pid.st.st2[3].st3[2].pID = id; // works OK pid.st.st2[3].st3[gcj].pID = id; // works OK pid.st.st2[gci].st3[2].pID = id; // works OK pid.st.st2[gci].st3[gcj].pID = id; // works OK // with pointer ID and LOCAL var as index (*p_pid).st.st2[3].st3[2].pID = id; // works OK (*p_pid).st.st2[3].st3[gcj].pID = id; // works OK (*p_pid).st.st2[gci].st3[2].pID = id; // works OK (*p_pid).st.st2[gci].st3[gcj].pID = id; // works OK end

As you can test from the example, it looks like a bug in the compiler recognizes the PRIVATE variables used as sub-structures indices as members of the same structures when we access with an ID. Because these are PRIVATE, they make a compilation error that should not.


Returning to your game code, it happens the same when trying to access "if ((*actor).ai.model.knownOpponents[cj].processId <= 0)" if "cj" is PRIVATE.

You also do not need pointers, "actors[x]" returns the ID you can save in a normal INT variable and then access LOCAL data with it, your code can be written:
Code:
global gci, gcj, gck; // global counters for loops ... process AIModelManager(faction) private pointer opponents; pointer actors; knownOpponentIndex = -1; opponent; // INT is sufficient actor; // INT is sufficient isVisible = false; begin opponents = GetFactionOpponents(faction); actors = GetFactionActors(faction); loop // foreach AI for (gci = 0; gci < MAX_CHARACTERS; ++gci) if (actors[gci] <= 0) continue; end actor = actors[gci]; for (gcj = 0; gcj < MAX_CHARACTERS - 1; ++gcj) if(actor.ai.model.knownOpponents[gcj].processId <= 0) continue; end ...

I'm using global counters to avoid the waste of memory by declaring them LOCAL and the bug that prevents you from using the PRIVATE.

As a Suggestion: Avoid using the "x", "y" and especially "z" variables as counter in the cycles to avoid a bad performance impact from the internal renderer using these variables.

I hope this solves the problems encountered in your game.

[Edited on 5-11-2017 by CicTec]

[Edited on 5-11-2017 by CicTec]

[Edited on 5-11-2017 by CicTec]

[Edited on 5-11-2017 by CicTec]
View user's profile View All Posts By User
Casper
DIV Pro
******




Posts: 31
Registered: 18-10-2017
Member Is Offline


[*] posted on 7-11-2017 at 04:08 PM


Hey CicTec!

Thanks for taking a closer look, really appreciate it!

I will simplify my pointer access as you indicated, I think it got wonky because I was fighting compile errors and once it worked I just left it that way.

I'm not sure using global counters is a good idea, since I have a lot of processes. If there are two instances of the same process, then every 'frame' they use the same counter it will cause problems, no? I will just use private vars instead of x/y/z :)
View user's profile View All Posts By User
CicTec
DIV Pro
******




Posts: 471
Registered: 6-8-2016
Member Is Offline


[*] posted on 7-11-2017 at 05:03 PM


Quote: Originally posted by Casper  
Hey CicTec!

Thanks for taking a closer look, really appreciate it!

I will simplify my pointer access as you indicated, I think it got wonky because I was fighting compile errors and once it worked I just left it that way.

I'm happy that the new code has helped you solve problems and simplify things. :)

Quote: Originally posted by Casper  

I'm not sure using global counters is a good idea, since I have a lot of processes. If there are two instances of the same process, then every 'frame' they use the same counter it will cause problems, no? I will just use private vars instead of x/y/z :)

The best thing is to use PRIVATE variables, but the bug prevent you from using them as an index for access to sustructs, but you can use them safetly for cycles, so you could mix the use of global for substrusts and private for all other uses.
View user's profile View All Posts By User

  Go To Top

Powered by XMB
XMB Forum Software © 2001-2012 The XMB Group
[Queries: 18]