The reason this happens is quite obvious if you step through the code. x = i - .5 means that for each point it will be a little further across in the x-axis. with your s = -s you are alternating successive points between s and -s in the y axis. putting the two together creates a zig-zag, sawtooth wave... whatever you want to call it. by using the (pretty wasteful i might add) n = w you are creating one which is so dense that it appears to be a solid rectangle.
by convenience n = w is the exact amount needed for it to break down like this since you are covering half the width of the screen with w/2 points per side of rectangle. e.g. each subsequent point is so close on the x axis that the point moves one pixel to the left for every two points evaluated. the only reason for it to not look perfect is rounding errors, since the n = w/2 means each point is half a pixel infront of the other. n = w+2 pushes it past the magic point of w/2 and so there is no chance of a visible artefact from a rounding error. such artefacts are still there but the zig-zag is so dense that they always get drawn over.
a better way to do this is to work out a single pixel width per frame then, still using s = -s for y, incrementing x manually with this width only when s is +ve or -ve (which ever you choose will probably not matter) you can then skip redundant lines too.
per frame:
ix = .5/w
xi = -.5
per point:
s=-s;
xi = if(above(s,0),xi + ix,xi);
x = xi;
y = s;
(untested since i am at work)
an even better way to draw a solid rectangle is with triangle.ape :P