"Tractor" Python implementation
for loop

Use a for loop when iterating over a collection:

    for (x, y) in current_positions:
        moves.append((x, y))


for has less power than while (theoretically) and its simplicity makes it a better choice over while.

Avoid premature optimization

Just multiply by two:

n *= 2


Some tests:

&gt;&gt;&gt; import timeit
&gt;&gt;&gt; timeit.timeit("10 &lt;&lt; 1")
0.029866752000089036
&gt;&gt;&gt; timeit.timeit("10 * 2")
0.03209113599950797
&gt;&gt;&gt; 0.029866752000089036 / 0.03209113599950797
0.9306854079751793


&lt;&lt; is just 7% faster than *2

And the majority of your time is spent branching if x + step &lt;= a: and playing with lists moves.append((x, y)), so the final improvement would be tiny, not worth the loss in readability.

Optimizing the algorithm

Your algorithm has exponential time complexity:

print(step, len(current_positions))


Gives:

1 2
2 4
4 8
8 16
16 32
32 64
64 74
128 0


At each iteration, the number of current_positions is doubling, and this can get out of hand really quickly.

Arguments name

a and b are not acceptable argument names. I suggest width and height.

Some plotting always gives ideas

Following @ErikR suggestion, I made a graph of the reachable points and noticed a serious regularity, still doing graphs is a nice skill to have, so I encourage you to reproduce this graph by yourself.