I had better stop before I gold-plate things any more. Anyway, the problem is in slot 3 you can't see the variables in slot 0, so ID and PY mean nothing and default to zero. I tested the VAR("0:ID") syntax suggested, while it worked I decided against it (more below). Also as stated earlier if you want to return a value you need to call the function with parenthesis ().
I wouldn't read variables in another file's globals, that make me feel dirty and gross. It tightly couples the two files and makes them less reusable. Instead of reading ID from slot 0 which makes slot 3 dependent on the particulars of your game and tied to a specific sprite in it. You should instead pass in the ID number that you want to operate on. This lets you reuse the functions in a different game and for different sprites in the same game.
I had contemplated passing in PY too, but you can get the current sprite x and y coordinate with SPOFS ID OUT X, Y. I wasn't sure what you were doing with SPCHR and again 100 is tied to a specific sprite so I had that value passed in as a parameter too. Got to avoid those evil magic numbers.
Then I started gold plating things and added a left, right, and down function as well as a background, background music and turned the player into a boat. Anyway here is what I came up with. The first is code for slot 0, the second is for slot 3. Feel free to ask questions. Also forgive any type-os I make in retyping it.
Slot 0
VAR SCREEN_W = 400, SCREEN_H = 240
VAR BOAT_RIGHT = 365, BOAT_DOWN = 366
VAR BOAT_LEFT = 367, BOAT_UP = 368
VAR WATER = 147
VAR TILE_SIZE = 16, MUSIC = 9
VAR TILES_W, TILES_H 'Background size (iles)
VAR PX, PY 'Player position
VAR U, V, W, H 'For sprite width and height
VAR B 'Button
VAR ID 'Player sprite
'Load functions into slot 3
LOAD "PRG3:FUNCS", 0
USE 3
TILES_W = SCREEN_W / TILE_SIZE
TILES_H = SCREEN_H / TILE_SIZE
'Clear junk off the screen
ACLS
BGSCREEN 0, TILES_W, TILES_H
BGFILL 0, 0, 0, TILES_W - 1, TILES_H - 1, WATER
BGMPLAY MUSIC
'Create the player sprite
SPSET BOAT_DOWN OUT ID
SPCHR ID OUT U, V, W, H
PX = (SCREEN_W - W) / 2
PY = (SCREEN_H - H) / 2
LOCATE 0, 0
COLOR #TWHITE, #TBLUE
PRINT "Press X to exit";
WHILE TRUE
SPCHR ID OUT U, V, W, H
B = BUTTON()
'UP, DOWN, LEFT and RIGHT are functions in slot 3
IF B AND #UP THEN PY = UP(ID, BOAT_UP)
IF B AND #DOWN THEN PY = DOWN(ID, BOAT_DOWN)
IF B AND #LEFT THEN PX = LEFT(ID, BOAT_LEFT)
IF B AND #RIGHT THEN PX = RIGHT(ID, BOAT_RIGHT)
IF B AND #X THEN BREAK 'Exit game
'Clip to screen coordinates
PX = MAX(0, MIN(SCREEN_W - W - 1, PX))
PY = MAX(0, MIN(SCREEN_H - H - 1, PY))
SPOFS ID, PX, PY
VSYNC
WEND
'Cleanup
BGMSTOP
BGCLR
SPCLR
COLOR #TWHITE, 0 '0 = Transparent background
END
Slot 3
COMMON DEF UP(ID, SPRITE_ID)
VAR X, Y
SPOFS ID OUT X, Y
SPCHR ID, SPRITE_ID
DEC Y, 1
RETURN Y
END
COMMON DEF DOWN(ID, SPRITE_ID)
VAR X, Y
SPOFS ID OUT X, Y
SPCHR ID, SPRITE_ID
INC Y, 1
RETURN Y
END
COMMON DEF LEFT(ID, SPRITE_ID)
VAR X, Y
SPOFS ID OUT X, Y
SPCHR ID, SPRITE_ID
DEC X, 1
RETURN X
END
COMMON DEF RIGHT(ID, SPRITE_ID)
VAR X, Y
SPOFS ID OUT X, Y
SPCHR ID, SPRITE_ID
INC X, 1
RETURN X
END