PenUltima Online Forum Index Official Core: 096.7
Official Core: 097 2008-02-26
Donate towards the POL web hosting bill!
 POL Home   FAQ   Search    Memberlist   Usergroups    Register    Profile   Log in to check your private messages   Log in
Whats the best structure for the include files

 
Post new topic   Reply to topic    PenUltima Online Forum Index -> General Help (095)
Display posts from previous:   

Author Message
Ventura



Joined: 09 Sep 2006
Posts: 7

PostPosted: Sat Nov 04, 2006 2:27 pm    Post subject: Whats the best structure for the include files Reply with quote

Im having trouble with include files when i declare 1 include in more then 1 script,ex: include"include/classes"; its saying that i already have declare the constants of that include file in another script....
whats the best include files structure?
plz give me a example of how to create include files and not have this problem....

Author Message
CWO



Joined: 04 Feb 2006
Posts: 685
Location: Chicago, IL USA

PostPosted: Sat Nov 04, 2006 6:58 pm    Post subject: Reply with quote

Best way to prevent that is to:

A: Make sure you don't have duplicate constant names.
B: Don't include inside of includes.

Author Message
Marilla



Joined: 02 Feb 2006
Posts: 329

PostPosted: Sat Nov 04, 2006 7:26 pm    Post subject: Reply with quote

CWO's A: is right on the mark; You should -never- declare the same constants in multiple files. Unfortunately, not all scripters have done this; specifically, many scripters will purposefully declare a constant in one file to avoid having to include another file. Personally, I think that's missing the point of includes and constants in the first place (to have 'magic' values set in one, central location so that you can change the values but only need to do so in one place)

You can avoid declaring the same const twice using one of two methods:

1) Declare the const only ever in one file, and include that file in ALL scripts that need that constant, no matter if a single constant is the only thing you are using from that include. eCompile completely ignores any code which is not used in an include when compiling, so you are NOT increasing the size of your compiled scripts by doing this. However, if you frequently find yourself including a file merely to get a couple constant values, and not for any other functions, you should consider splitting your constants into a separate include.

2) Slightly alter the name of the constant in 'secondary' declarations of it. Say, for example, you really, really, really want to avoid having to include client.inc just to get FONT_NORMAL. Do NOT declare a 'FONT_NORMAL' in your script. Instead, declare, [SCRIPTNAME]_FONT_NORMAL. This way, even if you later do decide to include client.inc, your constant will not collide.

I much prefer the first solution, because it avoids unnecessarily declaring constants that have already been declared elsewhere.



If you avoid ever declaring constants with the same name in multiple files, you should not need to worry so much about CWO's B:. Of course, in order for that to be true, you should also use the same principle with function names: Never use the same function names in multiple include files... NEVER! Again, if you have a function that you need, just include the file it's in. Making a separate copy of it just to avoid including a file is avoiding the whole point of includes in the first place. And, again, eCompile is able to optimize these includes - it does NOT include code that it has no calls for. You can verify this by having a validly declared function that nevertheless has some syntax error in it... if that function is not called anywhere at all, eCompile won't complain, because it's not even reading the body of that function.


I would actually go so far as to suggest that it may be very, very difficult, and probably not particularly useful, to try to actually never have includes included from within other includes. As long as you avoid variable, constant and function name collisions, there is no reason at all you can't have all the cross-including you want. Note that unlike compilers for other languages, eCompile will recognize when a file has been included more than once, and will not attempt to do so again.

(There is an except with eCompile for 095, but unless someone asks, I won't clutter up this post with that info!)

Author Message
Marilla



Joined: 02 Feb 2006
Posts: 329

PostPosted: Sat Nov 04, 2006 7:36 pm    Post subject: Reply with quote

Umm... I just realized; this IS the 095 help forum! So, let me explain that caveat to the above!

There are two (maybe three) different ways that eCompile can find your include files, based on how you write the include statement. One is the :package:file format, and the other is simply the normal directory/filename format. For example:

Code:

include ":mypackage:myinclude";
include "../pkg/mypackage/myinclude";


If you did that in a script/include, eCompile would actually think those are two different files, and it would include them 'both', resulting in name collisions on every single item in that file. Of course, you wouldn't include the file twice in the same file! But you might include it once one way in your script, and once another way in another include.

I said there might be three ways; I'm not sure if eCompile treats the simple 'file name' include method differently or not. That is:

Code:

include "myinclude";


Anyway, on 095, you should do your best to make sure that each individual include file is always included using the same syntax wherever it may be included, so that eCompile is able to recognize the multiple includes as pointing to the same file.

For instance, if you had an include file /pkg/mypkg/myinc.inc
Code:

const MY_COOL_CONST := 1;


You could actually put this line in -every single script and include- on your shard, and everything would work fine:

Code:

include ":mypkg:myinc";


But if you have one include somewhere that does this instead:

Code:

include "../pkg/mypkg/myinc";


You will get trouble with collisions on the name.


Finally, the current 096 and 097 cores' eCompiles no longer have this problem; they will recognize when you are including the same file, even if you do so by different methods. However, I still recommend always using the same method (and the method I recommend is the :package:file format, now)

Author Message
Ventura



Joined: 09 Sep 2006
Posts: 7

PostPosted: Sun Nov 05, 2006 1:47 am    Post subject: Reply with quote

Thanks a lot !!! nice tutorial Cool

Author Message
CWO



Joined: 04 Feb 2006
Posts: 685
Location: Chicago, IL USA

PostPosted: Sun Nov 05, 2006 2:42 am    Post subject: Reply with quote

Another cool thing that you can do with constants and includes is using the pre-processing done by eCompile using constants and conditional (if) statements. I'm actually doing this in my AI since AI is mostly the same but has different settings. Something like this:

Code:


const ENABLETHIS := 1;

program myscript(params)
  if (ENABLETHIS)
    DoThisFunction(params);
  endif
endprogram



Doing that, yes ENABLETHIS has a value so DoThisFunction will be compiled in the script. But if you did this:

Code:


const ENABLETHIS := 0;

program myscript(params)
  if (ENABLETHIS)
    DoThisFunction(params);
  endif
endprogram



This script will actually basically compile empty. eCompile looks for conditions like this to see if its including that function code or not. This is invaluable to do something like AI since you can have code and functions within a universally used function but enable/disable blocks of it by constants which will be put there or eliminated by eCompile itself. Even the IF statement isnt compiled with it if its false so your server never has to even run over that conditional statement and figure out where its jumping because its false.

Author Message
Marilla



Joined: 02 Feb 2006
Posts: 329

PostPosted: Sun Nov 05, 2006 8:26 pm    Post subject: Reply with quote

Yup! Put another way, constants which are tested ALONE in a conditional can serve as conditional compilation.

For instance, you could use it to have debug information printed for your combat system, but only when your const TESTING == 1. To publish your code to production, simply change the constant and recompile.

It's important that if you do this, the only thing being tested in your IF() is the constant value... if anything else is involved in the test condition, eCompile can not know the result, and must include all the code.

But as long as that is ALL you are testing in your conditional statements, eCompile will leave anything out when you test for a const that is 0, such as:

Code:

use uo;
const TESTING := 0;
program test(who)
   var what := 1;
   if (TESTING)
      what := 2;
   endif
   print(what);
endprogram


With the code above, since TESTING == 0, the whole "if (testing) what:=2; endif might as well not be there at all. Here's the 'lst' contents of compiling the above:
Code:

d:\pol\scripts\textcmd\coun\const0.src, Line 5
program test(who)
const TESTING := 0;
0: get arg 'who'
var what := 1;
1: decl local #1
2: 1L
3: :=
4: #
print(what);
5: local #1
6: Func(1,0): print
7: #
8: leave block(2)
9: progend

There is absolutely no hint at all of the IF (TESTING) or the what:=2 there.

Now if we just remove the const stuff entirely, as we might otherwise in a 'testing' situation, we might have this code:
Code:

use uo;
program test(who)
   var what := 1;
   print(what);
endprogram


This code produces the following lst: Note that it is almost exactly the same as the above!
Code:

d:\pol\scripts\textcmd\coun\empty.src, Line 3
program test(who)
use uo;
0: get arg 'who'
var what := 1;
1: decl local #1
2: 1L
3: :=
4: #
print(what);
5: local #1
6: Func(1,0): print
7: #
8: leave block(2)
9: progend


It's essentially exactly the same as the code with the TESTING == 0. What if TESTING==1? This is the resulting lst:
Code:

d:\pol\scripts\textcmd\coun\const1.src, Line 5
program test(who)
const TESTING := 1;
0: get arg 'who'
var what := 1;
1: decl local #1
2: 1L
3: :=
4: #
what := 2;
5: 2L
6: local1 :=
print(what);
7: local #1
8: Func(1,0): print
9: #
10: leave block(2)
11: progend

See the additional code there, where it sets what:=2? But you might notice something missing... What if we had TESTING as a VAR, instead of a CONST? This is the resulting lst:
Code:

d:\pol\scripts\textcmd\coun\var1.src, Line 3
var TESTING := 1;
0: decl global #0
1: 1L
2: :=
3: #
d:\pol\scripts\textcmd\coun\var1.src, Line 5
program test(who)
4: get arg 'who'
var what := 1;
5: decl local #1
6: 1L
7: :=
8: #
if (TESTING)
9: global #0
10: if false goto 13
what := 2;
11: 2L
12: local1 :=
print(what);
13: local #1
14: Func(1,0): print
15: #
16: leave block(2)
17: progend


Note: Now you can see the IF(TESTING) conditional that it has to keep in the code. Keep in mind all three of the above code are exactly the same, except for the value of 'TESTING', and whether it is a VAR or a CONST.

Clearly, eCompile itself is evaluating IF statements against a CONST, and conditionally compiling based on that. It completely leaves out code that would never run anyway, and it actually even leaves out the conditional itself from the code. If the const evaluates to 'true', it simply outputs the appropriate code into the compiled ecl, as if there was no conditional at all. (That is, exactly like 'conditional compilation' through pre-processor directives would do).


There is one caveat to this, however; You cannot declare a variable within the 'block' of code inside any of those conditionals, on the assumption that eCompile is just removing those blocks. It -IS- removing those blocks, however, it still does not permit the code to compile. An example. Say we adjusted the above example to this:

Code:

use uo;

const TESTING := 0;

program test(who)
   var what;
   if (TESTING)
      what := 2;
   else
      what := 0;
   endif
   print(what);
endprogram

This compiles and runs fine. Since TESTING==0, the whole 'testing' IF is left out, and the code that sets what:=0 is simply run. Here's the lst:
Code:

d:\pol\scripts\textcmd\coun\const0.src, Line 5
program test(who)
const TESTING := 0;
0: get arg 'who'
var what;
1: decl local #1
2: #
what := 0;
3: 0L
4: local1 :=
print(what);
5: local #1
6: Func(1,0): print
7: #
8: leave block(2)
9: progend

So, you might be tempted to think; Well, if eCompile is not creating a code block for the IF test, can I just declare the WHAT var within those blocks, like so?
Code:

use uo;
const TESTING := 0;
program test(who)
   if (TESTING)
      var what := 2;
   else
      var what := 0;
   endif
   print(what);
endprogram


This looks like it won't work, and you are right. It won't work:
Code:
Variable what has not been declared on line 11.


Even though eCompile does collapse that block, it apparently does not do that until AFTER it has checked to be sure all the variables are in proper scope in the blocks and such. This makes sense, since eCompile probably has to examine a lot of the structure of a function before it can be sure that conditionals testing a const are ONLY testing a const, and not somewhere down the line testing a variable or function return value, also. So, the above has to be written as originally.

Post new topic   Reply to topic    PenUltima Online Forum Index -> General Help (095) All times are GMT - 4 Hours
Page 1 of 1

 




Powered by phpBB © 2001, 2005 phpBB Group :: Theme & Graphics by GHS & Scott E. Royalty