简体   繁体   中英

Checking if two tiles are touching and are adjacent in NASM Assembly

Suppose that I have a 2D array, and I want to check whether one slot is adjacent and touching with another.

Suppose that the coordinates are in the 4-byte variables: OneX , OneY , TwoX , TwoY .

The solution I had for a while was that if you have the differences OneX - OneY and TwoX - TwoY and add them, if the result is either 1 or -1 , then yes, the slots are adjacent and touching.

mov EBX,[oneX]
sub EBX,[oneY]
mov ECX,[twoX]
sub ECX,[twoY]
add EBX,ECX
; Compare EBX with 1 or -1.......

This almost works. But no - given a format (x,y), take: (3,3) and (0,1). They're clearly not adjacent nor touching, but the function will say they are.

The question at Get adjacent elements in a two-dimensional array? is somewhat useful, but it focuses on finding all adjacent matches, whereas I want to check for two specific slots instead.

The structure of my array is like this:

map: dd 'a','b','c','d'  ; Double words just to make my life easier

Which is interpreted like

a b
c d

It's a square map.

There is no reason to Add them! And you are also substracting incorrect variables :).

You have to have two conditions OneX - TwoX and OneY - TwoY : both has to be 1, 0 or -1.

For example One is [4,5] and Two is [5,5] >= OneX - TwoX = -1 and OneY - TwoY = 0 => it is adjanced tile.

EDIT : For non-diagonal, there are two approaches :

a)One of condition must be 0 and the other one must be 1 or -1

b)Adding absolute value of OneX - TwoX and absolute value of OneY - TwoY must be 1

Here is some practical code, based on @libik answer:

Optimized for speed:

; eax = OneX-TwoX; ecx = OneY-TwoY
        mov    eax, [OneX]
        mov    ecx, [OneY]
        sub    eax, [TwoX]
        sub    ecx, [TwoY]

; eax = abs(eax); ecx=abs(ecx)
        mov    ebx, eax
        mov    edx, ecx
        sar    ebx, 31
        sar    edx, 31
        xor    eax, ebx
        xor    ecx, edx
        sub    eax, ebx
        sub    ecx, edx

; eax=abs(delta1)+abs(delta2); if eax = 1, jump to where needed
        add    eax, ecx
        dec    eax
        lz     .adjacent 

Optimized for size:

; eax = abs(OneX-TwoX); ecx = abs(OneY-TwoY)
        mov    eax, [OneX]
        mov    ecx, [OneY]
        sub    eax, [TwoX]
        jns    @f
        neg    eax
@@:
        sub    ecx, [TwoY]
        jns    @f
        neg    ecx
@@:
; eax=abs(delta1)+abs(delta2); if eax = 1, jump to where needed
        add    eax, ecx
        dec    eax
        lz     .adjacent 

Including diagonal cases

Replace add eax, ecx with or eax, ecx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM