Jump to content
Jet Set Willy & Manic Miner Community

Fixing the 'Ramps vs Walls' Bug


IRF

Recommended Posts

http://skoolkid.github.io/jetsetwilly/reference/facts.html#rampsVsWalls

 

Some preliminary thoughts:

 

When Willy is walking up a ramp, add an additional check for an Earth block (and RET if one is encountered):

 

- When Willy is walking left, the check should be made at (x,y-1);

- When Willy is walking right, the check should be made at (x+1,y-1);

 

where (x,y) are the coordinates of the top-left cell occupied by Willy's sprite prior to him crossing the cell boundary.

 

****

 

When Willy is walking down a ramp, the simple solution would be to block his progress is there is an Earth block ahead of his sprite and two cell-rows below. But that doesn't seem logical. In the example seen in 'On Top of the House', I feel the most realistic solution would be for Willy to simply step onto the block at the base of the ramp. But that would require amendments to two different routines:

 

(1) Edit the routine at #95C8 - after the check for a ramp cell under Willy's back foot, add an additional check for an Earth block under Willy's front foot (perform an XOR 01 on the L register, load the Earth attribute to A, and then do a CP (HL) / JP Z,#95F8 - all to be inserted in between the commands at #95DC and #95DE). So if Willy is standing on a ramp cell and an Earth block simultaneously, then the 'solidity' of the Earth block will take precedence over the 'downward pull' of the ramp cell* when deciding where to draw Willy;

 

(2) Adjust the 'Move Willy (3)' routine so that, when Willy is about to step off a ramp cell at (x+1,y+2) / (x,y+2) [when walking left / right respectively i.e. a ramp cell in the cell underneath Willy's back foot], then make a check for an Earth block at (x,y+2) / (x+1,y+2) [i.e. in the cell underneath Willy's front foot], and if there is an Earth block there, then undo the commands which adjust Willy's coordinates downwards by a row as he moves past the cell boundary. Edit: i.e. at #900A and #9078, insert the extra check, and if there is an Earth block under Willy's front foot, then set BC=00 (although C=0 should be sufficient).

 

****

 

* N.B. This shouldn't affect the ability for Willy to walk down a ramp cell through Water cells, such as occurs in 'Swimming Pool' or 'West Wing'.

Edited by IRF
Link to comment
Share on other sites

perform an XOR 01 on the L register

Sorry, that will probably only work if Willy's attribute coordinates (WATTR) hold an even value. If they hold an odd value, then the check for Earth blocks may be misplaced to a cell beyond where Willy is standing. I'll have to rethink the logic.

 

EDIT: In specific terms, if the ramp slopes up to the left, then it will be detected at WATTR+#40 ; in that circumstance, the test for an Earth block needs to be at WATTR+#41.

But if the ramp slopes up to the right, then it will be detected at WATTR=#41 ; the test for an Earth block then needs to be at WATTR+#40.

Ideally, we would have a generic set of operations that will work for both ramp directions.

Link to comment
Share on other sites

Ramp up to the left: Offset #DA = 0 .... Test for Earth at Underfoot Ramp coordinate +1
Ramp up to the right: Offset #DA = 1 .... Test for Earth at Underfoot Ramp coordinate -1

So we need to map 0 to 1, and 1 to -1.

LD A,(#80DA)

RLCA
00 -> 00 01 -> 02

CPL
00 -> FF=-01 02 -> FD=-03

ADD A, #02
-01 -> 01 -03 -> -01

LD E,A

There may be a more efficient, clever trick that utilises the Carry Flag?

EDIT: Maybe need to adjust D as well? 0->0, 1->-1

LD A,(#80DA)

NEG

LD D,A

Then ADD HL,DE

FURTHER EDIT: It's actually more efficient just to do:

LD A, (#80DA)
AND #01
LD C,A - insert into original code after #95D0

....

 

OR A

SBC HL,DE
LD A,C
XOR #01
ADD A, #40
LD E,A
[D already holds 00]
ADD HL,DE

LD A,(Earth)

CP(HL)

JR Z, #95F8  [original JSW address, probably now changed]

Edited by IRF
Link to comment
Share on other sites

Another couple of thoughts: the check for an overhead Earth block should also test whether Willy is in the top two rows before carrying out a test for a blocking Earth cell above him. Also, the test for an underfoot Earth block ahead of Willy should be done after the edge-of-room test (otherwise Earth blocks that are horizontally at the opposite end of the current room could have an inappropriate influence on his progression). EDIT: Actually, thinking about it, that latter point isn't important - when Willy walks off the edge of a room, the vertical displacement isn't applied anyway, even if he is on a ramp (hence the ramps in adjacent rooms don't line up when you view a master plan of the whole house e.g. see Orangery/West Wing Roof).

The two additional checks for Earth/wall cells have different outcomes anyway (in the former case, Willy's diagonal movement is blocked; in the latter case, his diagonal movement is converted into sideways movement).

****

Anyway, I'll try and put all of this into practice when I get a chance; ideally I will be able to build upon Norman Sword's work in making a generic 'sideways movement' routine, covering both left and right movements simultaneously. :)

Edited by IRF
Link to comment
Share on other sites

ld a,(RAMP)

sub (HL)

jr z,found_ ;if ramp is here keep bc=shift

;ramp not found so no offset needed

as_is:

ld b,d

ld c,d ;bc=0 no ramp so no offset/shift

found_:

 

Slight rewrite to detect 'On Top of the House'-type Earth/wall block:

 

UPDATE: Edited to update the D register when Willy is moving left and about to step onto a wall tile (so that the ADD HL,DE instruction points HL at the correct room cell):

 

ld a,(RAMP)

cp (HL)

jr nz,as_is ;if ramp is here keep bc=shift

 

LD A,C

CP #20

JR NZ found_ ;Willy is going up the ramp, so no need to check if he's about to step onto a wall

LD A, (ix+ramp_condition) ;reuse existing variable...

DEC A                                   ;decrement...

LD D,A                                  ;and load into D, to give correct values for both left and right movement

LD E,(ix+ramp_animation) ;reuse existing variable, which happens to hold the correct values for both left and right movement

ADD HL,DE

LD A, (wall)

CP (HL)

JR NZ, found_ ;no wall under Willy's front foot, so he proceeds down the ramp as normal

 

;ramp not found, or it was but an adjacent wall block 'over-ruled' it, so no offset needed

as_is:

LD BC, #0000 ;bc=0 no ramp so no offset/shift

found_:

Edited by IRF
Link to comment
Share on other sites

; the initial adjust is for ramps. e.g. up/down or level

ADD HL,BC ;Point HL at the cell at

; ;(y-1) Willy is on or about to go up a ramp

; ;(y+0) just walking

; ;(y+1) Willy is walking down a ramp

ld a,(WALL)

;in theory this position could be off the top of the screen

bit 1,h

jr nz,ignore_head_check

cp (hl) ;head

ret z ;return if path is blocked

ignore_head_check:

 

Slight rewrite to detect overhead blocking wall cell:

 

ADD HL,BC

ld a,(WALL)

;in theory this position could be off the top of the screen

bit 1,h

jr nz,ignore_head_check

 

;the next wall test only occurs if Willy is walking up a ramp (i.e. if B is -01)

INC B

JR NZ, ignore_other_head_check   ; the Zero Flag will be set only if Willy is walking up a ramp

 

LD B,A ; save wall attribute in B

 

;Adjust HL to find overhead wall

LD A,L

SUB A,(IX+ramp_animation) ;this variable can be reused

LD L,A

 

LD A,B

CP(HL)

RET Z

 

;Adjust HL back again

LD A,L

ADD A,(IX+ramp_animation) ;and reused again

LD L,A

 

LD A,B

 

ignore_other_head_check:

cp (hl) ;head  ;this is the original head-height wall check

ret z ;return if path is blocked

ignore_head_check:

 

******

 

UPDATE: Here is an alternative, slightly more efficient rewrite of this part of the routine:

 

ADD HL,BC

ld a,(WALL)

;in theory this position could be off the top of the screen

bit 1,h

jr nz,ignore_head_check

 

;the next wall test only occurs if Willy is walking up a ramp (i.e. if B is -01)

INC B

JR NZ, ignore_other_head_check   ; the Zero Flag will be set only if Willy is walking UP a ramp

 

LD B,L ;retain old coordinates in HL

 

;Adjust HL to find overhead wall

LD A,L

SUB A,(IX+ramp_animation) ;this variable can be reused

LD L,A

 

LD A,(WALL)

CP(HL)

RET Z

 

;Adjust HL back again

LD L,B

 

ignore_other_head_check:

cp (hl) ;head  ;this is the original head-height wall check

ret z ;return if path is blocked

ignore_head_check:

Edited by IRF
Link to comment
Share on other sites

Meanwhile :- something I wrote last week. ------ Which is an extension of my test files Not meant to be complete or working game.

 

 

Just a test extension of matt's logic. Which also had tile blocking incorporated. 

 

 

 

The very jerky jumps, means the jumps happen a lot quicker than the nice smooth arcs of what the jumps should have been.

 

 

 

 

Since the source code for this contains so many obsolete routines. It will probably be soon deleted/purged.

 

jerky set wibble .tap

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.