Odd SE problem - need help ! [solved]
Moderators: Moderators for English X Forum, Scripting / Modding Moderators
Odd SE problem - need help ! [solved]
After a script call with return variable $c and parameters $a and $b, the value of parameter $b has changed.
How is this possible?
Cheers Euclid
Edit: solved - please scroll down. E.
How is this possible?
Cheers Euclid
Edit: solved - please scroll down. E.
Last edited by euclid on Sat, 18. Nov 06, 02:24, edited 1 time in total.
you cant pass value by reference in scripts.
but there are 2 ways you can do it, add the values to the array and pass the array, the arrays should be passed by reference.
the other way is to use global or local varibles
but there are 2 ways you can do it, add the values to the array and pass the array, the arrays should be passed by reference.
the other way is to use global or local varibles
Code: Select all
set global varible 'b' value = 1
$c = call script 'script' a = $a
$b = global varible 'b'
I'm not sure what you mean.
The return variable $c has the correct value so the script call works. However the values of $h and $b have changed; not $a though.
IMHO the value of the parameters $a and $b should not be altered by the script call.
Or am I wrong?
Cheers Euclid
Code: Select all
008 $h = $b
009 write to player logbook $b
010 write to player logbook $h
011 @ $c = [THIS] -> call script 'divide' : integer or floating point array=$a integer or floating point array=$b
012 write to player logbook $b
013 write to player logbook $h
IMHO the value of the parameters $a and $b should not be altered by the script call.
Or am I wrong?
Cheers Euclid
It is utterly strange. The script 'divide' (part of my floating point math lib) seems to cause a change of the value of the second parameter.
The simple test script
run on null gives log entries in chronological order:
>>
x=39 and y=ARRAY(1,11,0) before divide call
After divide call: x=39, y=ARRAY(1,909090909,0) and z=ARRAY(1,354545453,-8)
<<
Clearly the script call has changed the script parameter y from (1,11,0) to (1,909090909,1). Strange thing is that the number at $y[1]$ is computed in by the script 'divide' as part of 1/11 = 909090909E-10.
Only the second parameter causes trouble and only if it is an array.
Very odd !!
Cheers Euclid
The simple test script
Code: Select all
001 $x = 39
002 $y = 11
003 @ $a = [THIS] -> call script 'int2float' : integer=$y
004 $mes = 'x= %s and y= %s before divide call'
005 write to player logbook: printf: fmt=$mes, $x, $a, null, null, null
006 @ $z = [THIS] -> call script 'divide' : integer or floating point array=$x integer or floating point array=$a
007 $mes = 'After divide call: x= %s , y= %s and z= %s'
008 write to player logbook: printf: fmt=$mes, $x, $a, $z, null, null
009 return null
>>
x=39 and y=ARRAY(1,11,0) before divide call
After divide call: x=39, y=ARRAY(1,909090909,0) and z=ARRAY(1,354545453,-8)
<<
Clearly the script call has changed the script parameter y from (1,11,0) to (1,909090909,1). Strange thing is that the number at $y[1]$ is computed in by the script 'divide' as part of 1/11 = 909090909E-10.
Only the second parameter causes trouble and only if it is an array.
Very odd !!
Cheers Euclid
looking throught the int2float
the lines 004 and 005 are confusing...
i think you are trying to suggest negative numbers... {$s = (negative) -1)
which you cannot do with the 'subtract (-)' command
is this correct?
the lines 004 and 005 are confusing...
Code: Select all
001 $a = array alloc: size=3
002 $s = 1
003 if $num < 0
004 $s = - 1
005 $num = - $num
006 end
...
which you cannot do with the 'subtract (-)' command
is this correct?
Uhm, so just to get that right:Cycrow wrote:Well, arrays are passed by reference, so if you change the array in the calling script, it will change in the parent.....
Say, I have an array $y in the main script. If this main script calles a subscript where also the name $y is used and the value gets changed there, then the value is also changed in the main script?
Cheers Euclid
what i ment, is if you passs the array to the subscript and change the array in the subscript, it will change in the calling script as well.
simply using the same varible names shouldn't cause the change.
thats y it would help to see the divide script, to c if theres anything there that might be changing the value
simply using the same varible names shouldn't cause the change.
thats y it would help to see the divide script, to c if theres anything there that might be changing the value
Originally I've used $q in the divide script but to trace the bug I've changed that to:
Still the same.
Cheers Euclid
Code: Select all
Arguments
1: p , Var/Number , 'integer or floating point array'
2: q , Var/Number , ' integer or floating point array'
Source Text
001 $s = size of array $p
002 $pp = $p
003 skip if $s > 1
004 @ $pp = [THIS] -> call script 'int2float' : integer=$p
005 $s = size of array $q
006 $qq = $q
007 skip if $s > 1
008 @ $qq = [THIS] -> call script 'int2float' : integer=$q
009 * gcd first
010 $s = $pp[1]
011 $t = $qq[1]
012 @ $g = [THIS] -> call script 'gcd' : first number=$s second number=$t output as array=[TRUE]
013 $pp[1] = $g[1]
014 $qq[1] = $g[2]
015 * gcd ends
016 $s = $qq[1]
017 @ $bb = [THIS] -> call script 'invert' : integer=$s
018 $qq[1] = $bb[1]
019 $s = $bb[2]
020 $t = $qq[2]
021 $t = $s - $t
022 $qq[2] = $t
023 @ $bb = [THIS] -> call script 'prod' : number 1=$pp number 2=$qq
024 return $bb
Cheers Euclid
Sorry for being so slow (was chasing this bug through the night) but it took a chat with AalaarDB (big thanks) to set my head straight.Cycrow wrote:Well, arrays are passed by reference, so if you change the array in the calling script, it will change in the parent.....
'arrays are passed by reference......strings and numbers by their value.'
Everbody kept saying that and didn't get it. But now it makes sense to me and maybe the following prevent some from chasing this 'bug' (more a feature?) like I did :
Passing can be done in various ways for example $A=$B is passing $B to $A.
Also script calls pass their parameters to the called script. For example this..
@ $c = [THIS] -> call script 'prod' : number 1=$a number 2=$b
...script call has 2 parameters $a and $b which are passed to the called script's arguments (inputs). The called script returns the result $c.
And, of course you can use these parameters within the script (arguments). In fact you do use these because you would not expect that changes made in the subscript are passed back to the parameters of the called subscript.
Why would $a or $b have changed after the script call above?
If the passed objects are strings or numbers then the above script call will not change $a and $b. But this is not so for arrays.
While for strings & numbers $A=$B copies $B to A$ for arrays only a reference (to the parameter in the calling script) is forwarded from $B to $A. So any changes made in $A will be back referenced via $B to the source array (in the above case the parameters $a and $b of the called script).
In fact, one could return the result $c without the '$return$c' in the called script by
@ [THIS] -> call script 'prod' : number 1=$a number 2=$b
and pass in 'prod' the result to $a.
But in some case (*sigh*) one likes to keep $a and $b so how to prevent that 'overwriting by reference'?
In the subscript the inputs (arguments) containing the reference have to be cloned first
$n = size of array $a
$n = n - 1
$ca = clone array $a: index 0 ...$n
....
....
and then the clones $ca,.. are used rather than the reference carrier $a and $b.
So, thanks again for your input (back to work.......)
Cheers Euclid
yeah i can c where you made the mistake.
i guess it helps to understand how pointers work in C/C++
its all about memory addresses, ur simply changing whats in a set memory space.
the main difference with scripting and C, is that certain values are always like pointers, but in C you can choose if they are value or pointers
i guess it helps to understand how pointers work in C/C++
its all about memory addresses, ur simply changing whats in a set memory space.
the main difference with scripting and C, is that certain values are always like pointers, but in C you can choose if they are value or pointers
Yes, 'by value' means 'make a copy', while 'by reference' is like 'this name refers to that variable'. By reference avoids the copy and is thus more efficient way to pass arguments. But then, like in this case, one may need an additional temporary variable.
References can lead to 'aliasing'. A wonderful way to shoot oneself into foot.
Try passing the same array as both arguments to your unfixed 'divide'. By now you should be able to deduce what will happen. Fortran has never even allowed that. C99 standard added argument qualifiers to prevent it.
I guess the SE lacks 'const reference'.
References can lead to 'aliasing'. A wonderful way to shoot oneself into foot.
Try passing the same array as both arguments to your unfixed 'divide'. By now you should be able to deduce what will happen. Fortran has never even allowed that. C99 standard added argument qualifiers to prevent it.
I guess the SE lacks 'const reference'.
the global varible also holds the reference of to the array.
so you can assign it to a varible and have another script use the array without it having to be passed in the first place.
also, any changes to the array are saved.
if you do something like
Script 1:
then another complety seperate scripts can also access the array.
Script 2:
you will find that the size from the first script is 3 after the call script.
remember the global varibles only store the reference, if you set the varible to something else, it wont effect the array, only the references thats stored in the global varible
so you can assign it to a varible and have another script use the array without it having to be passed in the first place.
also, any changes to the array are saved.
if you do something like
Script 1:
Code: Select all
$array = alloc array: size = 2
set global varible 'mu.array' balue = $array
= call script 'script 2'
$size = size of array $array
Script 2:
Code: Select all
$array = get global varible 'my.array'
append $value to array $array
remember the global varibles only store the reference, if you set the varible to something else, it wont effect the array, only the references thats stored in the global varible
Thanks Cycrow,
It's about Gnasirator's MK3 optimization.
The array $Stats (global variable plugin.autotrade.stats) is read correctly only once. Second read (get global variable) it contains zeros.
I wonder if this could be due to an overwrite by reference?
Cheers Euclid
It's about Gnasirator's MK3 optimization.
Code: Select all
001 * Init
002 $gained.total.delta = 0
003 $gained.total.delta.perHour = 0
004 $gained.total.perHour = 0
005 $timestamp = get global variable: name='plugin.autotrade.timestamp'
006 $timestamp.now = playing time
007 skip if $timestamp
008 $timestamp = $timestamp.now
009 $Stats = get global variable: name='plugin.autotrade.stats'
010 $PageID = get global variable: name='autotrade.PageID'
011 $log = null
012
013 * Spielerschiffe finden und UniTrader filtern
014 $traders = get ship array: of race Player class/type=null
015 $size.traders = size of array $traders
016
017 while $size.traders
018 *= wait randomly from 1 to 3 ms
019 dec $size.traders =
020 $test.ship = $traders[$size.traders]
021 $exp = $test.ship -> get local variable: name='experience'
022 $mk3 = $test.ship -> get amount of ware Handelssoftware Mk3 in cargo bay
023 skip if $mk3 AND $exp
024 remove element from array $traders at index $size.traders
025 end
026
027 if size of array $traders
028 $size.traders = size of array $traders
029 $data = array alloc: size=2
030 $stats.new = array alloc: size=$size.traders
031 $i = 0
032
033 while $i < $size.traders
034 @ = wait randomly from 50 to 150 ms
035 $test.ship = $traders[$i]
036 $trader.new.gained = $test.ship -> get local variable: name='Gain'
037 $data[0] = $test.ship
038 $data[1] = $trader.new.gained
039 $stats.new[$i] = $data
040 inc $i =
041 end
042
043 * Array stats.new enthaelt nun alle aktuellen MK3 Haendler und deren Gained
044
045 * Beinhaltet den gesamten verdienst seit beginn jeglicher unitrader
046 $gained.total = 0
047 * stats.new jetzt schon speichern, da es nun veraendert wird.
048 gosub refresh
049 * Erste Ausfuhrung der Statistikfunktion
050 if $Stats != null
051 $size.stats.new = size of array $stats.new
052 * Alten und neuen Array vergleichen, ob noch dieselben Schiffe vorhanden sind
053
054 while $size.stats.new
055 @ = wait randomly from 50 to 150 ms
056 dec $size.stats.new =
057 $test.ship = $stats.new[$size.stats.new][0]
058 $tempgained = $test.ship -> get local variable: name='Gain'
059 $gained.total = $gained.total + $tempgained
060
061 * returns -1 if not found
062 *$index.in.oldstats = get index of $test.ship in array $Stats offset=-1 + 1
063 $size.stats.old = size of array $Stats
064 $index.in.oldstats = -1
065 while $size.stats.old AND $index.in.oldstats < 0
066 dec $size.stats.old =
067 @ = wait randomly from 50 to 150 ms
068 $test.ship.old = $Stats[$size.stats.old][0]
069 skip if not $test.ship.old AND $test.ship.old == $test.ship
070 $index.in.oldstats = $size.stats.old
071 end
072
073 if $index.in.oldstats >= 0
074 $trader.old.gained = $Stats[$index.in.oldstats][1]
075 $test.ship.old = $Stats[$index.in.oldstats][0]
076 $trader.new.gained = $stats.new[$size.stats.new][1]
077 $trader.new.gained = $trader.new.gained - $trader.old.gained
078 $stats.new[$size.stats.new][1] = $trader.new.gained
079 end
080 end
081 end
082
083 * Zwischenstand:
084 * Alle in Stats enthaltenen Schiffe sind auch in stats.new
085 * Gained neu = Gained neu - Gained alt
086 * Neue Schiffe sind in stats.new aber nicht in Stats
087
088 calculate:
089 * Time
090 $time.diff = $timestamp.now - $timestamp
091 $time.diff.secs = $time.diff mod 60
092 $time.diff.min = ( $time.diff mod 3600 ) / 60
093 $time.diff.hour = $time.diff / 3600
094 $timestamp.sec = $timestamp.now mod 60
095 $timestamp.min = ( $timestamp.now mod 3600 ) / 60
096 $timestamp.hour = $timestamp.now / 3600
097 * Beinhalten den Gesamtverdienst seit letzter Statistikabfrage
098 $gained.total.delta = 0
099
100 $size.stats.new = size of array $stats.new
101 $i = 0
102 while $i < $size.stats.new
103 $tempgained = $stats.new[$i][1]
104 $gained.total.delta = $gained.total.delta + $tempgained
105 inc $i =
106 end
107 $gained.total.delta.perHour = $gained.total.delta / $time.diff * 3600
108 skip if $gained.total.delta.perHour
109 $gained.total.delta.perHour = 0
110 $gained.total.perHour = $gained.total / $timestamp.now * 3600
111 end
112 * end if traders
113
114 endit:
115 gosub output
116 return null
117
118 output:
119 if $timestamp > 0
120 $log = sprintf: pageid=$PageID textid=300, $time.diff.hour, $time.diff.min, $time.diff.secs, null, null
121 else
122 $log = sprintf: pageid=$PageID textid=301, null, null, null, null, null
123 end
124 $dummy = sprintf: pageid=$PageID textid=303, $timestamp.hour, $timestamp.min, $timestamp.sec, null, null
125 $log = $log + $dummy
126 $dummy = sprintf: pageid=$PageID textid=302, $gained.total, $gained.total.delta, $gained.total.perHour, $gained.total.delta.perHour, null
127 $log = $log + $dummy
128 write to player logbook $log
129 endsub
130 return null
131
132 breakpoint:
133 [THIS] -> set destination to [PLAYERSHIP]
134 @ = wait 10000 ms
135 $data = $stats.new[0]
136 $data = $Stats[0]
137 endsub
138 return null
139
140 refresh:
141 set global variable: name='plugin.autotrade.timestamp' value=$timestamp.now
142 gosub breakpoint
143 set global variable: name='plugin.autotrade.stats' value=$stats.new
144 endsub
145 return null
146
147 failure:
148 write to player logbook 'Statistikfehler'
149 return null
I wonder if this could be due to an overwrite by reference?
Cheers Euclid