| 06-18-2006, 12:02 AM | #1 |
What's the difference between: JASS:function List_First takes location list returns location return GetLocationX(list) return 0. endfunction function List_IsEmpty takes location list returns boolean return (List_First(list)==null) endfunction and JASS:function List_First takes location list returns location return GetLocationX(list) return 0. endfunction function List_IsEmpty takes location list returns boolean local location first=List_First(list) local boolean r=(first==null) set first=null return r endfunction The difference is that the second one actually works and the first one will always return true |
| 06-18-2006, 12:38 AM | #2 |
http://www.wc3campaigns.net/showthread.php?t=83194 http://www.wc3campaigns.net/showthread.php?p=804603 Heh, you even posted in the latter. I've been thinking about rects again. What you could do is have one min/max pair be a min float and an arbitrary value, and the other min/max pair a pointer and type information. Since pointers are always positive you can flip the sign bit and use only positive numbers for type information then stash pointer in min and type in max. If you need both to be arbitrary values you can use min float in both to indicate it's arbitrary. If you want a double linked list type with static typing, you could put two pointers in Y and a minfloat and value in X. Edit: The really super strange thing about this bug is that warcraft *does* pass reals around in the regular integer registers. Apparently for some things it uses the floating point registers (like it should). Maybe there's a better way to force it into the integer register. Hm.. I bet something different happens on macs, any mac users care to test? |
| 06-18-2006, 03:43 PM | #3 |
Right its a terrible quirk. I do find it fun though to typecast booleans and then do something like if(b and not b)then call BJDebugMsg("THIS IS A SLAP IN THE FACE OF ALL LOGIC") endif The answer is pretty simple, if you look at my recursive thought test map I include a functioning cons car and cdr. Although my definition of null is different, as I personally define null as well null. I personally suggest putting the typecasting inside car and cdr, only because a less thoughtful user may forget the bug exist. Remember that you can extract values correctly! Only comparisons are flawed. local location r=cons(5,null) call BJDebugMsg(I2S(car(r))) if(car(r)==4)then call BJDebugMsg("WTF") endif Remember that in Scheme and Lisp it is an error to call car or cdr on null, so while this may cause war3 to crash you are technically inline :trisomy: Anyway, Pipedream I think hijacking a rect wouldn't be bad for a typed list. Assuming we have haskell like typed list we then only need three things: type of car, car,cdr. Car and cdr will be stored in the max x, and max y, and the type could just use the min y, since max y is always a handle. If max x is negative we will get its absolute value and store its sign bit in min x. This should solve all our woes, although locations should be pretty suffecient otherwise. I think its glorious that we've moved on from just abusing the gamecache, and now are truly messing up warcraft III by overtly using the return bug to hijack data structures. |
| 06-18-2006, 04:03 PM | #4 |
The question sounds dumb: Does the location named first actually exist? |
| 06-18-2006, 07:39 PM | #5 |
Read my post please, the value it extracts is the right one. It's the comparison that is flawed. As my code example was demoing that would print five, but it would also somehow say that it's value was 4 (which is horribly wrong). |
| 06-18-2006, 07:43 PM | #6 |
pipedream: are you sure about it failing when comparing it to 0? (as acording to your post?) JASS:function List_FirstI takes location l returns integer return GetLocationX(l) return 0 endfunction function List_FirstIH takes location l returns handle return List_FirstI(l) return null endfunction //works function List_IsEmpty takes location list returns boolean return (List_FirstIH(list)==null) endfunction //also works function List_IsEmpty takes location list returns boolean return (List_FirstI(list)==0) endfunction |
| 06-18-2006, 07:54 PM | #7 |
I do not understand. Qas this an answer to my question? |
| 06-18-2006, 07:59 PM | #8 |
Another one that works: JASS:function List_IsEmpty takes location list returns boolean return (GetLocationX(list)==CS_h2r(null)) endfunction = bert: Yes it does exist. |
| 06-18-2006, 11:49 PM | #9 |
My tests showed that comparisons always returned true. However, since it seems to have something to do with registers mixing up, I expect the result is pretty well undefined and just depends on what was there beforehand. I don't understand this at all. Here's the end of GetLocationX: Code:
.text:6F2ADA14 mov eax, [edi+24h] ; edi must contain handle. +0x24 is X, +0x28 is Y .text:6F2ADA17 pop edi .text:6F2ADA18 pop ebx .text:6F2ADA19 mov esp, ebp .text:6F2ADA1B pop ebp .text:6F2ADA1C retn .text:6F2ADA1C GetLocationX endp On an unrelated note, also from GetLocationX/Y: Code:
.text:6F2E0B90 push ebp .text:6F2E0B91 mov ebp, esp .text:6F2E0B93 mov edx, [ebp+arg_0] .text:6F2E0B96 test edx, edx .text:6F2E0B98 mov eax, ecx .text:6F2E0B9A mov [eax], edx .text:6F2E0B9C jz short loc_6F2E0BA1 .text:6F2E0B9E inc dword ptr [edx+4] .text:6F2E0BA1 .text:6F2E0BA1 loc_6F2E0BA1: ; CODE XREF: sub_6F2E0B90+Cj .text:6F2E0BA1 pop ebp .text:6F2E0BA2 retn 4 .text:6F2E0BA2 sub_6F2E0B90 endp Code:
.text:6F2E0320 sub_6F2E0320 proc near ; CODE XREF: MoveLocation+81p .text:6F2E0320 ; GetLocationX+87p ... .text:6F2E0320 mov ecx, [ecx] .text:6F2E0322 test ecx, ecx .text:6F2E0324 jz short locret_6F2E032F .text:6F2E0326 dec dword ptr [ecx+4] .text:6F2E0329 jnz short locret_6F2E032F .text:6F2E032B mov eax, [ecx] .text:6F2E032D jmp dword ptr [eax] .text:6F2E032F ; --------------------------------------------------------------------------- .text:6F2E032F .text:6F2E032F locret_6F2E032F: ; CODE XREF: sub_6F2E0320+4j .text:6F2E032F ; sub_6F2E0320+9j .text:6F2E032F retn .text:6F2E032F sub_6F2E0320 endp |
| 06-28-2006, 01:36 AM | #10 | |
Quote:
|
| 06-28-2006, 01:58 AM | #11 |
All right: works:function List_IsEmpty takes location list returns boolean return not(List_First(list)!=null) endfunction does not work:function List_IsEmpty takes location list returns boolean return (List_First(list)==null) endfunction The new question is : Why is that the == operator is bugged? |
| 06-28-2006, 02:43 AM | #12 |
It looks like blizzard does all in game floating point with a homegrown emulator. I'm guessing that it gets confused as to which internal compare function to use. Not, like assignment, changes that type information properly. |
| 06-28-2006, 03:01 AM | #13 |
Actually, just != seems to be returning things correctly I added the not so it works. edit: Does not work:function List_IsEmpty takes location list returns boolean return not not(List_First(list)==null) endfunction |
| 06-28-2006, 03:19 AM | #14 |
Huh.. maybe it's related to the IsUnitType bug. In game or I'd test. |
| 06-28-2006, 04:20 AM | #15 |
It could be that JASS doesn't allow you to use functions that don't return primitive data types. The very first function is returning a location and the second function is trying to directly use the location in its return line. However, by using a local variable to store the same information, the second function returns the boolean just fine, or at least this is what I think is happening. I could be wrong about this, but this is the only explanation I could think of. Edit: Or it could be that the function GetLocationX returns a real and not a location so the program is reading it as null because it doesn't return anything. Also, the other functions work because they become casted into either an integer or a handle as they're being returned (just a thought). |
