推箱子_无操作系统

来源:互联网 发布:知乎长期光头 编辑:程序博客网 时间:2024/05/29 04:03

 

 

; box.s    ; 推箱子,运行不需操作系统,自有引导扇区,软盘引导    ; 玩法:W S A D 上下左右,Q 退出,R 重玩当前一关      ; 初学汇编,求师友    ; NASM 16位 实模式  ; Ubuntu  ; nasm -o box.bin box.s ; sudo dd if=box.bin of=/dev/fd0 bs=512 count=15 conv=notrunc ; Bochs 模拟         ; 函数调用约定   ; 参数从右向左压栈,由调用函数平衡栈   ; 被调用函数返回后与调用前相比,栈中元素及栈大小不改变   ; 被调用方不维护 ax, bx, cx, dx,但保证维护其它寄存器   ; 函数返回值 ax, bx, cx, dx         ; 代码为将来改进做好了准备(常数, 变量 和 未实现的函数)   ; 如 人物各方向不同,移动动画,使用斜视图实现3D效果         ; 常数           ; 程序占用扇区总数,不超过 0xFFFF 字节   %define  SEC_NUM   15           ; 每个扇区大小 字节   %define  SEC_SIZE  0x200           ; 显示   %define  VIDEO_ID        0x13   %define  VIDEO_HORZ_P    320 %define  VIDEO_VERT_P    200 %define  VIDEO_P         (VIDEO_HORZ_P*VIDEO_VERT_P) %define  VIDEO_SEG       0xA000 %define  VIDEO_PAL_PORT  0x03C8  %define  VIDEO_COL_PORT  0x03C9         ; 栈,考虑对齐 %define  STACK_TOP  0xFF00 %define  STACK_SEG  0x8000         ; 引导 %define  BOOT_SEG   0x7C0         ; 级别总数(级别为 1 .. LEVEL_MAX ) %define  LEVEL_MAX  4         ; 按键虚拟键码 %define  VK_NULL    0xFFFF  %define  VK_W       ('W') %define  VK_A       ('A') %define  VK_S       ('S') %define  VK_D       ('D') %define  VK_Q       ('Q') %define  VK_R       ('R')         ; 游戏状态 %define  GS_WIN     0x1 %define  GS_QUIT    0x2 %define  GS_REPLAY  0x3   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 设置 [bits 16]         ; org 0x7C00          ; 初始化 cs, ip         jmp BOOT_SEG : BOOT BOOT :          ; 初始化段寄存器         mov ax, cs         mov ds, ax         mov es, ax         mov fs, ax         mov gs, ax         ; 初始化 栈         mov ax, STACK_SEG         mov ss, ax         mov ax, STACK_TOP         mov sp, ax          ; 读入整个程序         ; 偷懒,假设要读取的扇区都在 0 磁道,若扇区数增加,需修改此段代码         mov ah, 0x2         mov al, SEC_NUM         dec al         ; mov cx, 0x0001  悲剧!!!!         mov cx, 0x0002         mov dx, 0x0000         mov bx, SEC_SIZE         int 0x13          ; 初始化显示方式         call initVideo          ; 跳入 main 执行         call main          ; 跳入 shutdown 关机         call shutdown          times (0x200-2-($-$$)) db 0         db 0x55         db 0xAA   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 地图 ;                                       ; 地图单元 ;                                         ;         *          ------------                  ;        *****              ^              ;       *********           |                ;      *************                            ;      |  *********|                       ;      | +   ***** |       UNIT_VERT_P             ;      |+       *  |                    ;      +        |  +                             ;         +     | +         |              ;            +  |+          V       ; 位置点-->     @     ----------                        ;                                                   ;      |           |                                ;      |UNIT_HORZ_P|                                ;                                                   ;                                                   ;                                                   ; 地图布局                                   ; 单元点坐标以单元为单位,常量 *_U ; 像素点坐标以像素为单位,常量 *_P ; 坐标点格式(x,y),先水平,后垂直  ; 单元点的像素坐标为其右下角像素的像素坐标  ; 水平 MAP_HORZ_U 个单元  ; 垂直 MAP_VERT_U 个单元  ; 单元点(xu,yu) in [0 .. MAP_HORZ_U)*[0 .. MAP_VERT_U)  ; 像素点(xp,yp) in [0 .. VIDEO_HORZ_P)*[0 .. VIDEO_VERT_P) ; 二维图片实现3D效果,暂未使用,待扩充 ; 绘制从左上角单元开始,至右下角单元结束,实现3D效果 ; 地图原点为地图左上角单元(xu=0,yu=0)的像素坐标 ;  ;    +--------------------------> xu in [0 .. MAP_HORZ_U) ;    |                            xp in [0 .. VIDEO_HORZ_P) ;    |                  *                        ;    |                 *   *                     ;    |                *       *                  ; yu |               *           *               ; yp |              *               *            ;    v   ----------*                   *------------ ;                  |  *               *|         ;        DY_HORZ_P |     *           * |      DY_VERT_P ;                  |        *       *  |          ;                  |           *   *   |             ;        ----------+--------------@----+-------------   ;                  |              |    |               ;                  |   DX_HORZ_P  |    |              ;                  |              |    |             ;                                  DX_VERT_P          ;                                                            ; 注意正负号,作为增量 %define  DX_VERT_P    (0) %define  DY_VERT_P    (22) %define  DX_HORZ_P    (22) %define  DY_HORZ_P    (0)  %define  UNIT_HORZ_P  (22) %define  UNIT_VERT_P  (22) %define  UNIT_P       (UNIT_HORZ_P*UNIT_VERT_P)  %define  MAP_HORZ_U   8 %define  MAP_VERT_U   8 %define  MAP_U        (MAP_HORZ_U*MAP_VERT_U)          ; 单元 id,一字节,使用位或,一个单元可以为 BOX+DEST 或BOX+FLOOR %define  UID_SPACE   0x01 %define  UID_FLOOR   0x02 %define  UID_WALL    0x04 %define  UID_BOX     0x08 %define  UID_DEST    0x10 %define  UID_PLAYER  0x20         ; 一字节 %define  DIR_UP     0x0 %define  DIR_DOWN   0x1 %define  DIR_LEFT   0x2 %define  DIR_RIGHT  0x3  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void main() ; 主程序 main :          mov byte[level], 0x1 .PLAY :          movzx ax, byte[level]         cmp ax, LEVEL_MAX         ja .COMPLETE          call initOneLevel         call playOneLevel          cmp ax, GS_QUIT         je .QUIT         cmp ax, GS_REPLAY         je .REPLAY         cmp ax, GS_WIN         jne .ERR         inc byte[level] .REPLAY :          jmp .PLAY .COMPLETE :          call initOneLevel         jmp .EXIT .QUIT :          mov byte[level], LEVEL_MAX+1         call initOneLevel         jmp .EXIT .ERR :          jmp .EXIT .EXIT :          ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void shutdown() ; 关机 shutdown :          ; 暂时死循环吧         jmp $         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void initOneLevel() ; 初始化 level 级别 initOneLevel :          push si         push di         movzx ax, byte[level]         mov cx, MAP_SIZE         mul cx         mov si, MAP_CUR         add si, ax         mov di, MAP_CUR         cld         rep movsb         pop di         pop si         call eraseAll         call drawAll         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax playOneLevel() ; 玩 level 级别 ; 返回 GS_WIN   GS_REPLAY   GS_QUIT playOneLevel :  .PLAY :          call getKey         cmp ax, VK_Q         je .QUIT         cmp ax, VK_R         je .REPLAY          movzx cx, byte[px_u]         movzx dx, byte[py_u]         cmp ax, VK_W         je .UP         cmp ax, VK_S         je .DOWN         cmp ax, VK_A         je .LEFT         cmp ax, VK_D         je .RIGHT         jmp .PLAY .UP :          mov byte[dir], DIR_UP         sub dx, 2         push dx         push cx         inc dx         push dx         push cx         jmp .TMOVE .DOWN :          mov byte[dir], DIR_DOWN         add dx, 2         push dx         push cx         dec dx         push dx         push cx         jmp .TMOVE .LEFT :          mov byte[dir], DIR_LEFT         sub cx, 2         push dx         push cx         inc cx         push dx         push cx         jmp .TMOVE .RIGHT :          mov byte[dir], DIR_RIGHT         add cx, 2         push dx         push cx         dec cx         push dx         push cx .TMOVE :          ; BOX         mov ax, UID_BOX         push ax         call isUidU         add sp, 2         test ax, ax         jnz .BOX         ; FLOOR         mov ax, UID_FLOOR         push ax         call isUidU         add sp, 2         test ax, ax         jnz .WALK         ; DEST         mov ax, UID_DEST         push ax         call isUidU         add sp, 2         test ax, ax         jnz .WALK         jmp .CANTMOVE .BOX :          push bp         mov bp, sp         mov ax, [bp+8]         push ax         mov ax, [bp+6]         push ax         call isInMapU         test ax, ax         jz .ENDBOX         mov ax, UID_BOX         push ax         call isUidU         add sp, 2         test ax, ax         jnz .ENDBOX         mov ax, UID_WALL         push ax         call isUidU         add sp, 2         test ax, ax         jz .PUSHBOX .ENDBOX :          mov sp, bp         pop bp         add sp, 8         jmp .MOVED .PUSHBOX :          mov ax, [bp+8]         mov cx, MAP_HORZ_U         mul cx         add ax, [bp+6]         push si         mov si, MAP_CUR         add si, ax         ; movzx ax, [si] 悲剧!!!!         mov al, [si]         xor al, UID_BOX         mov [si], al         pop si         mov ax, [bp+4]         mov cx, MAP_HORZ_U         mul cx         add ax, [bp+2]         push si         mov si, MAP_CUR         add si, ax         mov al, [si]         xor al, UID_BOX         mov [si], al         pop si         mov ax, [bp+2]         mov [px_u], al         mov ax, [bp+4]         mov [py_u], al         jmp .ENDBOX .WALK :          pop ax         mov [px_u], al         pop ax         mov [py_u], al         add sp, 4         jmp .MOVED .CANTMOVE :          add sp, 8 .MOVED :          call drawAll         call judgeWin         test ax, ax         jnz .WIN         jmp .PLAY .WIN :          mov ax, GS_WIN         jmp .EXIT .REPLAY :          mov ax, GS_REPLAY         jmp .EXIT .QUIT :          mov ax, GS_QUIT .EXIT :          ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax isUidU( uid, xu, yu ) ; 判断单元点(xu,yu)是否为uid ; ax!=0 是,   ax==0 否 ; 若此单元点不在地图中,返回 否 isUidU :          push bp         mov bp, sp         mov ax, [bp+8]         push ax         mov ax, [bp+6]         push ax         call isInMapU         add sp, 4         test ax, ax         jz .EXIT         mov ax, [bp+8]         mov cx, MAP_HORZ_U         mul cx         add ax, [bp+6]         push si         mov si, MAP_CUR         add si, ax         movzx ax, byte[si]         pop si         and ax, [bp+4] .EXIT :          mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax isInMapU( xu, yu ) ; 判断单元点(xu,yu)是否在地图中(所在点为SPACE算不在地图中) ; ax!=0 在,    ax==0 不在 isInMapU :          push bp         mov bp, sp         mov bx, [bp+4]         cmp bx, MAP_HORZ_U         jae .NO         mov ax, [bp+6]         cmp ax, MAP_VERT_U         jae .NO         mov cx, MAP_HORZ_U         mul cx         add ax, bx         push si         mov si, MAP_CUR         add si, ax         mov al, [si]         pop si         test al, UID_SPACE         jnz .NO .YES :          mov ax, 1         jmp .EXIT .NO :          mov ax, 0 .EXIT :          mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax judgeWin() ; 判断是否胜利,ax==0 否,ax!=0 胜 ; 简单化,扫描整个地图 judgeWin :          push si         mov si, MAP_CUR         mov cx, MAP_U .judgeWin :          xor bx, bx         movzx ax, byte[si]         test ax, UID_DEST         jz .skip1         inc bx .skip1 :          test ax, UID_BOX         jz .skip2         inc bx .skip2 :          cmp bx, 1         je .LOSE         inc si         loop .judgeWin .WIN :          mov ax, 1         jmp .EXIT .LOSE  :          mov ax, 0 .EXIT :          pop si         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void eraseAll() ; 清除所有图像 eraseAll :          mov ax, 01         mov cx, VIDEO_P         push es         mov bx, VIDEO_SEG         mov es, bx         push di         mov di, 0         cld         rep stosb         pop di         pop es         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void drawAll() ; 直接重绘地图,无关背景 ; 兼容3D效果,从左上角到右下角顺序绘制 drawAll :          push si          mov si, MAP_CUR         mov bx, 0 ; yu         mov cx, MAP_VERT_U .drawAll1 :          push cx          mov ax, 0 ; xu         mov cx, MAP_HORZ_U .drawAll2 :          push cx          push bx         push ax         movzx cx, byte[si]         inc si         push cx         call drawUidU         pop cx         pop ax         pop bx          inc ax         pop cx         loop .drawAll2          inc bx         pop cx         loop .drawAll1          pop si          movzx ax, byte[py_u]         push ax         movzx ax, byte[px_u]         push ax         mov ax, UID_PLAYER         push ax         call drawUidU         add sp, 6         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void drawUidU( uid, xu, yu ) ; 绘制单元坐标为(xu,yu)的单元uid ; uid == UID_FLOOR,  drawUidU :          push bp         mov bp, sp         mov ax, [bp+8]         push ax         mov ax, [bp+6]         push ax         call convU2P         add sp, 4         push bx         push ax         mov ax, [bp+4]         push ax         call drawUid         add sp, 6         mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax, bx  convU2P( xu, yu ) ; 单元坐标转换为像素坐标,依据 orgx_p, orgy_p ; 返回 ax==xp, bx=yp ; 适应3D侧视图 convU2P :          push bp         mov bp, sp         movzx ax, byte[orgx_p]         movzx bx, byte[orgy_p] .convU2P_L1 :          mov cx, [bp+4]         test cx, cx         jz .convU2P_L2 .convU2P1 :          add ax, DX_HORZ_P         add bx, DY_HORZ_P         loop .convU2P1 .convU2P_L2 :          mov cx, [bp+6]         test cx, cx         jz .EXIT .convU2P2 :          add ax, DX_VERT_P         add bx, DY_VERT_P         loop .convU2P2 .EXIT :          mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void drawUid( uid, xp, yp ) ; 绘制像素点为(xp,yp)且类型为uid的单元点 ; uid == UID_SPACE, UID_FLOOR,  drawUid :          push bp         mov bp, sp         mov ax, [bp+4]         push ax         call convUid2Uoff         pop bx         mov bx, [bp+8]         push bx         mov bx, [bp+6]         push bx         push ax         call drawUoff         mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax convUid2Uoff( uid ) ; uid == UID_FLOOR,      uoff = UOFF_FLOOR,  ; 不依赖 uid 和 uoff 的定义,无跳表,大量比较 ; 处理了player的方向dir ; BOX+DEST或BOX+FLOOR 按BOX处理,所以注意测试顺序 convUid2Uoff :          push bp         mov bp, sp         mov ax, [bp+4] .SPACE :          test ax, UID_SPACE         jz .BOX         mov ax, UOFF_SPACE         jmp .EXIT .BOX :          test ax, UID_BOX         jz .FLOOR         mov ax, UOFF_BOX         jmp .EXIT .FLOOR :          test ax, UID_FLOOR         jz .WALL         mov ax, UOFF_FLOOR         jmp .EXIT .WALL :          test ax, UID_WALL         jz .DEST         mov ax, UOFF_WALL         jmp .EXIT .DEST :          test ax, UID_DEST         jz .PLAYER         mov ax, UOFF_DEST         jmp .EXIT .PLAYER :          test ax, UID_PLAYER         jz .ELSE         mov al, [dir]     .UP :          cmp al, DIR_UP         jne .DOWN         mov ax, UOFF_PLAYER_UP         jmp .EXIT     .DOWN :          cmp al, DIR_DOWN         jne .LEFT         mov ax, UOFF_PLAYER_DOWN         jmp .EXIT     .LEFT :          cmp al, DIR_LEFT         jne .RIGHT         mov ax, UOFF_PLAYER_LEFT         jmp .EXIT     .RIGHT :          cmp al, DIR_RIGHT         jne .ELSE         mov ax, UOFF_PLAYER_RIGHT         jmp .EXIT .ELSE :          mov ax, UOFF_SPACE  .EXIT :          mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void drawUoff( uoff, xp, yp ) ; 绘制像素点为(xp,yp)且地图单元位图偏移为uoff的单元点 ; off == UOFF_SPACE, UOFF_FLOOR,  drawUoff :          ; 悲剧!!!!         push bp         mov bp, sp         push si         push di         push es          mov si, [bp+4]          mov cx, VIDEO_SEG         mov es, cx          mov ax, [bp+8]         sub ax, UNIT_VERT_P         inc ax         mov cx, VIDEO_HORZ_P         mul cx         mov bx, [bp+6]         sub bx, UNIT_HORZ_P         inc bx         add ax, bx         mov di, ax          mov cx, UNIT_VERT_P .drawUoff1 :          push cx          mov cx, UNIT_HORZ_P .drawUoff2 :          mov al, [ds:si]         test al, al         jz .drawUoff3         mov [es:di], al .drawUoff3 :          inc si         inc di         loop .drawUoff2          sub di, UNIT_HORZ_P         add di, VIDEO_HORZ_P         pop cx         loop .drawUoff1          pop es         pop di         pop si         mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax peekKey() ; 获取键盘输入,不阻塞 ; 若无输入返回 VK_NULL ; 若有输入,取出,且不将其从缓冲区中清除 peekKey :          mov ah, 1         int 0x16         jz .VK_NULL         push ax         call convKey2Vk         add sp, 2         jmp .EXIT .VK_NULL :          mov ax, VK_NULL .EXIT :          ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax getKey() ; 获取键盘输入,阻塞 ; 若无输入,阻塞 ; 若有输入,取出,且将其从缓冲区中清除 getKey :          mov ah, 0         int 0x16         push ax         call convKey2Vk         add sp, 2         cmp ax, VK_NULL         je getKey         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func ax convKey2Vk( bios_ax ) ; 将BIOS键盘输入转换为虚拟键码 ; 不依赖任何编码,大量比较 convKey2Vk :          push bp         mov bp, sp         mov ax, [bp+4]          cmp al, 'W'         je .VK_W         cmp al, 'w'         je .VK_W                  cmp al, 'A'         je .VK_A         cmp al, 'a'         je .VK_A                  cmp al, 'S'         je .VK_S         cmp al, 's'         je .VK_S          cmp al, 'D'         je .VK_D         cmp al, 'd'         je .VK_D          cmp al, 'Q'         je .VK_Q         cmp al, 'q'         je .VK_Q          cmp al, 'R'         je .VK_R         cmp al, 'r'         je .VK_R          jmp .VK_NULL .VK_W :          mov ax, VK_W         jmp .EXIT .VK_A :          mov ax, VK_A         jmp .EXIT .VK_S :          mov ax, VK_S         jmp .EXIT .VK_D :          mov ax, VK_D         jmp .EXIT .VK_Q :          mov ax, VK_Q         jmp .EXIT .VK_R :          mov ax, VK_R         jmp .EXIT .VK_NULL :          mov ax, VK_NULL .EXIT :          mov sp, bp         pop bp         ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void sleep( t ) ; 等待 t 毫秒,等待中的输入被清除(清空输入缓冲区) ; 移动动画使用 sleep :          ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 调色板 BOX_PAL :          ; r   g    b         db 63, 63, 00 ; 00 透明色                 ; SPACE         db 00, 00, 00 ; 01 背景色         db 00, 00, 00 ; 02         db 00, 00, 00 ; 03         db 00, 00, 00 ; 04         db 00, 00, 00 ; 05                 ; FLOOR         db 16, 22, 28 ; 06         db 21, 26, 32 ; 07         db 00, 07, 15 ; 08         db 00, 00, 00 ; 09         db 00, 00, 00 ; 10                 ; WALL         db 00, 07, 15 ; 11         db 63, 63, 63 ; 12         db 14, 20, 22 ; 13         db 30, 31, 38 ; 14         db 37, 42, 45 ; 15                 ; BOX         db 60, 60, 60 ; 16         db 25, 30, 06 ; 17         db 44, 47, 21 ; 18         db 55, 56, 37 ; 19         db 00, 07, 15 ; 20                 ; DEST         db 60, 60, 30 ; 21         db 00, 07, 15 ; 22         db 00, 00, 00 ; 23         db 00, 00, 00 ; 24         db 00, 00, 00 ; 25                 ; PLAYER         db 00, 07, 15 ; 26         db 60, 60, 60 ; 27         db 00, 00, 00 ; 28         db 60, 44, 62 ; 29         db 63, 28, 62 ; 30         db 00, 32, 63 ; 31         db 00, 00, 00 ; 32         db 00, 00, 00 ; 33 BOX_PAL_NUM : equ $-BOX_PAL  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; func void initVideo() ; 初始化显示方式 initVideo :          ; 设置显示方式         mov ax, 0x0013         int 0x10          ; 设置调色板         xor bx, bx  ; rgbrgbrgb         xor cx, cx  ; index 0 .iVset :          cmp bx, BOX_PAL_NUM         je .iVexit          ; 调色板 index         mov dx, VIDEO_PAL_PORT         mov ax, cx         out dx, al         inc cx          ; 调色板颜色         mov dx, VIDEO_COL_PORT         mov al, [ds:BOX_PAL+bx]         out dx, al         inc bx         mov al, [ds:BOX_PAL+bx]         out dx, al         inc bx         mov al, [ds:BOX_PAL+bx]         out dx, al         inc bx          jmp .iVset .iVexit :          ret  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 地图单元位图 ; (繁琐的工作,还好有 Vim + 自制的MageX ) UOFF_SPACE :          db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01         db 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01 UOFF_FLOOR :          db 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 07, 07, 07, 07, 06, 06, 07, 07, 07, 07, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 08         db 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08, 08 UOFF_WALL :          db 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11         db 11, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 11         db 11, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 11         db 11, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11         db 11, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11         db 11, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11         db 11, 12, 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11         db 11, 12, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11         db 11, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11         db 11, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11         db 11, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 11         db 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 UOFF_BOX :          db 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20         db 20, 06, 06, 06, 06, 06, 06, 06, 18, 18, 18, 18, 18, 18, 06, 06, 06, 06, 06, 06, 06, 20         db 20, 06, 06, 06, 06, 06, 18, 18, 16, 16, 16, 16, 18, 18, 18, 18, 06, 06, 06, 06, 06, 20         db 20, 06, 06, 06, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 06, 06, 06, 20         db 20, 06, 06, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 18, 06, 06, 20         db 20, 06, 06, 18, 16, 16, 16, 16, 16, 16, 17, 16, 16, 16, 16, 16, 16, 18, 18, 06, 06, 20         db 20, 06, 18, 18, 16, 16, 16, 16, 16, 16, 17, 17, 16, 16, 16, 16, 18, 18, 18, 18, 06, 20         db 20, 06, 18, 18, 18, 16, 16, 16, 16, 17, 17, 17, 17, 18, 16, 18, 18, 18, 18, 18, 06, 20         db 20, 18, 18, 18, 18, 18, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 20         db 20, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 20         db 20, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 20         db 20, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 20         db 20, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 20         db 20, 18, 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 18, 18, 19, 19, 18, 18, 18, 18, 20         db 20, 06, 18, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 18, 19, 19, 19, 18, 18, 18, 06, 20         db 20, 06, 18, 18, 18, 18, 18, 18, 18, 18, 17, 17, 18, 19, 19, 19, 19, 18, 18, 18, 06, 20         db 20, 06, 06, 18, 18, 18, 18, 18, 18, 19, 19, 17, 18, 19, 19, 19, 18, 18, 18, 06, 06, 20         db 20, 06, 06, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 18, 18, 18, 18, 06, 06, 20         db 20, 06, 06, 06, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 18, 18, 18, 18, 06, 06, 06, 20         db 20, 06, 06, 06, 06, 06, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 06, 06, 06, 06, 06, 20         db 20, 06, 06, 06, 06, 06, 06, 06, 18, 18, 18, 18, 18, 18, 06, 06, 06, 06, 06, 06, 06, 20         db 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 UOFF_DEST :          db 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 21, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 06, 06, 22         db 22, 06, 06, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 21, 21, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 21, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 22         db 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 UOFF_PLAYER_UP :          db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 31, 27, 27, 31, 29, 29, 31, 27, 27, 31, 29, 29, 29, 06, 06, 26         db 26, 06, 29, 29, 29, 31, 28, 28, 31, 31, 31, 31, 28, 28, 31, 31, 31, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 27, 31, 31, 31, 31, 31, 27, 31, 31, 31, 31, 31, 31, 27, 29, 29, 06, 26         db 26, 29, 29, 29, 27, 27, 31, 31, 31, 31, 27, 27, 31, 31, 31, 31, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 27, 27, 27, 31, 31, 27, 27, 27, 27, 31, 31, 27, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 27, 27, 27, 30, 30, 30, 30, 27, 27, 27, 29, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 29, 29, 27, 30, 30, 30, 30, 27, 29, 29, 29, 29, 29, 29, 29, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 UOFF_PLAYER_DOWN :          db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 31, 27, 27, 31, 29, 29, 31, 27, 27, 31, 29, 29, 29, 06, 06, 26         db 26, 06, 29, 29, 29, 31, 28, 28, 31, 31, 31, 31, 28, 28, 31, 31, 31, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 27, 31, 31, 31, 31, 31, 27, 31, 31, 31, 31, 31, 31, 27, 29, 29, 06, 26         db 26, 29, 29, 29, 27, 27, 31, 31, 31, 31, 27, 27, 31, 31, 31, 31, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 27, 27, 27, 31, 31, 27, 27, 27, 27, 31, 31, 27, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 27, 27, 27, 30, 30, 30, 30, 27, 27, 27, 29, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 29, 29, 27, 30, 30, 30, 30, 27, 29, 29, 29, 29, 29, 29, 29, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 UOFF_PLAYER_LEFT :          db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 31, 27, 27, 31, 29, 29, 31, 27, 27, 31, 29, 29, 29, 06, 06, 26         db 26, 06, 29, 29, 29, 31, 28, 28, 31, 31, 31, 31, 28, 28, 31, 31, 31, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 27, 31, 31, 31, 31, 31, 27, 31, 31, 31, 31, 31, 31, 27, 29, 29, 06, 26         db 26, 29, 29, 29, 27, 27, 31, 31, 31, 31, 27, 27, 31, 31, 31, 31, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 27, 27, 27, 31, 31, 27, 27, 27, 27, 31, 31, 27, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 27, 27, 27, 30, 30, 30, 30, 27, 27, 27, 29, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 29, 29, 27, 30, 30, 30, 30, 27, 29, 29, 29, 29, 29, 29, 29, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 UOFF_PLAYER_RIGHT :          db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 31, 31, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 31, 27, 27, 31, 29, 29, 31, 27, 27, 31, 29, 29, 29, 06, 06, 26         db 26, 06, 29, 29, 29, 31, 28, 28, 31, 31, 31, 31, 28, 28, 31, 31, 31, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 27, 31, 31, 31, 31, 31, 27, 31, 31, 31, 31, 31, 31, 27, 29, 29, 06, 26         db 26, 29, 29, 29, 27, 27, 31, 31, 31, 31, 27, 27, 31, 31, 31, 31, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 27, 27, 27, 31, 31, 27, 27, 27, 27, 31, 31, 27, 27, 27, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 27, 27, 27, 27, 27, 30, 30, 27, 27, 27, 27, 27, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 27, 27, 27, 30, 30, 30, 30, 27, 27, 27, 29, 29, 29, 29, 29, 26         db 26, 29, 29, 29, 29, 29, 29, 29, 27, 30, 30, 30, 30, 27, 29, 29, 29, 29, 29, 29, 29, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 26         db 26, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 29, 29, 29, 29, 29, 06, 06, 26         db 26, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 26         db 26, 06, 06, 06, 06, 06, 06, 06, 29, 29, 29, 29, 29, 29, 06, 06, 06, 06, 06, 06, 06, 26         db 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 变量         level : db 1 ; 当前地图 MAP_CUR :          times MAP_U db 0         orgx_p : db 0         orgy_p : db 0         px_u   : db 0         py_u   : db 0         dir  : db 0 MAP_SIZE : equ $-MAP_CUR  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 地图,级别从低到高按顺序,相对 MAP_CUR 定位  %define SPACE    UID_SPACE %define FLOOR    UID_FLOOR %define WALL     UID_WALL %define DEST     UID_DEST %define BOX      (UID_FLOOR|UID_BOX) %define BOXDE    (UID_DEST|UID_BOX) %define PLAYE    UID_FLOOR  MAP_LEVEL_1 :          db SPACE, SPACE, WALL,  WALL,  WALL,  SPACE, SPACE, SPACE         db SPACE, SPACE, WALL,  DEST,  WALL,  SPACE, SPACE, SPACE         db SPACE, SPACE, WALL,  FLOOR, WALL,  WALL,  WALL,  WALL         db WALL,  WALL,  WALL,  BOX,   FLOOR, BOX,   DEST,  WALL         db WALL,  DEST,  FLOOR, BOX,   FLOOR,   WALL,  WALL,  WALL         db WALL,  WALL,  WALL,  WALL,  BOX,   WALL,  SPACE, SPACE         db SPACE, SPACE, SPACE, WALL,  DEST,  WALL,  SPACE, SPACE         db SPACE, SPACE, SPACE, WALL,  WALL,  WALL,  SPACE, SPACE         db 90, 30, 4, 4, DIR_UP  MAP_LEVEL_2 :          db SPACE, SPACE, WALL,  WALL,  WALL,  WALL,  SPACE, SPACE         db SPACE, WALL,  WALL,  FLOOR, FLOOR, WALL,  SPACE, SPACE         db SPACE, WALL,  FLOOR, BOX,   FLOOR, WALL,  SPACE, SPACE         db SPACE, WALL,  WALL,  BOX,   FLOOR, WALL,  WALL,  SPACE         db SPACE, WALL,  WALL,  FLOOR, BOX,   FLOOR, WALL,  SPACE         db SPACE, WALL,  DEST,  BOX,   FLOOR, FLOOR, WALL,  SPACE         db SPACE, WALL,  DEST,  DEST,  BOXDE, DEST,  WALL,  SPACE         db SPACE, WALL,  WALL,  WALL,  WALL,  WALL,  WALL,  SPACE         db 90, 30, 2, 2, DIR_UP  MAP_LEVEL_3 :          db SPACE, WALL,  WALL,  WALL,  WALL,  WALL,  SPACE, SPACE         db SPACE, WALL,  FLOOR, FLOOR, WALL,  WALL,  WALL,  SPACE         db SPACE, WALL,  FLOOR, BOX,   FLOOR, FLOOR, WALL,  SPACE         db WALL,  WALL,  WALL,  FLOOR, WALL,  FLOOR, WALL,  WALL         db WALL,  DEST,  WALL,  FLOOR, WALL,  FLOOR, FLOOR, WALL         db WALL,  DEST,  BOX,   FLOOR, FLOOR, WALL,  FLOOR, WALL         db WALL,  DEST,  FLOOR, FLOOR, FLOOR, BOX,   FLOOR, WALL         db WALL,  WALL,  WALL,  WALL,  WALL,  WALL,  WALL,  WALL         db 90, 30, 2, 2, DIR_UP  MAP_LEVEL_4 :          db SPACE, SPACE, WALL,  WALL,  WALL,  WALL,  WALL,  WALL         db SPACE, WALL,  WALL,  FLOOR, FLOOR, WALL,  FLOOR, FLOOR         db SPACE, WALL,  FLOOR, FLOOR, FLOOR, WALL,  FLOOR, FLOOR         db SPACE, WALL,  BOX,   FLOOR, BOX,   FLOOR, BOX,   FLOOR         db SPACE, WALL,  FLOOR, BOX,   WALL,  WALL,  FLOOR, FLOOR         db WALL,  WALL,  FLOOR, BOX,   FLOOR, WALL,  FLOOR, WALL         db DEST,  DEST,  DEST,  DEST,  DEST,  FLOOR, FLOOR, WALL         db WALL,  WALL,  WALL,  WALL,  WALL,  WALL,  WALL,  WALL         db 90, 30, 7, 1, DIR_UP  MAP_LEVEL_COMPELETE :          db FLOOR, FLOOR, FLOOR, SPACE, SPACE, FLOOR, FLOOR, SPACE         db FLOOR, SPACE, SPACE, SPACE, SPACE, FLOOR, SPACE, FLOOR         db FLOOR, SPACE, SPACE, SPACE, SPACE, FLOOR, SPACE, FLOOR         db FLOOR, FLOOR, FLOOR, SPACE, SPACE, FLOOR, SPACE, FLOOR         db FLOOR, SPACE, SPACE, SPACE, SPACE, FLOOR, SPACE, FLOOR         db FLOOR, SPACE, SPACE, SPACE, SPACE, FLOOR, SPACE, FLOOR         db FLOOR, FLOOR, FLOOR, SPACE, SPACE, FLOOR, FLOOR, SPACE         db SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE         db 95, 40, 1, 3, DIR_UP