g | x | w | all
Bytes Lang Time Link
220Python3250718T154858ZAjax1234
104Python 2210319T043600Zkops
048Charcoal210318T232712ZNeil
nanJ210318T011029ZJonah

Python3, 220 bytes

def f(p):
 d,n={},[]
 for x,y,X,Y in p:
  if X+Y:d[v]=d.get(v:=(x+X,y+Y),[])+[(x,y)]
  else:n+=[(x,y)]
 n+=[j for k in d for j in d[k]if len(d[k])>1]+[]
 return[i if len(d[a])>1 or a in n else a for a in d for i in d[a]]

Try it online!

Python 2, 127 112 104 bytes

def f(l):r=map(sum,l);exec"r=[[p,x][r.count(p)>1or[x+d,-d]in l]for p,[x,d]in zip(r,l)];"*len(l);return r

Try it online!

Takes input as a list of pairs of complex numbers, outputs a list of complex numbers. Initially has everyone walk unless they would swap and then repeatedly sends back anyone who collided until there are no collisions left.

-8 bytes thanks to xnor!

Charcoal, 48 bytes

Wφ«≔⁰φFθ¿∧§κ¹∨№θ⟦Σκ±§κ¹⟧⊖№EθΣλΣκ«≔⊟κφ⊞κ⁰»»Eθ⭆¹Σι

Try it online! Link is to verbose version of code. Takes input as an array of pairs of complex numbers and outputs a list of complex numbers. Explanation:

Wφ«

Repeat while a flag value is non-zero.

≔⁰φ

Zero out the flag value.

Fθ

Loop over the people.

¿∧§κ¹

If they want to move, and...

∨№θ⟦Σκ±§κ¹⟧

... they would be swapping with the person at their destination, or...

⊖№EθΣλΣκ«

... another person would end up at the same destination, then:

≔⊟κφ

Set the flag value by removing that person's desired movement, and...

⊞κ⁰

Replace their movement with standing still.

»»Eθ⭆¹Σι

Print the final positions. (I've printed them on separate lines as that's what Charcoal's default output should be, although Charcoal doesn't know how to output complex numbers, so I've had to cheat slightly. I could extend that cheat and simply output the whole list as a Python array which would save two bytes.)

J, 60 58 50 47 bytes

[:+/(*1,:1-(1<1#.+/=/+/)+{.(~:*[=i.{_,~])+/)^:_

Try it online!

Takes input as a matrix of complex numbers -- starting positions in the 1st row, steps to walk in the 2nd row.

Passes all test cases including those suggested by tsh and the cycle of 4 suggested by xnor.

tldr how

We iteratively adjust the steps to be 0 for impossible moves (same destination (1<1#.+/=/+/) or + swaps {.(~:*[=i.{_,~])+/) until they reach a fixed point ^:_. Iteration is needed because some steps only become illegal after a walker changes from someone who will move to someone standing still. There's a chain reaction.

After that iteration, impossible steps will have been converted to 0, and legal steps will remain what they were.

Once that's done, we just add those steps to the starting positions [:+/.