; ECE 291 Fall 2000 Project
; -- Territory --
;
; Completed By:
;  Sung Hyuk Kim, Joseph Kim, Stuart Johns, and Jason Leake
;
; Professor Kalbarczyk
; Guest Authors - Peter Johnson, Michael Urman
; University of Illinois Urbana Champaign
; Dept. of Electrical & Computer Engineering
;
; Ver 1.0

%include "lib291.inc"
%include "libmp4.inc"

	BITS 32

	GLOBAL _main

; Define functions, variables used by main()
EXTERN _LoadPNG
_LoadPNG_arglen		EQU	18
EXTERN _CurrentState
EXTERN _StateHandlers
EXTERN _RubberBandFlag

; Event structure - 8 bytes long so we can address it easily
STRUC Event
.Condition	resw	1	; Condition bitmask (in mouse handler format)
.X		resw	1	; X coordinate in screen pixels from left
.Y		resw	1	; Y coordinate in screen pixels from top
.Buttons	resw	1	; Button status (in mouse handler format)
ENDSTRUC

; Point structure - 4 bytes so that we can address it at ease
STRUC Point
.X      resw    1
.Y      resw    1
ENDSTRUC

; Event Queue size (# of elements and size in bytes)
QUEUE_ELEMENTS	equ 50
QUEUE_SIZE	equ	QUEUE_ELEMENTS * Event_size

; scancodes that we will need for KbdHandler
ESCKEY  EQU     01      ; ESC key scancode
RARROW  EQU     77      ; RIGHT Arrow key scancode
LARROW  EQU     75      ; LEFT Arrow key scancode
DARROW  EQU     80      ; DOWN Arrow key scancode
UARROW  EQU     72      ; UP Arrow key scancode



	SECTION .bss
LargeStack      resb    464*464*4
tempMap         resb    464*464
OrigESP         resb    4
OrigSS          resb    2

_QueueNumEvents resb    1       ;Number of events in the queue
_Queue          resb    (QUEUE_ELEMENTS +1)*Point_size

_ImageBlock     resw    1       ;Non-rubberband image
_OverlayBlock   resw    1       ;Overlay images (for alphablit)
_FontBlock      resw    1       ;The antialiased font
_EnemyBlock     resw    1       ;enemy's image
_PlayerBlock    resw    1       ;player's image
_NumBlock       resw    1
_KbdSeg         resw    1
_KbdOff         resw    1
_TimerSeg       resw    1
_TimerOff       resw    1


ClosestPointE1  resw    1   ;holds the closest point in the LineBuffer
                                ;it's more like an index for LineBuffer
ClosestPointE2  resw    1
ClosestPointE3  resw    1
chasePointX     resw    1
chasePointY     resw    1




Level           resb    1
PercentTaken    resb    1       ; Percent of Territory taken by the player
Score           resd    1       ; Game score
Timelimit       resd    1       ; Time limit for each level to finish it
TimeLeft        resd    1       ; Time left to play the level

_ExitFlag	resb	1	; Set to 1 to exit immediately
_MouseSeg	resw	1	; Mouse RMCB segment
_MouseOff	resw	1	; Mouse RMCB offset

NewKey          resb    1

_LineBuffer     resb    50*4    ;each 4 bytes will hold xpos and ypos
FinishPercent   resb      1      ; the percent amount of Territory that the player needs to take to finish the level
Lives           resb      1       ; Number of lives the player has
GameFlags       resd     1
; in&out territory bit is set as the game starts since the player is in his territory
; in the beginning of the game


;Bit 0 - exit game flag
;Bit 1&2 - previous direction for the player
;Bit 3&4 ?direction bit for player
        ; 00 - move down
        ; 01 - move right
        ; 10 - move left
        ; 11 - move up
;Bit 5&6 ?direction bit for enemy1
;Bit 7&8 ?direction bit for enemy2
;Bit 9&10 ?direction bit for enemy3
;Bit 11 ?in&out territory bit      1 - in territory, 0 - in free space
;Bit 12, 13, & 14 ?enemies?life status
;Bit 15 ?chaseFlag bit
;Bit 16 ?playerCollisionFlag
;Bit 17, 18, & 19 ?enemyCollisionFlag



	SECTION .data
AreaTaken       dd      0       ;The amount of area already claimed
TimerTick       db      0
index           db      0        ;index for the LineBuffer

EnemyPoint
.X1     dw    90
.Y1     dw    100
.X2     dw    70
.Y2     dw    400
.X3     dw    20
.Y3     dw    300
END

XPos            dw      8       ; Position coordinate for the player
YPos            dw      8
MenuExitflag    db     0       ; Flag to exit menu section
TypeOfMidi      db     0
StartGame       db     0       ; Game will start as the player wants to do


NumberofEnemies db      3       ; As the enemy die, it will change
_territoryMap   db      464*464 times, (1)


;background      db      640*480 times
;backbuffer      db      640*480 times

randVal         dw      1234    ; seed the randval

_EnemyFirst     dd      _EnemyPoint
_LineFirst     dd      _LineBuffer
_QueueFirst     dd      _Queue  ;Pointer to the head of the queue

;Required files: loaded at startup
_BackgroundFN   db      'sample.png',0
_FontFN         db      'font.png',0
_PlayerFN       db      'player.png',0
_EnemyFN        db      'enemy.png',0
_GameOverFN     db      'over.png',0
_NumFN          db      'number.png',0


;Use this constant in DrawPixelD() to normalize the 0-1.5 range to
;0-1 range
_MapTo1         dq     1.5

_StartFN        db      'MENU.png',0        ;;;;;;;;;;

; Use this constant in AlphaBlit() to round the division by 256 properly.
_RoundingFactor	dd	800080h,	80h


	SECTION .text

;---------------------------------------
; Program Start
;_main function
;written by Sung Kim,
;Modified by Joseph kim
;--------------------------------------
_main

	call	_LibInit

	; Change this to 0 to simplify debugging
	; (it disables the "rubberbanding" feature which will call the
	;  respective function every time the mouse moves).
	; During handin, we will test with rubberbanding enabled!
	mov	byte [_RubberBandFlag], 1

	; Graphics init
	invoke	_SetGraphics, word 640, word 480
	test	eax, eax
	jnz	near .quit

	; Mouse/Keyboard init
;	call	_InstallMouse

	; Allocate Back Image buffer
	invoke	_AllocMem, dword 640*480*4
	cmp	ax, -1
	je	near .exit
	mov	[_ImageBlock], ax

	; Allocate Overlay Image buffer
	invoke	_AllocMem, dword 640*480*4
	cmp	ax, -1
	je	near .exit
	mov	[_OverlayBlock], ax

	; Allocate Font Image buffer
	invoke	_AllocMem, dword 2048*16*4
	cmp	ax, -1
	je	near .exit
	mov	[_FontBlock], ax

        ; Allocate Player Image buffer
        invoke  _AllocMem, dword 16*16*4
        cmp     ax, -1
        je      near .exit
        mov     [_PlayerBlock], ax

        ; Allocate Enemy Image buffer
        invoke _AllocMem, dword 16*16*4
        cmp     ax, -1
        je      near .exit
        mov     [_EnemyBlock], ax

        ; Allocate Number Image buffer
        invoke  _AllocMem, dword 160*32*4
        cmp     ax, -1
        je      near .exit
        mov     [_NumBlock], ax
.DisplayMenu
	;set up initial display
        invoke  _LoadPNG, dword _StartFN, word [_ImageBlock], dword 0, dword 0, dword 0
	call	libCopyImageToScreen
	call	_RefreshVideoBuffer
.WaitforKeyPressed
	; Install keyboard handler: the 291 high-res driver requires you
	;  to use IRQ 7 and Port 300h to permit debugging with the standard
	;  keyboard driver in the Command Prompt window.
	invoke	_Install_Int, dword 15, dword KeyboardISR

	; Wait for a key
.wait:
	cmp	byte [NewKey], 0
	jz	.wait

	; Clean up after ourselves
	invoke	_Remove_Int, dword 15

        invoke  _Install_Int, dword 15, dword KeyboardISR1
        invoke  _Install_Int, dword 8, dword  TimerHandler
;        call    _InstallMouse
        call    IntPlayer

 	; Load background, font, set up initial display
        invoke  _LoadPNG, dword _BackgroundFN, word [_ImageBlock], dword 0, dword 0, dword 0
	invoke	_LoadPNG, dword _FontFN, word [_FontBlock], dword 0, dword 0, dword 0
        invoke  _LoadPNG, dword _PlayerFN, word [_PlayerBlock], dword 0, dword 0, dword 0
        invoke  _LoadPNG, dword _EnemyFN, word [_EnemyBlock], dword 0, dword 0, dword 0

	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        push    ebx
        push    eax
        invoke  _LoadPNG, dword _BackgroundFN, word [_ImageBlock], dword 0, dword 0, dword 0

        pop     eax
        pop     ebx
        movzx   ebx, word[XPos]
        movzx   eax, word[YPos]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 0, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        movzx   ebx, word[EnemyPoint.X1]
        movzx   eax, word[EnemyPoint.Y1]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        movzx   ebx, word[EnemyPoint.X2]
        movzx   eax, word[EnemyPoint.Y2]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        movzx   ebx, word[EnemyPoint.X3]
        movzx   eax, word[EnemyPoint.Y3]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

	; Main event processing loop
        ; RandomMove will be called from TimerHandler

.loop:
        
	cmp	byte [_ExitFlag], 0
	jnz	near .exit
        mov     eax, [GameFlags]
        and     eax, 00000001h
        jnz      .gameisOver

        call    _MovePlayer    ;it calls _CheckPlayerCollision, _CheckplayerOFB
                                ;and _Calculate_Territory
        mov     al, byte[index]
        movzx   eax, ax
        lea     eax, [_LineBuffer+eax*4]
        invoke  _AALine, word [eax-4], word [eax-2], word [eax], word[eax+2], dword 0
        call    _GameOver
        Call    _Update_Stats
        call	libCheckEvents
	test	eax, eax
	jz	.loop		; No events

	; Call proper state handler for new event
	movzx	eax, byte [_CurrentState]
	call	[_StateHandlers+eax*4]

	jmp	short .loop

.gameisOver

        invoke  _LoadPNG, dword _GameOverFN, word [_ImageBlock], dword 0, dword 0, dword 0
	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        invoke  _Remove_Int, dword 15
	invoke	_Install_Int, dword 15, dword KeyboardISR

	; Wait for a key         to finish the game
.wait1:
        mov     ecx, 5
   .loops:
        invoke  _LoadPNG, dword _GameOverFN, word [_ImageBlock], dword 0, dword 0, dword 0
        dec     ecx
        jnz     .loops

	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

	cmp	byte [NewKey], 0
        jz      .wait1

	; Clean up after ourselves
	invoke	_Remove_Int, dword 15
        jmp     .exit1


.exit:
        invoke   _Remove_Int, dword 15

.exit1:
	; Shutdown and cleanup
        invoke   _Remove_Int, dword 15
        invoke   _Remove_Int, dword 8
;	call	_RemoveMouse
	call	_UnsetGraphics
	invoke	_FreeMem, word [_FontBlock]
	invoke	_FreeMem, word [_OverlayBlock]
	invoke	_FreeMem, word [_ImageBlock]
        invoke  _FreeMem, word [_PlayerBlock]
        invoke  _FreeMem, word [_PlayerBlock]
.quit:
	call	MP4LibExit
	call	_LibExit
	ret



;----------------------------------------------------------
;GameOver
;input:EnemyPoint, XPos, YPos
;output: GameFlags
;purpose: if there is collision, GameOver flag is set.
;written by:  Sung Kim
;modified by: Stu Johnson, Joseph Kim
;----------------------------------------------------------
_GameOver
        push    eax
        push    ebx
        mov     ax, [XPos]
        add     ax, 2
        cmp     ax, [EnemyPoint.X1]
        jbe     .lessthan
        jmp     .checkEnemy2
.lessthan
        sub     ax, 4
        cmp     ax, [EnemyPoint.X1]
        jae     .checkY
        jmp     .checkEnemy2
.checkY
        mov     bx, [YPos]
        add     bx, 2
        cmp     bx, [EnemyPoint.Y1]
        jbe      .lessthanY
        jmp     .checkEnemy2
.lessthanY
        sub     bx, 4
        cmp     bx, [EnemyPoint.Y1]
        jae     near .Gameover
        jmp     .checkEnemy2

        
.checkEnemy2

        mov     ax, [XPos]
        push    ax
        add     ax, 2
        cmp     ax, [EnemyPoint.X2]
        jbe     .lessthan1
        jmp     .checkEnemy3
.lessthan1
        sub     ax, 4
        cmp     ax, [EnemyPoint.X2]
        jae     .checkY1
        jmp     .checkEnemy3
.checkY1
        mov     bx, [YPos]
        add     bx, 2
        cmp     bx, [EnemyPoint.Y2]
        jbe      .lessthanY1
        jmp     .checkEnemy3
.lessthanY1
        sub     bx, 4
        cmp     bx, [EnemyPoint.Y2]
        jae     .Gameover
        jmp     .checkEnemy3

.checkEnemy3
        mov     ax, [XPos]
        push    ax
        add     ax, 2
        cmp     ax, [EnemyPoint.X3]
        jbe     .lessthan2
        jmp     .endGameOver
.lessthan2
        sub     ax, 4
        cmp     ax, [EnemyPoint.X3]
        jae     .checkY2
        jmp     .endGameOver
.checkY2
        mov     bx, [YPos]
        add     bx, 2
        cmp     bx, [EnemyPoint.Y3]
        jbe      .lessthanY2
        jmp     .endGameOver
.lessthanY2
        sub     bx, 4
        cmp     bx, [EnemyPoint.Y3]
        jae     .Gameover
        jmp     .endGameOver

.Gameover
        mov     eax, [GameFlags]
        or      eax, 00000001h  ;setting the gameover flag
.endGameOver
        pop     ebx
        pop     eax
        ret



;----------------------------------------------------------
;KeyboardHandler
;purpose: it acts on any Key
;code from lecture
;----------------------------------------------------------
KeyboardISR
	mov	dx, 300h		; Note the different port
	in	al, dx

	test	al, 80h			; Ignore releases
	jnz	.done
	mov	byte [NewKey], 1	; Got a new key!
.done:
        mov     al, 20h
        out     20h, al

        xor     eax, eax        ; Don't chain!

        ret
KeyboardISR_end

;----------------------------------------------------------
;KeyboardHandler1
;Purpose: It acts on ESC, Rarrow, Larrow, Darrow, and Uarrow
;written by Sung Kim
;Modified by Joseph kim
;----------------------------------------------------------
KeyboardISR1
	mov	dx, 300h		; Note the different port
	in	al, dx

	test	al, 80h			; Ignore releases
        jnz     near .done

        cmp     al, ESCKEY
        je      .quitGame
        cmp     al, RARROW
        je      .movingRight
        cmp     al, LARROW
        je      .movingLeft
        cmp     al, DARROW
        je      .movingDown
        cmp     al, UARROW
        je       near .movingUp

        jmp     .acknowledgement

.quitGame:
        mov     eax, [GameFlags]
        or      eax, 00000001h
        mov     [GameFlags], eax
        jmp     .acknowledgement
.movingRight:
        mov     eax, [GameFlags]
        or      eax, 00000008h  ;00001000   set the bit 3 to 1
        and     eax, 000000efh  ;11101111b     set the bit 4 to 0
        mov     [GameFlags], eax
        jmp     .acknowledgement
.movingLeft:
        mov     eax, [GameFlags]
        or      eax, 00000010h  ; 00010000b
        and     eax, 000000f7h  ; 11110111b
        mov     [GameFlags], eax
        jmp     .acknowledgement
.movingDown:
        mov     eax, [GameFlags]
        and     eax, 000000e7h  ; 11100111b
        mov     [GameFlags], eax
        jmp     .acknowledgement

.movingUp:
        mov     eax, [GameFlags]
        or      eax, 00000018h  ; 00011000b
        mov     [GameFlags], eax

.acknowledgement:
        mov     al, 20h
        out     20h, al

        xor     eax, eax

        ret
KeyboardISR1_end


;---------------------------------------------------------------------------
;TimerHandler Purpose - to take control of calls for enemy movement
;Input - TimerTick
;Output - TimerTick
;written by Sung Kim
;Modified by Joseph kim
;---------------------------------------------------------------------------
TimerHandler
	mov	dx, 300h		; Note the different port
	in	al, dx

	test	al, 80h			; Ignore releases
	jnz	.done

        inc     byte[TimerTick]
        mov     al, 24
        mov     ah, [Level]  ; TimerTick = 12-Level with min amount of 2
        cmp     ah, 9
        jbe     .NotAboveLevel9
        mov     ah, 10
.NotAboveLevel9:
        sub     al, ah
        cmp     [TimerTick], al
        jne     .done
        call    _RandomMove
        call    _GameOver
        xor     al, al
        mov     [TimerTick], al
.done
        mov     al, 20h
        out     20h, al

        xor     eax, eax
        ret
TimerHandler_end


;--------------------------------------------------------------
;--			InstallMouse()		    --
;--	Input:	None 
;--	Output: Writes to variables: MouseSeg, MouseOff 
;--		Returns 1 on error, 0 otherwise 
;--	Purpose: Install the mouse callback 
;--	Notes:	Don't forget to lock areas the callback will access 
;--		You need to use a library function to obtain a real-mode callback address (segment and
;                       offset) that you can pass to Int 33h.
;--		Do not try to pass cs and the offset of MouseCallback directly to Int 33h: selectors are not the
;                       same as segments!
;--		You want the callback to be called on left mouse button press and release as
;                       well as on mouse movement.
;--		To get the length of the handler, subtract the start of the handler from the
;                       label at the end of the handler (remember, labels are just addresses)
;       from MP4 code
;       
;--------------------------------------------------------------
_InstallMouse

        push eax
        push edx
        push bx

        mov eax,_MouseCallback_end
        sub eax,_MouseCallback

        invoke _LockArea, word ds, dword _MouseCallback, dword eax
        invoke _Get_RMCB, dword _MouseSeg, dword _MouseOff, dword _MouseCallback, byte 0

        mov dword [DPMI_EAX],0Ch 	;call the mouse handler function
        mov dword [DPMI_ECX],07h 	;set the required bits to 1
        mov edx, dword [_MouseSeg]
        mov dword [DPMI_ES],edx
        mov edx, dword [_MouseOff]
        mov dword [DPMI_EDX],edx ;[es:edx]
        mov bx,33h 			; the mouse interrupt
        call DPMI_Int

        pop bx
        pop edx
        pop eax
	ret

;--------------------------------------------------------------
;--			RemoveMouse()		     --
;--	Input:	Reads from variables: MouseSeg, MouseOff 
;--	Output:	None 
;--	Purpose: Remove the mouse callback 
;--	Notes:	Uninstall the mouse callback using Int 33h before you free the real-mode callback. 
;--------------------------------------------------------------
_RemoveMouse

        push bx
        push si

        xor si, si

        mov word [DPMI_EAX], 000Ch	; call the mouse handler function
        mov word [DPMI_ECX], 0007h	; se the requireds bits to one
        mov word [DPMI_ES], si
        mov word [DPMI_EDX], si
        mov bx, 33h			; mouse interrupt
        call DPMI_Int

        pop si
        pop bx

        invoke _Free_RMCB, dword [_MouseSeg], dword [_MouseOff]	;free mouse

	ret

;--------------------------------------------------------------
;--                        MouseCallback()                   --
;Input: DPMIRegsPtr, pointer to a DPMI registers structure
;Output: Adds event to event queue
;Purpose: Process mouse input
;Notes: Index into the DPMI registers structure using the library-defined DPMI_*_off, where *=EAX,EBX, etc.
;       Look at the mouse interrupt documentation to find what registers map to what variables
;       See the Mouse section for further information.
;--------------------------------------------------------------
proc _MouseCallback
%$DPMIRegsPtr	arg	4

        xor eax, eax	;clear the registers
        xor ecx, ecx
        xor ebx, ebx
        cmp byte[_QueueNumEvents], byte QUEUE_ELEMENTS

        je .Full	; if the event queue is full

        movzx eax, byte [_QueueNumEvents]
        mov ecx, Event_size
        mul ecx
        add eax, [_QueueFirst]
        mov ebx, _Queue
        add ebx, QUEUE_SIZE
        mov edx, 0
        cmp eax, ebx
        
        jl .NotBigger
        sub eax, QUEUE_SIZE

.NotBigger
        push esi
        mov esi, dword[ebp+%$DPMIRegsPtr]
        mov cx, [esi+DPMI_EAX_off]
        mov word[eax+Event.Condition], cx
        mov cx, [esi+DPMI_ECX_off]
        mov word [eax+Event.X], cx
        mov cx, [esi + DPMI_EDX_off]
        mov word[eax+Event.Y], cx
        mov cx, [esi+DPMI_EBX_off]
        mov word[eax+Event.Buttons], cx
        add byte[_QueueNumEvents], byte 1

        pop esi

.Full     ; if the queue is full, we exit the function
        endproc
_MouseCallback_end


;---------------------------------------------------------------------------
;MovePlayer
;Purpose - update the position of the player
;Input - XPos, YPos
;Output - XPos, Ypos
;Call - CheckPlayerOFB, CheckPlayerCollision, and CheckPlayerOFB
;written by Stu Johnson
;modified by Jason Leake
;---------------------------------------------------------------------------
_MovePlayer       ;add to this function - every time player takes a step and goes from not
                        ; in his territory to in his territory, call calculate territory
                            ;every time player changes direction, write to the line buffer
                ;
        push eax
        push ebx
        mov     eax, dword [GameFlags]
        and     eax, 00000000000000000000000000011000b
        cmp     eax, 24
        je      near .moveUp
        cmp     eax, 16
        je      near .moveLeft
        cmp     eax, 8
        je      near .moveRight
        cmp     eax, 0           ;don't need this actually
        je      near .moveDown
.moveLeft:
        mov     eax, 00000000000000000000100000000000b         ;in or out of territory
        and     eax, dword [GameFlags]
        cmp     eax, 0
        je      .outOfTerritory
                                                        ;we are in territory
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000110b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection
        cmp     ebx, 00000000000000000000000000000010b
        je      .noChangeDirection                              ; if he was going the opposite direction we don't need to store into the line buffer
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx  ;storing xy because of direction change
        inc     index

.noChangeDirection:
        sub     word [XPos], 2
        call    _CheckPlayerCollision
        mov     eax, 00010000h              ;2^16  16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove
        jmp     .collide
.checkMove:
        call    _CheckPlayerOFB             ; check if player moved out of his  territory
        mov     ebx, 00000000000000000000100000000000b               ;bit 11 is in or out of territory, 1 means in territory
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        jne     near .endMovePlayer           ; we have checked everything and moved our player
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

.collide:
        add     word [XPos],2
        jmp     .endMovePlayer
.outOfTerritory:
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000110b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection1
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

.noChangeDirection1:
        
        sub     word [XPos], 2
        call    _CheckPlayerCollision
        mov     eax, 00010000h       ;2^16        16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove1
        jmp     .collide1
.checkMove1:
        call    _CheckPlayerOFB
        mov     ebx, 0000000000000000000100000000000b
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        je      near .endMovePlayer
        ;moved back into territory so we need to call calculate territory and move XY coordinates into the Line Buffer
        call    _Calculate_Territory

.collide1:
        add     word [XPos], 2
        jmp     .endMovePlayer

.moveRight:
        mov     eax, 00000000000000000000100000000000b         ;in or out of territory
        and     eax, dword [GameFlags]
        cmp     eax, 0
        je    near  .outOfTerritory2
                                                        ;we are in territory
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000010b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection2
        cmp     ebx, 00000000000000000000000000000110b
        je      .noChangeDirection2
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

.noChangeDirection2:
        add     word [XPos], 2
        call    _CheckPlayerCollision
        mov     eax, 00010000h           ;2^16  16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove2
        jmp     .collide2
.checkMove2:
        call    _CheckPlayerOFB             ; check if player moved out of his  territory
        mov     ebx, 00000000000000000000100000000000b               ;bit 11 is in or out of territory, 1 means in territory
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        jne     near .endMovePlayer           ; we have checked everything and moved our player
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

.collide2:
        sub     word [XPos], 2
        jmp     .endMovePlayer
.outOfTerritory2:
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000010b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection3
        cmp     ebx, 00000000000000000000000000000110b
        je      .noChangeDirection3
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

.noChangeDirection3:
        
        add     word [XPos], 2
        call    _CheckPlayerCollision
        mov     eax, 00010000h     ;2^16  16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove3
        jmp     .collide3
.checkMove3:
        call    _CheckPlayerOFB
        mov     ebx, 0000000000000000000100000000000b
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        je      near .endMovePlayer
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index
        ;moved back into territory so we need to call calculate territory and move XY coordinates into the Line Buffer
        call    _Calculate_Territory
.collide3:
        sub     word [XPos], 2
        jmp     .endMovePlayer
.moveUp:
        mov     eax, 00000000000000000000100000000000b         ;in or out of territory
        and     eax, dword [GameFlags]
        cmp     eax, 0
        je      near .outOfTerritory3
                                                        ;we are in territory
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000100b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection4
        cmp     ebx, 00000000000000000000000000000000b
        je      .noChangeDirection
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index
        ;mov XY coordinates into the line buffer because we have changed direction
.noChangeDirection4:
        sub     word [YPos], 4
        call    _CheckPlayerCollision
        mov     eax, 00010000h               ;2^16   16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove4
        jmp     .collide4
.checkMove4:
        call    _CheckPlayerOFB             ; check if player moved out of his  territory
        mov     ebx, 00000000000000000000100000000000b               ;bit 11 is in or out of territory, 1 means in territory
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        jne     near    .endMovePlayer           ; we have checked everything and moved our player
        ;moved out of territory so need to put XY coordinates into the Line Buffer Queue
.collide4:
        add     word [YPos], 4
        jmp     .endMovePlayer
.outOfTerritory3:
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000100b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection5
        cmp     ebx, 00000000000000000000000000000000b
        je      .noChangeDirection5
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

        ;mov XY coordinates into the line buffer because we have changed direction
.noChangeDirection5:
        
        sub     word [YPos], 4
        call    _CheckPlayerCollision
        mov     eax, 00010000h                  ;2^16  16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove5
        jmp     .collide5
.checkMove5:
        call    _CheckPlayerOFB
        mov     ebx, 0000000000000000000100000000000b
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        je      near .endMovePlayer
        ;moved back into territory so we need to call calculate territory and move XY coordinates into the Line Buffer
        call    _Calculate_Territory
.collide5:
        add     word [YPos], 4
        jmp     .endMovePlayer
.moveDown:
        mov     eax, 00000000000000000000100000000000b         ;in or out of territory
        and     eax, dword [GameFlags]
        cmp     eax, 0
        je   near   .outOfTerritory4
                                                        ;we are in territory
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000000b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection6
        cmp     ebx, 00000000000000000000000000000100b
        je      .noChangeDirection6
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

        ;mov XY coordinates into the line buffer because we have changed direction
.noChangeDirection6:
        add     word [YPos], 4
        call    _CheckPlayerCollision
        mov     eax, 00010000h          ;2^16  16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove6
        jmp     .collide6
.checkMove6:
        call    _CheckPlayerOFB             ; check if player moved out of his  territory
        mov     ebx, 00000000000000000000100000000000b               ;bit 11 is in or out of territory, 1 means in territory
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        jne   near  .endMovePlayer           ; we have checked everything and moved our player
        ;moved out of territory so need to put XY coordinates into the Line Buffer Queue
.collide6:
        sub     word [YPos], 4
        jmp     .endMovePlayer
.outOfTerritory4:
        mov     ebx, 00000000000000000000000000000110b       ;bits 2and 3 are previous direction bits
        and     ebx, dword [GameFlags]
        cmp     ebx, 00000000000000000000000000000000b      ; going same direction if previous direction equals current direction
        je      .noChangeDirection7
        cmp     ebx, 00000000000000000000000000000100b
        je      noChangeDirection7
        mov     ax, word [XPos]
        mov     bx, word [YPos]
        mov     word[LineBuffer + index*4], ax
        mov     word[LineBuffer + index*4 +2], bx
        inc     index

        ;mov XY coordinates into the line buffer because we have changed direction
.noChangeDirection7:
        
        add     word [YPos],4
        call    _CheckPlayerCollision
        mov     eax, 00010000h                  ;2^16  16th bit is collision bit
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .checkMove7
        jmp     .collide7
.checkMove7:
        call    _CheckPlayerOFB
        mov     ebx, 0000000000000000000100000000000b
        and     ebx, dword [GameFlags]
        cmp     ebx, 0
        je   near   .endMovePlayer
        ;moved back into territory so we need to call calculate territory and move XY coordinates into the Line Buffer
        call    _Calculate_Territory
.collide7:
        sub     word [YPos], 4
        jmp     .endMovePlayer

.endMovePlayer:
        mov     eax, dword [GameFlags]
        and     eax, 00000000000000000000000000011000b
        cmp     eax, 24
        je      near .PmoveUp
        cmp     eax, 16
        je      near .PmoveLeft
        cmp     eax, 8
        je      near .PmoveRight
        cmp     eax, 0           ;don't need this actually
        je      near .PmoveDown
        
.PmoveLeft:
        mov     eax, 00000000000000000000000000000110b
        or      dword [GameFlags], eax
        jmp     .realEnd
.PmoveUp:
        mov     eax, 00000000000000000000000000000100b
        or      dword [GameFlags], eax
        mov     eax, 11111111111111111111111111111101b
        and     dword [GameFlags], eax
        jmp     .realEnd
.PmoveRight:
        mov     eax, 00000000000000000000000000000010b
        or      dword [GameFlags], eax
        mov     eax, 11111111111111111111111111111011b
        and     dword [GameFlags], eax
        jmp     .realEnd
.PmoveDown:
        mov     eax, 11111111111111111111111111111001b
.realEnd:

        push    ebx
        push    eax
        invoke  _LoadPNG, dword _BackgroundFN, word [_ImageBlock], dword 0, dword 0, dword 0

        pop     eax
        pop     ebx
        movzx   ebx, word[XPos]
        movzx   eax, word[YPos]

        invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 0, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer


        movzx   ebx, word[EnemyPoint.X1]
        movzx   eax, word[EnemyPoint.Y1]

        invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        movzx   ebx, word[EnemyPoint.X2]
        movzx   eax, word[EnemyPoint.Y2]

        invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer


        movzx   ebx, word[EnemyPoint.X3]
        movzx   eax, word[EnemyPoint.Y3]

        invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

pop ebx
pop eax
ret

;------------------------------------------
;_Update_Stats
;Purpose - display updated stats
;inputs -
;output - gameboard
;written by Sung Kim
;------------------------------------------
_Update_Stats

        push    eax
        push    ebx
        push    ecx

        mov     al, byte [Level]
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 194, word ax, dword 500

        mov     eax, dword[Score]
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 120, word bx, dword 564
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 120, word bx, dword 548
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 120, word bx, dword 532
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 120, word bx, dword 516
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 120, word bx, dword 500



        mov     al, byte [PercentTaken]
        mov     ah, 0
        mov     cl, 10
        div     cl
        sub     al, ah
        mov     bl, ah
        mov     bh, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 265, word bx, dword 516
        mov     ah, 0
        div     cl
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 265, word ax, dword 500

        mov     al, byte[Lives]
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 336, word ax, dword 500

        mov     eax, dword [TimeLeft]
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 407, word bx, dword 532
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 407, word bx, dword 516
        mov     cl, 10
        div     cl
        mov     bl, ah
        mov     bh, 0
        mov     ah, 0
        invoke  _DisplayStat, word [_ImageBlock], dword 407, word bx, dword 500
        pop     ecx
        pop     ebx
        pop     eax

        ret

;---------------------------------------------------------------------------
;CheckPlayerOFB
;Purpose - check if the palyer is out of territory
;Input - Xpos, Ypos, territoryMap(holds 0 or color vaules depending
;       on whether the territory is taken by the player or not)
;Output - set the in&out territory flag
;written by Stu Johnson
;---------------------------------------------------------------------------
_CheckPlayerOFB
        
        push    eax
        push    edx
        push    ebx

        movzx   eax, word[YPos]
        mov     edx, 480
        mul     edx
        movzx   ebx, word[XPos]
        add     eax, ebx                 ; eax holds position of player on Territory Map
        shl     eax, 2
        cmp     [_territoryMap + eax], 0     ; territoryMap will be a
        je      .setFlag
        and     dword [GameFlags], 11111111111111111110111111111111b
        jmp     .endCheckPlayerOFB
.setFlag:
        or      dword [GameFlags], 00000000000000000001000000000000b

.endCheckPlayerOFB:
        pop     ebx
        pop     edx
        pop     eax
        ret



;---------------------------------------------------------------------------
;CheckPlayerCollision
;Purpose - check players collison with boundaries and his line
;Input - XPos, YPos, LineBuffer, territoryMap
;Output - playerCollisionFlag 1 if player has a collison and 0 otherwise
;written by Stu Johnson
;modified by Sung Kim, Joseph Kim
;---------------------------------------------------------------------------
_CheckPlayerCollision

        push    eax
        push    ecx
        push    edx
        push    esi

        cmp     word [XPos], 5               ; if xpos is 0, player hit the boundary
        jbe     near .Boundary

        cmp     word [XPos], 300             ; if xpos is 640, player hit the boundary
        jae     near .Boundary

        cmp     word [YPos], 463             ; if ypos is 450, player hit the boundary
        jae     near .Boundary

        cmp     word [YPos], 10              ; if ypos is 100, player hit the boundary
        jbe     .Boundary
        jmp     .noBoundary
.Boundary:
        or      dword[GameFlags], 00000000000000010000000000000000b
        jmp     .endCheckPlayerCollision

.noBoundary
        xor     esi, esi                   ; si = 0
        jmp     .endCheckPlayerCollision
.beginCheck:
        mov     ax, [_LineBuffer+esi*4]      ; ax holds x pos of start of line
        push    esi
        inc     esi
        mov     cx, [_LineBuffer+esi*4]       ; cx holds x pos of next line segment
        pop     esi
        cmp     ax, cx
        je      near .xSame

.ySame:
        mov     dx, [_LineBuffer+ esi*8 +2]            ;Y position is same for both
        cmp     [YPos], dx
        jne     near .noCollision                      ; No collision if player does not have same ypos as line
        cmp     [XPos],ax
        jbe     near .xBelow
        cmp     [XPos], cx                         ;Xpos is above both values
        ja      near .noCollision
        or      dword[GameFlags], 00000000000000010000000000000000b    ;Xpos is above ax and below cx
        jmp     .endCheckPlayerCollision
.xBelow:
        cmp     [XPos], cx                                       ; Xpos is below both ax and cx
        jb      near .noCollision
        or      dword[GameFlags], 00000000000000010000000000000000b    ;Xpos is below ax and above cx
        jmp     .endCheckPlayerCollision

.xSame:
        mov     ax, [_LineBuffer+esi*4 +2]
        push    esi
        inc     esi
        mov     cx, [_LineBuffer+esi*4 +2]
        pop     esi
        mov     dx, [_LineBuffer + esi*4]            ;X position is same for both
        cmp     [XPos], dx
        jne     near .noCollision                      ; No collision if player does not have same xpos as line
        cmp     [YPos], ax
        jbe     near .yBelow
        cmp     [YPos], cx                         ;ypos is above both values
        ja      near .noCollision
        or      dword[GameFlags], 00000000000000010000000000000000b    ;ypos is above ax and below cx
        jmp     .endCheckPlayerCollision
.yBelow:
        cmp     [YPos], cx                                       ; ypos is below both ax and cx
        jb      near .noCollision
        or      dword[GameFlags], 00000000000000010000000000000000b    ;ypos is below ax and above cx
        jmp     .endCheckPlayerCollision
  
.noCollision:
        cmp     esi, 50
        je      .endCheckPlayerCollision
        inc     esi
        jmp     .beginCheck
.endCheckPlayerCollision:

        pop     esi
        pop     edx
        pop     ecx
        pop     eax

        ret



;----------------------------------------------------------------------------
;DrawPlayer
;Purpose - draw the player on the game board
;Input -DestSel, destination selector to write character into
;       Dest, offset into DestSel
;       Choice, decide whether draw the player or the enemy
;       PlayerPos, position to write character at: specified in character units, not pixels
;Output - gameboard
;written by Sung Kim, Joseph Kim
;----------------------------------------------------------------------------
proc _DrawPlayer
%$DestSel	arg	2
%$Dest		arg	4
%$Choice		arg   2                  ;0 is player & 1 is enemy
%$PlayerPos	arg	4
_DrawPlayer_arglen equ 12


	push	ds
	push	es
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	edi
	push	esi

        mov     ax, [ebp + %$Choice]
        cmp     ax, 0   ;player
        jne     near .drawEnemy
        mov     ax, [_PlayerBlock]
        jmp     .next

.drawEnemy
        mov     ax, [_EnemyBlock]

.next
	mov	es, a
	mov	ax, [ebp + %$DestSel]
	mov	ds, ax			; ds = [ebp + %$DestSel]
	mov	edi, dword [ebp + %$Dest]                 ;starting offset for y
        mov     eax, edi
        mov     ecx, 640*4
        mul     ecx
        mov     edi, eax

        xor     esi, esi
       	mov	ebx, 16			; word size    :colum size


.PosY
	push	ebx
        mov     ebx, [ebp+%$PlayerPos]     ;PlayerPos is xPos
	shl	ebx, 2   ; 4 bytes per character
	xor	ecx, ecx
.PosX
	mov	eax, dword [es:esi + ecx*4]	; copy character pixel
	inc	ebx			; copy dword by dword
	mov	dword [edi + ebx*4], eax	; copy character and color to buffer
	inc	ecx
	cmp	ecx, 16
	jne	.PosX
        
        add     esi, 64         ;16*4
	add	edi, 2560	; 640*4
	pop	ebx
	dec	ebx
	jnz	.PosY

	pop	esi
	pop	edi
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	pop	es
	pop	ds
endproc


;----------------------------------------------------------------------------
;DisplayStat
;Purpose - display the stat on the game board
;Input - DestSel, destination selector to write character into
;       Dest, offset into DestSel
;       Num, this should be the num that is the same number to display
;       NumPos, position to write character at: specified in character units,
;       not pixels
;Output - gameboard
;written by Sung Kim
;----------------------------------------------------------------------------
proc _DisplayStat
%$DestSel arg 2
%$Dest  arg 4
%$Num  arg   2              ;
%$NumPos arg 4


        push    ds
        push    es
        push    eax
        push    ebx
        push    ecx
        push    edx
        push    edi
        push    esi
        mov     ax, word [_NumBlock]
        mov     es, ax
        mov     ax, word [ebp + %$DestSel]
        mov     ds, ax   ; ds = [ebp + %$DestSel]
        mov     edi, dword [ebp + %$Dest]                 ;starting offset for y
        movzx   esi, byte [ebp + %$Num]
        shl     esi, 6
        mov     ebx, 16   ; word size

.PosY
        push ebx

        mov     ebx, dword [ebp+%$NumPos]

        shl ebx, 2   ; 4 bytes per character
        xor ecx, ecx
.PosX
        mov eax, dword [es:esi + ecx*4] ; copy character pixel
        inc ebx   ; copy dword by dword
        mov dword [edi + ebx*4], eax ; copy character and color to buffer
        inc ecx
        cmp ecx, 16
        jne .PosX
        
        add     esi, 640         ;10*16*4
        add edi, 2560 ; 640*4
        pop ebx
        dec ebx
        jnz .PosY

        pop esi
        pop edi
        pop edx
        pop ecx
        pop ebx
        pop eax
        pop es
        pop ds
endproc



;---------------------------------------------------------------------------
;Random
;Purpose - generates a random number for enemy movement
;Input - randval
;Output - ax: random number 0 to 7
;Written by Sung Kim from MP2
;---------------------------------------------------------------------------
_Random
        push    ebx
        push    ecx
        push    edx

        mov     ax, word [randVal]
        mov     cx, 37
        mov     bx, 31
        mul     cx
        add     ax, bx
        adc     dx, 0
        mov     cx, 65535
        div     cx
        mov     word [randVal], dx
        mov     ax, dx
        mov     dx, 0
        mov     cx, 8
        div     cx
        mov     ax, dx

        pop     edx
        pop     ecx
        pop     ebx
        ret

;---------------------------------------------------------------------------
;RandomMove
;Purpose - move enemies randomly while they are not chasing a player
;Input - EnemyPoint
;Output - EnemyPoint
;written by Stu Johnson
;modified by Jason Leake
;---------------------------------------------------------------------------
proc _RandomMove
        push eax
        push ebx

        call    _CheckDistance
.RandomMoveEnemy1:
        mov    eax, dword [GameFlags]
        mov     ebx, 00000000000100000000000000000000b
        and     ebx, eax                                ;ebx is 0 if chase flag was not set
        cmp     ebx, 0
        jne     .callChase
        ; we need to move randomly because the chase flag was not set
        call    _Random                                 ;gets random value for randVal
        add     ax, 2                   ;ax is number between 2 and 9
        shr     ax, 1                   ;ax is between 1 and 4
        cmp     ax, 4
        je      .MoveLeft
        cmp     ax, 3
        je       .MoveUp
        cmp     ax, 2
        je      .MoveRight
        cmp     ax, 1
        je      .MoveDown
.MoveLeft:
        mov     eax, 00020000h          ;2^17  ;17th bit is collision bit
        sub     word [EnemyPoint.X1], 2
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .RandomMoveEnemy2
        inc     word [EnemyPoint.X1]
        jmp     .RandomMoveEnemy2
.MoveRight:
        mov     eax, 00020000h                  ;2^17
        add     word [EnemyPoint.X1], 2
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .RandomMoveEnemy2
        dec     word [EnemyPoint.X1]
        jmp     .RandomMoveEnemy2
.MoveDown:
        mov     eax, 00020000h                           ;2^17
        add     word [EnemyPoint.Y1], 4
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .RandomMoveEnemy2
        dec     word [EnemyPoint.Y1]
        jmp     .RandomMoveEnemy2
.MoveUp:
        mov     eax, 00020000h                          ;2^17
        sub     word [EnemyPoint.Y1], 4
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .RandomMoveEnemy2
        inc     word [EnemyPoint.Y1]

        jmp     .RandomMoveEnemy2

.RandomMoveEnemy2:

        mov    eax, dword [GameFlags]
        mov     ebx, 00000000001000000000000000000000b
        and     ebx, eax                                ;ebx is 0 if chase flag was not set
        cmp     ebx, 0
        jne     .callChase
        ;we need to move randomly because the chase flag was not set
        call    _Random                                 ;gets random value for randVal
        add     ax, 2                                  ;ax is number between 2 and 9
        shr     ax, 1                                 ;ax is between 1 and 4
        cmp     ax, 4
        je      .MoveLeft2
        cmp     ax, 3
        je      .MoveUp2
        cmp     ax, 2
        je      .MoveRight2
        cmp     ax, 1
        je      .MoveDown2
.MoveLeft2:
        mov     eax, 00040000h          ;2^18    18th bit is collision bit
        sub     word [EnemyPoint.X2], 2
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .RandomMoveEnemy3
        inc     word [EnemyPoint.X2]
        jmp     .RandomMoveEnemy3
.MoveRight2:
        mov     eax, 00040000h                  ;2^18
        add     word [EnemyPoint.X2], 2
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .RandomMoveEnemy3
        dec     word [EnemyPoint.X2]
        jmp     .RandomMoveEnemy3
.MoveDown2:
        mov     eax, 00040000h                  ;2^18
        add     word [EnemyPoint.Y2], 4
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .RandomMoveEnemy3
        dec     word [EnemyPoint.Y2]
        jmp     .RandomMoveEnemy3
.MoveUp2:
        mov     eax, 00040000h                  ;2^18
        sub     word [EnemyPoint.Y2], 4
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .RandomMoveEnemy3
        inc     word [EnemyPoint.Y2]
        jmp     .RandomMoveEnemy3


.RandomMoveEnemy3:

        mov    eax, dword [GameFlags]
        mov     ebx, 00000000001000000000000000000000b
        and     ebx, eax                                ;ebx is 0 if chase flag was not set
        cmp     ebx, 0
        jne     .callChase
        ; we need to move randomly because the chase flag was not set
        call    _Random                                 ;gets random value for randVal
        add     ax, 2                    ;ax is number between 2 and 9
        shr     ax, 1                    ;ax is between 1 and 4
        cmp     ax, 4
        je      .MoveLeft3
        cmp     ax, 3
        je      .MoveUp3
        cmp     ax, 2
        je      .MoveRight3
        cmp     ax, 1
        je      .MoveDown3
.MoveLeft3:
        mov     eax, 00080000h             ;2^19  ;19th bit is collision bit
        sub     word [EnemyPoint.X3], 2
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no collision
        je      .endRandomMove
        inc     [EnemyMove.X3]
        jmp     .endRandomMove
.MoveRight3:
        mov     eax, 00080000h                  ;2^19
        add     word [EnemyPoint.X3], 2
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .endRandomMove
        dec     word [EnemyPoint.X3]
        jmp     .endRandomMove
.MoveDown3:
        mov     eax, 00080000h                  ;2^19
        add     word [EnemyPoint.X3], 4
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .endRandomMove
        cmp     eax
        dec     word [EnemyPoint.Y3]
        jmp     .endRandomMove
.MoveUp3:
        mov     eax, 00080000h                  ;2^19
        sub     word [EnemyPoint.Y3], 4
        call    CheckEnemyCollision
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .endRandomMove
        inc     word [EnemyPoint.Y3]
        jmp     .endRandomMove

.callChase:
        call    _Chase

.endRandomMove:
       push    ebx
        push    eax
        invoke  _LoadPNG, dword _BackgroundFN, word [_ImageBlock], dword 0, dword 0, dword 0

        pop     eax
        pop     ebx
        movzx   ebx, word[XPos]
        movzx   eax, word[YPos]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 0, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer


        movzx   ebx, word[EnemyPoint.X1]
        movzx   eax, word[EnemyPoint.Y1]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

        movzx   ebx, word[EnemyPoint.X2]
        movzx   eax, word[EnemyPoint.Y2]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer


        movzx   ebx, word[EnemyPoint.X3]
        movzx   eax, word[EnemyPoint.Y3]

       invoke  _DrawPlayer, word [_ImageBlock], dword eax, word 1, dword ebx
       	call	libCopyImageToScreen
	call	_RefreshVideoBuffer

endproc



;---------------------------------------------------------------------------
;CheckDistance
;Purpose - to find the distance between enemies and the line drawn by the player or the player and determine which is closest and whether the player or the line is close enough to chase
;Input - XPosE1, YPosE1, XPosE2, YPosE2, XPosE3, YPosE3, LineBuffer,
;Output - set ChaseFlag
;written by Stu Johnson
;modified by Jason Leake
;---------------------------------------------------------------------------
proc _CheckDistance
;finding distance of player to enemy
        push    ax
        push    bx
        push    cx
        push    edx
        mov     eax, 00000800h
        and     eax, dword [GameFlags]
        cmp     eax, 0
        je      .donotchase
        mov     ax, word [XPos]                 ;ax has x poedxtion of player
        mov     bx, word [EnemyPoint.X1]        ;bx has x poedxtion of enemy1
        sub     ax, bx                   ;ax has the difference in x poedxtions
        cmp     ax, 0
        ja      .yDiff                   ;if ax is negative we want to make it poedxtive
        neg     ax
        inc     ax
.yDiff:
        mov     bx, word [YPos]                 ;bx has y poedxtion of player
        mov     cx, word [EnemyPoint.Y1]        ;cx has y poedxtion of enemy1
        sub     bx, cx
        cmp     bx, 0
        ja      .addDiff
        neg     bx
        inc     bx
.addDiff:
        add     ax, bx                  ;ax has (Xp-Xe)+(Yp-Ye)
        mov     word [ClosestPointE1], ax
        ; now I need to calculate this same total for every midpoint of the line buffer
        xor     edx, edx
.beginCalc:                                   ;finding distance from linebuffer to enemy
                ;finding midpoint
        mov     ax, word [_LineBuffer+edx*4]        ;bx has x coordinate of  linebuffer
        mov     cx, word [_LineBuffer+edx*4+4]      ;cx has next x coordinate of linebuffer
        cmp     ax, cx                      ;check if the X coordinates are different
        je      .getYmid
        add     ax, cx
        div     2
        mov     ah, 0                           ;al now has the midpoint of the change in x
        mov     cx, word [EnemyPoint.X1]
        sub     ax, cx                      ;ax has diff between midpoint of x and enemyX
        cmp     ax, 0                       ;make sure ax is above 0
        ja      .getYdiff
        neg     ax
        inc     ax
.getYdiff:
        mov     cx, word [_LineBuffer+edx*4+2]
        mov     bx, word [EnemyPoint.Y1]
        sub     cx, bx
        cmp     cx, 0                        ;cx has diff between y of line buffer and enemyy
        ja      .addxy
        neg     cx
        inc     cx                       ;make sure cx is above 0
.addxy:
        add     ax, cx                       ;ax now has(Xmidpoint - Xe)+(Y - Ye)
        jmp     .findMin
.getYmid:
        mov     ax, word [_LineBuffer+edx*4+2]
        mov     bx, word [LineBuffer+edx*4+6]
        div     2
        mov     ah, 0                           ;al now has the midpoint of the change in Y
        mov     cx, word [EnemyPoint.Y1]
        sub     ax, cx                      ;ax has diff between midpoint of y and enemyY
        cmp     ax, 0                       ;make sure ax is above 0
        ja      .getXdiff
        neg     ax
        inc     ax
.getXdiff:
        mov     cx, word [LineBuffer+edx*4]
        mov     bx, word [EnemyPoint.X1]
        sub     cx, bx
        cmp     cx, 0                        ;cx has diff between X of line buffer and enemyy
        ja      .addyx
        neg     cx
        add     cx, 1                        ;make sure cx is above 0
.addyx:
        add     ax, cx                       ;ax now has(Ymidpoint - Ye)+(X - Xe)
        ;jmp     .findMin
.findMin:
        mov     bx, word [LineBuffer+edx*4]
        mov     cx, word [EnemyPoint.X1]
        sub     bx, cx
        cmp     bx, 0                         ;bx now has (X-Xe)
        jae     .donotnegate                     ;make sure it is not negative
        neg     bx
        add     bx, 1
.donotnegate:
        mov     cx, word [LineBuffer+edx*4+2]
        mov     dx, word [EnemyPoint.Y1]
        sub     cx, dx
        cmp     cx, 0
        jae     .addem
        neg     cx
        inc     cx
.addem:
        add     bx, cx                        ;bx now has (Y - Ye)+ (X - Xe)of this point in the line buffer
        cmp     word [ClosestPointE1], bx     ;compare bx to closest point
        jb      .nextCompare
        mov     word [ClosestPointE1], bx
        mov     word [ClosestBufferE1], edx
.nextCompare:
        cmp     word [ClosestPointE1], ax
        jb      .keepChecking
        mov     word [ClosestPointE1], ax
        mov     word [ClosetBufferE1], edx
        cmp     edx, 50
        je      .setEnemy1ChaseFlag
        inc     edx
        jmp     beginCalc

.keepChecking:
        
        cmp     edx, 50
        je      .setEnemy1ChaseFlag
        inc     edx
        jmp     beginCalc
.setEnemy1ChaseFlag:
        mov     al, byte [Level]
        cmp     al, 4
        jae     .Distance2
        cmp     word [ClosestPointE1], 50             ; chase point
        jl      .chase
        jmp     .CheckEnemy2
.Distance2:
        cmp     ax, 7
        jae     .Distance3
        cmp     word [ClosestPointE1], 75
        jl      .chase
        jmp     .CheckEnemy2
.Distance3:
        cmp     word [ClosestPointE1], 100
        jl      .chase
        jmp     .CheckEnemy2
.chase:
        or      dword [GameFlags], 00100000h



CheckEnemy2:
        mov     ax, word [XPos]                 ;ax has x poedxtion of player
        mov     bx, word [EnemyPoint.X2]        ;bx has x poedxtion of enemy2
        sub     ax, bx                   ;ax has the difference in x poedxtions
        cmp     ax, 0
        ja      .yDiff2                   ;if ax is negative we want to make it poedxtive
        neg     ax
        inc     ax
.yDiff2:
        mov     bx, word [YPos]                 ;bx has y poedxtion of player
        mov     cx, word [EnemyPoint.Y2]        ;cx has y poedxtion of enemy2
        sub     bx, cx
        cmp     bx, 0
        ja      .addDiff2
        neg     bx
        inc     bx
.addDiff2:
        add     ax, bx                  ;ax has (Xp-Xe)+(Yp-Ye)
        mov     word [ClosestPointE2], ax
        ; now I need to calculate this same total for every midpoint of the line buffer
        xor     edx, edx
.beginCalc2:                                   ;finding distance from linebuffer to enemy
                ;finding midpoint
        mov     ax, word [LineBuffer+edx*4]        ;bx has x coordinate of  linebuffer
        mov     cx, word [LineBuffer+edx*4+4]      ;cx has next x coordinate of linebuffer
        cmp     ax, cx                      ;check if the X coordinates are different
        je      .getYmid2
        add     ax, cx
        div     2
        mov     ah, 0                           ;al now has the midpoint of the change in x
        mov     cx, word [EnemyPoint.X2]
        sub     ax, cx                      ;ax has diff between midpoint of x and enemyX
        cmp     ax, 0                       ;make sure ax is above 0
        ja      .getYdiff2
        neg     ax
        inc     ax
.getYdiff2:
        mov     cx, word [LineBuffer+edx*4+2]
        mov     bx, word [EnemyPoint.Y2]
        sub     cx, bx
        cmp     cx, 0                        ;cx has diff between y of line buffer and enemyy
        ja      .addxy2
        neg     cx
        inc     cx                       ;make sure cx is above 0
.addxy2:
        add     ax, cx                       ;ax now has(Xmidpoint - Xe)+(Y - Ye)
        jmp     .findMin2
.getYmid2:
        mov     ax, word [LineBuffer+edx*4+2]
        mov     bx, word [LineBuffer+edx*4+6]
        div     2
        mov     ah, 0                           ;al now has the midpoint of the change in Y
        mov     cx, word [EnemyPoint.Y2]
        sub     ax, cx                      ;ax has diff between midpoint of y and enemyY
        cmp     ax, 0                       ;make sure ax is above 0
        ja      .getXdiff2
        neg     ax
        inc     ax
.getXdiff2:
        mov     cx, word [LineBuffer+edx*4]
        mov     bx, word [EnemyPoint.X2]
        sub     cx, bx
        cmp     cx, 0                        ;cx has diff between X of line buffer and enemyy
        ja      .addyx2
        neg     cx
        add     cx, 1                        ;make sure cx is above 0
.addyx2:
        add     ax, cx                       ;ax now has(Ymidpoint - Ye)+(X - Xe)
        ;jmp     .findMin2
.findMin2:
        mov     bx, word [LineBuffer+edx*4]
        mov     cx, word [EnemyPoint.X2]
        sub     bx, cx
        cmp     bx, 0                         ;bx now has (X-Xe)
        jae     .donotnegate2                     ;make sure it is not negative
        neg     bx
        add     bx, 1
.donotnegate2:
        mov     cx, word [LineBuffer+edx*4+2]
        mov     dx, word [EnemyPoint.Y2]
        sub     cx, dx
        cmp     cx, 0
        jae     .addem2
        neg     cx
        inc     cx
.addem2:
        add     bx, cx                        ;bx now has (Y - Ye)+ (X - Xe)of this point in the line buffer
        cmp     word [ClosestPointE2], bx     ;compare bx to closest point
        jb      .nextCompare2
        mov     word [ClosestPointE2], bx
        mov     word [ClosestBufferE2], edx
.nextCompare2:
        cmp     word [ClosestPointE2], ax
        jb      .keepChecking2
        mov     word [ClosestPointE2], ax
        mov     word [ClosetBufferE2], edx
        cmp     edx, 50
        je      .setEnemy2ChaseFlag
        inc     edx
        jmp    beginCalc2

.keepChecking2:
        
        cmp     edx, 50
        je      .setEnemy2ChaseFlag
        inc     edx
        jmp    beginCalc2
.setEnemy2ChaseFlag:
        mov     al, byte [Level]
        cmp     al, 4
        jae     .Distance2
        cmp     word [ClosestPointE2], 50             ; chase point
        jl      .chase2
        jmp     .CheckEnemy3
.Distance22:
        cmp     ax, 7
        jae     .Distance32
        cmp     word [ClosestPointE2], 75
        jl      .chase2
        jmp     .CheckEnemy3
.Distance32:
        cmp     word [ClosestPointE2], 100
        jl      .chase2
        jmp     .CheckEnemy3
.chase2:
        or      dword [GameFlags], 00200000h



.CheckEnemy3:
        mov     ax, word [XPos]                 ;ax has x poedxtion of player
        mov     bx, word [EnemyPoint.X3]        ;bx has x poedxtion of enemy1
        sub     ax, bx                   ;ax has the difference in x poedxtions
        cmp     ax, 0
        ja      .yDiff3                   ;if ax is negative we want to make it poedxtive
        neg     ax
        inc     ax
.yDiff3:
        mov     bx, word [YPos]                 ;bx has y poedxtion of player
        mov     cx, word [EnemyPoint.Y3]        ;cx has y poedxtion of enemy1
        sub     bx, cx
        cmp     bx, 0
        ja      .addDiff3
        neg     bx
        inc     bx
.addDiff3:
        add     ax, bx                  ;ax has (Xp-Xe)+(Yp-Ye)
        mov     word [ClosestPointE3], ax
        ; now I need to calculate this same total for every midpoint of the line buffer
        xor     edx, edx
.beginCalc3:                                   ;finding distance from linebuffer to enemy
                ;finding midpoint
        mov     ax, word [LineBuffer+edx*4]        ;bx has x coordinate of  linebuffer
        mov     cx, word [LineBuffer+edx*4+4]      ;cx has next x coordinate of linebuffer
        cmp     ax, cx                      ;check if the X coordinates are different
        je      .getYmid3
        add     ax, cx
        div     2
        mov     ah, 0                           ;al now has the midpoint of the change in x
        mov     cx, word [EnemyPoint.X3]
        sub     ax, cx                      ;ax has diff between midpoint of x and enemyX
        cmp     ax, 0                       ;make sure ax is above 0
        ja      .getYdiff3
        neg     ax
        inc     ax
.getYdiff3:
        mov     cx, word [LineBuffer+edx*4+2]
        mov     bx, word [EnemyPoint.Y3]
        sub     cx, bx
        cmp     cx, 0                        ;cx has diff between y of line buffer and enemyy
        ja      .addxy3
        neg     cx
        inc     cx                       ;make sure cx is above 0
.addxy3:
        add     ax, cx                       ;ax now has(Xmidpoint - Xe)+(Y - Ye)
        jmp     .findMin3
.getYmid3:
        mov     ax, word [LineBuffer+edx*4+2]
        mov     bx, word [LineBuffer+edx*4+6]
        div     2
        mov     ah, 0                           ;al now has the midpoint of the change in Y
        mov     cx, word [EnemyPoint.Y3]
        sub     ax, cx                      ;ax has diff between midpoint of y and enemyY
        cmp     ax, 0                       ;make sure ax is above 0
        ja      .getXdiff3
        neg     ax
        inc     ax
.getXdiff3:
        mov     cx, word [LineBuffer+edx*4]
        mov     bx, word [EnemyPoint.X3]
        sub     cx, bx
        cmp     cx, 0                        ;cx has diff between X of line buffer and enemyy
        ja      .addyx3
        neg     cx
        add     cx, 1                        ;make sure cx is above 0
.addyx3:
        add     ax, cx                       ;ax now has(Ymidpoint - Ye)+(X - Xe)
        ;jmp     .findMin
.findMin3:
        mov     bx, word [LineBuffer+edx*4]
        mov     cx, word [EnemyPoint.X3]
        sub     bx, cx
        cmp     bx, 0                         ;bx now has (X-Xe)
        jae     .donotnegate3                     ;make sure it is not negative
        neg     bx
        add     bx, 1
.donotnegate3:
        mov     cx, word [LineBuffer+edx*4+2]
        mov     dx, word [EnemyPoint.Y3]
        sub     cx, dx
        cmp     cx, 0
        jae     .addem3
        neg     cx
        inc     cx
.addem3:
        add     bx, cx                        ;bx now has (Y - Ye)+ (X - Xe)of this point in the line buffer
        cmp     word [ClosestPointE3], bx     ;compare bx to closest point
        jb      .nextCompare3
        mov     word [ClosestPointE3], bx
        mov     word [ClosestBufferE3], edx
.nextCompare3:
        cmp     word [ClosestPointE3], ax
        jb      .keepChecking3
        mov     word [ClosestPointE3], ax
        mov     word [ClosetBufferE3], edx
        cmp     edx, 50
        je      .setEnemy3ChaseFlag
        inc     edx
        jmp    beginCalc3

.keepChecking3:
        
        cmp     edx, 50
        je      .setEnemy3ChaseFlag
        inc     edx
        jmp    beginCalc3
.setEnemy3ChaseFlag:
        mov     ax, level
        cmp     ax, 4
        jae     .Distance23
        cmp     word [ClosestPointE3], 50             ; chase point
        jl      .chase3
        jmp     .endCheckDistance
.Distance23:
        cmp     ax, 7
        jae     .Distance33
        cmp     word [ClosestPointE3], 75
        jl      .chase3
        jmp     .endCheckDistance
.Distance33:
        cmp     word [ClosestPointE3], 100
        jl      .chase3
        jmp     .endCheckDistance
.chase3:
        or      dword [GameFlags], 00400000h
.endCheckDistance:
jmp .avoidoverwrite
.donotchase
and dword [GameFlags], 0FF8FFFFFh
.avoidoverwrite:
pop edx
pop cx
pop bx
pop ax
        ;ret
endproc
;---------------------------------------------------------------------------
;Chase
;Purpose - to cause enemies to chase after the player
;Input - XPos, Ypos, XPosE1, YPosE1, XPosE2, YPosE2, XPosE3, YPosE3
;Output - XPosE1, YPosE1, XPosE2, YPosE2, XPosE3, YPosE3
;written by Stu Johnson
;modified by Jason Leake
;---------------------------------------------------------------------------
proc _Chase
        push    eax
        push    ebx
        push    dx
                ;closestpoint has value
                ;closestbuffer has value
        mov     ax, word [LineBuffer+ClosestBufferE1*4] ;first find if closest point is a midpoint of point of turning
        mov     bx, word [EnemyPoint.X1]
        sub     ax, bx
        cmp     ax, 0
        jbe     .nonegate                                 ;ax has (X - Xe)
        neg     ax
        inc     ax
.nonegate:
        mov     bx, word [LineBuffer+ClosestBufferE1*4+2]
        mov     cx, word [EnemyPoint.Y1]
        sub     bx, cx                                   ;bx has (Y - Ye)
        cmp     bx, 0
        jbe     .compareClosest
        neg     bx
        inc     bx
.compareClosest:
        add     ax, bx
        cmp     ax, word [ClosestPointE1]  ;if these are equal, enemy should chase point in the buffer
        jne     .Midpoint
        mov     ax, word [LineBuffer+ClosetBufferE1*4]         ;ax has X coordinate of closest point
        mov     bx, word [LineBuffer+ClosetBufferE1*4+2]         ;bx has Y coordinate of closest point
        jmp     .enemychase
.Midpoint:
                                                        ;must find midpoint of line for enemy to chase
        mov     ax, word [LineBuffer+ClosetBufferE1*4]        ;x has x coordinate of  linebuffer
        mov     bx, word [LineBuffer+ClosetBufferE1*4+4]      ;cx has next x coordinate of linebuffer
        cmp     ax, bx                      ;check if the X coordinates are different
        je      .ymid
        add     ax, bx
        mov     bx, 2
        div     bx
        ; where does this answer go,  do I have to move 0 into a register to make sure I don't use remainder
        mov     bx, word [LineBuffer+ClosetBufferE1*4+2]
        jmp     .enemychase
.ymid:
        mov     ax, word [LineBuffer+ClosetBufferE1*4+2]
        mov     bx, word [LineBuffer+ClosetBufferE1*4+6]
        add     ax, bx
        div     2
        mov     bx, ax
        mov     ax, word [LineBuffer+ClosetBufferE1]
.enemychase:
        mov     word [chasePointX], ax
        mov     word [chasePointY], bx
        mov     cx, word [EnemyPoint.X1]               ;ax has X coordinate to chase, bx has y coordinate to chase
        sub     ax, cx
        cmp     ax, 0
        jb      .nochangeedxgn                                  ;if negative then player is to the left of enemy
        neg     ax
        inc     ax
.nochangeedxgn:
        mov     dx, word [EnemyPoint.Y1]
        sub     bx, dx
        jb      .nochangeedxgn1
        neg     bx
        inc     bx
.nochangeedxgn1:                                          ;ax and bx have difference of x and y coordinates of enemy and closest point
        cmp     ax, bx
        jb      .movupdown                               ; we need to move left or right now
        mov     ax, word [chasePointX]
        mov     bx, word [EnemyPoint.X1]
        sub     ax, bx
        cmp     ax, 0
        jb      .chaseLeft
                                         ;move right
        mov     eax, 00020000h           ;2^17
        inc     word [EnemyPoint.X1]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .chaseEnemy2
        dec     word [EnemyPoint.X1]
        jmp     .chaseEnemy2
.chaseLeft:
                                          ;move left
        mov     eax, 00020000h            ;2^17     17th bit is colliedxon bit
        dec     word [EnemyPoint.X1]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no colliedxon
        je      .chaseEnemy2
        inc     word [EnemyPoint.X1]
        jmp     .chaseEnemy2

.movupdown:
        
        mov     ax, word [chasePointY]
        mov     bx, word [EnemyPoint.Y1]
        sub     ax, bx
        cmp     ax, 0
        jb      .chaseUp
        mov     eax, 00020000h                  ;2^17  chaedxng down
        inc     word [EnemyPoint.Y1]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .chaseEnemy2
        dec     word [EnemyPoint.Y1]
        jmp     .chaseEnemy2
.chaseUp:
        mov     eax, 00020000h
        dec     word [EnemyPoint.Y1]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .chaseEnemy2
        inc     word [EnemyPoint.Y1]
        jmp     .chaseEnemy2
.chaseEnemy2:
        
        mov     ax, word [_LineBuffer+ClosetBufferE2*4]          ;first find if closest point is a midpoint of point of turning
        mov     bx, word [EnemyPoint.X2]
        sub     ax, bx
        cmp     ax, 0
        jbe     .nonegate2                                 ;ax has (X - Xe)
        neg     ax
        inc     ax
.nonegate2:
        mov     bx, word [_LineBuffer+ClosetBufferE2*4+2]
        mov     cx, word [EnemyPoint.Y2]
        sub     bx, cx                                   ;bx has (Y - Ye)
        cmp     bx, 0
        jbe     .compareClosest2
        neg     bx
        inc     bx
.compareClosest2:
        add     ax, cx
        cmp     ax, word [ClosestPointE2]  ;if these are equal, enemy should chase point in the buffer
        jne     .Midpoint2
        mov     ax, word [_LineBuffer+ClosetBufferE2*4]         ;ax has X coordinate of closest point
        mov     bx, word [_LineBuffer+ClosetBufferE2*4+2]         ;bx has Y coordinate of closest point
        jmp     .enemychase2
.Midpoint2:
                                                        ;must find midpoint of line for enemy to chase
        mov     ax, word [_LineBuffer+ClosetBufferE2*4]        ;x has x coordinate of  linebuffer
        mov     bx, word [_LineBuffer+ClosetBufferE2*4+4]      ;cx has next x coordinate of linebuffer
        cmp     ax, bx                      ;check if the X coordinates are different
        je      .ymid2
        add     ax, bx
        div     2
        ; where does this answer go,  do I have to move 0 into a register to make sure I don't use remainder
        mov     bx, word [_LineBuffer+ClosetBufferE2*4+2]
        jmp     .enemychase2
.ymid2:
        mov     ax, word [_LineBuffer+ClosetBufferE2*4+2]
        mov     bx, word [_LineBuffer+ClosetBufferE2*4+6]
        add     ax, bx
        div     2
        mov     bx, ax
        mov     ax, word [_LineBuffer+ClosetBufferE2*4]
.enemychase2:
        mov     word [chasePointX2], ax
        mov     word [chasePointY2], bx
        mov     cx, word [EnemyPoint.X2] ;ax has X coordinate to chase, bx has y coordinate to chase
        sub     ax, cx
        cmp     ax, 0
        jb      .nochangeedxgn2                                  ;if negative then player is to the left of enemy
        neg     ax
        inc     ax
.nochangeedxgn2:
        mov     dx, word [EnemyPoint.Y2]
        sub     bx, dx
        jb      .nochangeedxgn3
        neg     bx
        inc     bx
.nochangeedxgn3:                                          ;ax and bx have difference of x and y coordinates of enemy and closest point
        cmp     ax, bx
        jb      .movupdown2                               ; we need to move left or right now
        mov     ax, word [chasePointX2]
        mov     bx, word [EnemyPoint.X2]
        sub     ax, bx
        cmp     ax, 0
        jb      .chaseLeft2
                                         ;move right
        mov     eax, 00040000h                           ;2^18
        inc     word [EnemyPoint.X2]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .chaseEnemy3
        dec     word [EnemyPoint.X2]
        jmp     .chaseEnemy3
.chaseLeft2:
                                          ;move left
        mov     eax, 00040000h ;2^18   18th bit is colliedxon bit
        dec     word [EnemyPoint.X2]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no colliedxon
        je      .chaseEnemy3
        inc     word [EnemyPoint.X2]
        jmp     .chaseEnemy3

.movupdown2:
        
        mov     ax, word [chasePointY2]
        mov     bx, word [EnemyPoint.Y2]
        sub     ax, bx
        cmp     ax, 0
        jb      .chaseUp2
        mov     eax, 00040000h                  ;2^18 ;chaedxng down
        inc     word [EnemyPoint.Y2]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .chaseEnemy3
        dec     word [EnemyPoint.Y2]
        jmp     .chaseEnemy3
.chaseUp2:
        mov     eax, 00040000h                  ;2^18
        dec     word [EnemyPoint.Y2]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .chaseEnemy3
        inc     word [EnemyPoint.Y2]
        jmp     .chaseEnemy3

.chaseEnemy3:
        
        mov     ax, word [LineBuffer+ClosetBufferE3*4]          ;first find if closest point is a midpoint of point of turning
        mov     bx, word [EnemyPoint.X3]
        sub     ax, bx
        cmp     ax, 0
        jbe     .nonegate3                                 ;ax has (X - Xe)
        neg     ax
        inc     ax
.nonegate3:
        mov     bx, word [LineBuffer+ClosetBufferE3*4+2]
        mov     cx, word [EnemyPoint.Y3]
        sub     bx, cx                                   ;bx has (Y - Ye)
        cmp     bx, 0
        jbe     .compareClosest3
        neg     bx
        inc     bx
.compareClosest3:
        add     ax, cx
        cmp     ax, word [ClosestPointE3] ;if these are equal, enemy should chase point in the buffer
        jne     .Midpoint2
        mov     ax, word [LineBuffer+ClosetBufferE3*4]         ;ax has X coordinate of closest point
        mov     bx, word [LineBuffer+ClosetBufferE3*4+2]         ;bx has Y coordinate of closest point
        jmp     .enemychase3
.Midpoint3:
                 ;must find midpoint of line for enemy to chase
        mov     ax, word [LineBuffer+ClosetBufferE3*4]        ;x has x coordinate of  linebuffer
        mov     bx, word [LineBuffer+ClosetBufferE3*4+4]      ;cx has next x coordinate of linebuffer
        cmp     ax, bx                      ;check if the X coordinates are different
        je      .ymid3
        add     ax, bx
        div     2
        ; where does this answer go,  do I have to move 0 into a register to make sure I don't use remainder
        mov     bx, word [LineBuffer+ClosetBufferE3*4+2]
        jmp     .enemychase3
.ymid3:
        mov     ax, word [LineBuffer+ClosetBufferE3*4+2]
        mov     bx, word [LineBuffer+ClosetBufferE3*4+6]
        add     ax, bx
        div     2
        mov     bx, ax
        mov     ax, word [LineBuffer+ClosetBufferE3*4]
.enemychase3:
        mov     word [chasePointX3], ax
        mov     word [chasePointY3], bx
        mov     cx, word [EnemyPoint.X3]  ;ax has X coordinate to chase, bx has y coordinate to chase
        sub     ax, cx
        cmp     ax, 0
        jb      .nochangeedxgn4                                  ;if negative then player is to the left of enemy
        neg     ax
        inc     ax
.nochangeedxgn4:
        mov     dx, word [EnemyPoint.Y3]
        sub     bx, dx
        jb      .nochangeedxgn5
        neg     bx
        inc     bx
.nochangeedxgn5:                                          ;ax and bx have difference of x and y coordinates of enemy and closest point
        cmp     ax, bx
        jb      .movupdown3                               ; we need to move left or right now
        mov     ax, word [chasePointX3]
        mov     bx, word [EnemyPoint.X3]
        sub     ax, bx
        cmp     ax, 0
        jb      .chaseLeft3
                                         ;move right
        mov     eax, 00080000h           ;2^19
        inc     word [EnemyPoint.X3]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .endChase
        dec     [EnemyPoint.X3]
        jmp     .endChase
.chaseLeft3:
                                          ;move left
        mov     eax, 00080000h            ;2^19  19th bit is colliedxon bit
        dec     word [EnemyPoint.X3]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0                     ;eax is 0 if there was no colliedxon
        je      .endChase
        inc     word [EnemyPoint.X3]
        jmp     .endChase

.movupdown3:
        
        mov     ax, word [chasePointY3]
        mov     bx, word [EnemyPoint.Y3]
        sub     ax, bx
        cmp     ax, 0
        jb      .chaseUp3
        mov     eax, 00080000h                           ;2^19 ;chaedxng down
        inc     word [EnemyPoint.Y3]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .endChase
        cmp     eax
        dec     word [EnemyPoint.Y3]
        jmp     .endChase
.chaseUp3:
        mov     eax, 00080000h                          ;2^19
        dec     word [EnemyPoint.Y3]
        call    CheckEnemyColliedxon
        mov     ebx, dword [GameFlags]
        and     eax, ebx
        cmp     eax, 0
        je      .endChase
        inc     word [EnemyPoint.Y3]
        jmp     .endChase

.endChase:
        pop     dx
        pop     ebx
        pop     eax
        ;ret
endproc





;---------------------------------------------------------------------------
;Calculate_Territory
;Purpose - calculate total territory captured by player
;Input - territoryMap, player
;Output - territoryPlayer
;written by Jason Leake
;---------------------------------------------------------------------------
proc _Calculate_Territory
        push    eax
        push    ebx
        push    ecx
        push    edx

        mov     bx, word [LineBuffer]     ;see if x1 = x2
        mov     cx, word [LineBuffer + 4]
        cmp     bx, cx                   ;run the function if x1 != x2
        jne     .continue

        mov     bx, word [LineBuffer+2]     ;compare y1 and y2 if x1 = x2
        mov     cx, word [LineBuffer +6]
        je      .return                  ; end function if y1 = y2 else continue

.continue:

        movzx   ecx, [index]
        dec     ecx
.drawlinehlp:
        mov     eax, ecx
        mov     ax, word [LineBuffer + eax*4]
        sub     ax, word [LineBuffer + eax*4 -4]
        cmp     ax, 0
        je      .verticalhlp

;horizontal
        movzx ecx, word [LineBuffer + eax*4 +2]
        mov ebx, 0
.multiplyhlp:
        add ebx, 464
        loop .multiply

        mov dx, word [LineBuffer + eax*4]
        cmp dx, word [LineBuffer + eax*4 -4]
        jg .HorizontalFirstToSecondhlp

;HorizontalSecondToFirsthlp
        add ebx, word [LineBuffer + eax*4 -4]

        movzx ecx, word [LineBuffer + eax*4 -4]
        movzx edx, word [LineBuffer + eax*4]
        sub ecx, edx

        jmp .endofhorizontalhlp

.HorizontalFirstToSecondhlp:
        add ebx, word[LineBuffer + eax*4]

        movzx ecx, word [LineBuffer + eax*4]
        movzx edx, word [LineBuffer + eax*4 -4]
        sub ecx, edx

.endofhorizontalhlp:
        mov byte [territoryMap + ebx], 0
        dec ebx
        loop .endofhorizontalhlp
        jmp .endofloophlp

.verticalhlp:
        mov dx, word [LineBuffer + eax*4 +2]
        cmp dx, word [LineBuffer + eax*4 -2]
        jg .VerticalFirstToSecondhlp

;VerticalSecondToFirsthlp
        movzx ecx, word [LineBuffer + eax*4 -2]
        mov ebx, 0
.multiply2hlp:
        add ebx, 464
        loop .multiply2hlp
        add ebx, word [LineBuffer + eax*4]

        movzx ecx, word [LineBuffer + eax*4 -2]
        movzx edx, word [LineBuffer + eax*4 +2]
        sub ecx, edx

        jmp .endofverticalhlp

.VerticalFirstToSecondhlp
        movzx ecx, word [LineBuffer + eax*4 +2]
        mov ebx, 0
.multiply3hlp:
        add ebx, 464
        loop .multiply3hlp
        add ebx, word [LineBuffer + eax*4]

        movzx ecx, word [LineBuffer + eax*4 +2]
        movzx edx, word [LineBuffer + eax*4 -2]
        sub ecx, edx

.endofverticalhlp:
        mov byte [territoryMap + ebx], 0
        sub ebx, 464
        loop .endofverticalhlp

.endofloophlp:

        mov ecx, eax
        loop .drawlinehlp

;calculate the point in territory map that the player entered unclaimed territory
        mov ebx, 0
        movzx ecx, word [LineBuffer + 2]
        .multiply:
        add ebx, 464
        loop .multiply
        add ebx, [LineBuffer]
        push ebx

;see if the player enter the unclaimed territory traveling along a horizontal
; or a vertical line

        mov cx, word [LineBuffer]
        sub cx, word [LineBuffer + 4]
        cmp cx, 0
        jne .horizontal

;copy the territoryMap to the tempMap
        mov bx, 0
        mov ecx, 215296                       ;464*464
.copy:
        mov dx, byte [territoryMap + bx]
        mov byte [tempMap + bx], dx
        inc bx
        loop .copy

;find the area to the right of the line and mark that territory on tempMap
        pop ebx
        push ebx
        inc ebx

        mov dword [OrigESP], esp
        mov word [OrigSS], ss
        mov ax, ds
        mov ss, ax
        mov esp, LargeStack + 464*464
        mov edx, 0
        call _Area_Counter
        mov esp, dword [OrigESP]
        mov ss, word [OrigSS]

;find the area to the left of the line
        mov ecx, MAXAREA
        sub ecx, dword [AreaTaken]
        sub ecx, edx

;determine which area is smaller
        cmp ecx, edx
        jb .rightedxde

;copy the territoryMap to the tempMap
        mov bx, 0
        mov ecx, 215296                       ;464*464
.copy2:
        mov dx, byte [territoryMap + bx]
        mov byte [tempMap + bx], dx
        inc bx
        loop .copy2

;find the area to the left of the line and mark that territory on tempMap
        pop ebx
        dec ebx

        mov dword [OrigESP], esp
        mov word [OrigSS], ss
        mov ax, ds
        mov ss, ax
        mov esp, LargeStack + 464*464
        mov edx, 0
        call _Area_Counter
        mov esp, dword [OrigESP]
        mov ss, word [OrigSS]

        jmp .update_stats

.rightedxde:
        pop ebx
        jmp .update_stats

.horizontal:

        add ebx, 464
        push ebx

;copy the territoryMap to tempMap
        mov bx, 0
        mov ecx, 215296                      ;464*464
.copy3:
        mov dx, byte [territoryMap + bx]
        mov byte [tempMap + bx], dx
        inc bx
        loop .copy3

        pop ebx

;calculate the area above the line and mark that territory on tempMap
        mov dword [OrigESP], esp
        mov word [OrigSS], ss
        mov ax, ds
        mov ss, ax
        mov esp, LargeStack + 464*464
        mov edx, 0
        call _Area_Counter
        mov esp, dword [OrigESP]
        mov ss, word [OrigSS]

;calculate the area below the line
        mov ecx, MAXAREA
        sub ecx, dword [AreaTaken]
        sub ecx, edx
        cmp ecx, edx
        jb .topedxde

        pop ebx
        sub ebx, 464

        push ebx

;copy the territoryMap to tempMap
        mov bx, 0
        mov ecx, 215296                       ;464*464
.copy4:
        mov dx, byte [territoryMap + bx]
        mov byte [tempMap + bx], dx
        inc bx
        loop .copy4
        
        pop ebx

;calculate the area below the line and mark that territory on tempMap
        mov dword [OrigESP], esp
        mov word [OrigSS], ss
        mov ax, ds
        mov ss, ax
        mov esp, LargeStack + 464*464
        mov edx, 0
        call _Area_Counter
        mov esp, dword [OrigESP]
        mov ss, word [OrigSS]


        jmp .update_stats

.topedxde:

.update_stats:
        
;update AreaTaken
        add dword [AreaTaken], edx

;copy tempMap to territoryMap
        mov bx, 0
        mov ecx, 215296                    ;464*464
.claim:
        mov dx, byte [tempMap + bx]
        mov byte [territoryMap + bx], dx
        inc bx
        loop .claim

;update PercentTaken
        mov eax, dword [AreaTaken]
        mov edx, 0
        div MAXPERCENT
        mov byte[PercentTaken], al             ;AreaTaken/MAXPERCENT

.return:
        pop     edx
        pop     ecx
        pop     ebx
        pop     eax

endproc

;---------------------------------------------------------------------------
;Area Counter
;Purpose - calculate total territory captured by player
;Input - territoryMap, tempMap, ebx - contains point to start checking from
;        edx - must be 0
;Output - tempMap, edx - edxze of the area
;written by Jason Leake
;---------------------------------------------------------------------------
proc _Area_Counter
        
        push    ebx
        push    edx
;check if the pixel is neutral territory if not then return
        cmp byte [tempMap + ebx], 0
        je .return

;claim the pixel
        mov [tempMap + ebx], 0
        inc edx

;check the pixel to the right
        push ebx
        inc ebx
        call _Area_Counter
        pop ebx

;check the pixel below
        push ebx
        add ebx, 464
        call _Area_Counter
        pop ebx

;check the pixel to the left
        push ebx
        dec ebx
        call _Area_Counter
        pop ebx

;check the pixel above
        push ebx
        sub ebx, 464
        call _Area_Counter
        pop ebx

.return:
        pop     edx
        pop     ebx
endproc


;---------------------------------------------------------------------------
;Check_Enemy_Status
;Purpose - to determine status of enemies
;Input - territoryMap, EnemyPoint
;Output - GameFlags
;Written by Jason Leake
;---------------------------------------------------------------------------

proc _Check_Enemy_Status
        push    ebx
        push    ecx

;check if enemy1 died
        xor     ebx, ebx
        movzx   ecx,  word [EnemyPoint.Y1]
        sub     ecx, 8
.multiply:
        add     ebx, 464
        loop    .multiply
        movzx   ecx, word [EnemyPoint.X1]
        add     ebx, ecx
        sub     ebx, 8
        cmp     byte [territoryMap+ebx], 0
        je      .E1Live
        dec     byte [NumberofEnemies]
        or      dword [GameFlags], 00001000h
.E1Live

;check if enemy2 died
        xor     ebx, ebx
        movzx   ecx,  word [EnemyPoint.Y2]
        sub     ecx, 8
.multiply2:
        add     ebx, 464
        loop    .multiply2
        movzx   ecx, word [EnemyPoint.X2]
        add     ebx, ecx
        sub     ebx, 8
        cmp     byte [territoryMap+ebx], 0
        je      .E2Live
        dec     byte [NumberofEnemies]
        or      dword [GameFlags], 00002000h
.E2Live

;check if enemy3 died
        xor     ebx, ebx
        movzx   ecx,  word [EnemyPoint.Y3]
        sub     ecx, 8
.multiply3:
        add     ebx, 464
        loop    .multiply3
        movzx   ecx, word [EnemyPoint.X3]
        add     ebx, ecx
        sub     ebx, 8
        cmp     byte [territoryMap+ebx], 0
        je      .E3Live
        dec     byte [NumberofEnemies]
        or      dword [GameFlags], 00004000h
.E3Live
        pop     ecx
        pop     ebx

endproc

;---------------------------------------------------------------------------
;CheckEnemyColliedxon
;Purpose - check enemies colliedxon with the player? territory or his line
;Input - XPosE1, YPosE1, XPosE2, YPosE2, XPosE3, YPosE3, territoryMap
;Output - enemyColliedxonFlag1, 2, and 3 1 if player has a colliedxon and 0 otherwise
;Written by Stu Johnson
;modified by Sung Kim, Joseph Kim
;---------------------------------------------------------------------------
proc _CheckEnemyColliedxon
        push eax
        push ebx
        push dx
.Enemy1:
        mov     ax, word [EnemyPoint.Y1]
        YposE1
        mov     dx, 680
        mul     dx
        movzx   ebx, word [EnemyPoint.X1]
        add     eax, ebx                 ; eax holds poedxtion of enemy on Territory Map
        cmp     byte [territoryMap+eax], 0     ; territoryMap will be a 0 if it is player's territory
        jne     .endCheckEnemyColliedxon       ; enemy collided with territory
        or      dword [GameFlags], 00000000000000100000000000000000b
        xor edx, edx
.checkLineColliedxon1:
        mov     ax, word [LineBuffer+edx*4]      ; ax holds x pos of start of line
        mov     cx, word [LineBuffer+edx*4+4]       ; cx holds x pos of next line segment
        cmp     ax, cx
        je      .xSame1
        mov     dx, word [LineBuffer+edx*4+2]            ;Y poedxtion is same for both
        cmp     word [EnemyPoint.Y1], dx
        jne     .noColliedxon1                      ; No colliedxon if enemy does not have same ypos as line
        cmp     word [EnemyPoint.X1],ax
        jbe     .xBelow1
        cmp     word [EnemyPoint.X1], cx                         ;Xpos is above both values
        ja      .noColliedxon1
        dec     byte[Lives]                            ;sub     lives, 1
        call    DieInitialize                           ;player dies
        jmp     .endCheckEnemyColliedxon                  ; player must be initialized
.xBelow1:
        cmp     word [EnemyPoint.X1], cx                                       ; Xpos is below both ax and cx
        jb      .noColliedxon1
        dec     byte[Lives]                     ;sub     lives, 1   ;player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
.xSame1:
        mov     ax, word [LineBuffer+edx*4+2]
        mov     cx, word [LineBuffer+edx*4+6]
        mov     dx, word [LineBuffer+edx*4]           ;X poedxtion is same for both
        cmp     word [EnemyPoint.X1], dx
        jne     .noColliedxon1                      ; No colliedxon if enemy does not have same xpos as line
        cmp     word [EnemyPoint.Y1], ax
        jbe     .yBelow1
        cmp     word [EnemyPoint.Y1], cx                         ;ypos is above both values
        ja      .noColliedxon1
        dec     byte[Lives]                     ;sub     lives, 1  ;player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
.yBelow1:
        cmp     word [EnemyPoint.Y1], cx                                       ; ypos is below both ax and cx
        jb      .noColliedxon1
        dec     byte [Lives]                    ;sub     lives, 1   player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
  
.noColliedxon1:
        cmp     edx, 50
        je      .endCheckEnemyColliedxon
        inc     edx
        jmp     .checkLineColliedxon1

.Enemy2:
        mov     ax, word [EnemyPoint.Y2]
        mov     dx, 680
        mul     dx
        movzx   ebx, word [EnemyPoint.X2]
        add     eax, ebx                 ; eax holds poedxtion of enemy on Territory Map
        cmp     byte [territoryMap+eax], 0     ; territoryMap will be a 0 if it is player's territory
        jne     .endCheckEnemyColliedxon       ; enemy collided with territory
        or      dword [GameFlags], 00000000000001000000000000000000b
        xor edx, edx
.checkLineColliedxon2:
        mov     ax, [LineBuffer+edx*4]     ; ax holds x pos of start of line
        mov     cx, [LineBuffer+edx*4+4]       ; cx holds x pos of next line segment
        cmp     ax, cx
        je      .xSame2
        mov     dx, word [LineBuffer+edx*4+2]            ;Y poedxtion is same for both
        cmp     word [EnemyPoint.Y2], dx
        jne     .noColliedxon2                      ; No colliedxon if enemy does not have same ypos as line
        cmp     word [EnemyPoint.X2], ax
        jbe     .xBelow2
        cmp     word [EnemyPoint.X2], cx                         ;Xpos is above both values
        ja      .noColliedxon2
        dec     byte [Lives]                            ;sub     lives, 1
        call    DieInitialize                           ;player dies
        jmp     .endCheckEnemyColliedxon                  ; player must be initialized
.xBelow2:
        cmp     word [EnemyPoint.X2], cx                                       ; Xpos is below both ax and cx
        jb      .noColliedxon2
        dec     byte [Lives]                    ;sub     lives, 1  player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
.xSame2:
        mov     ax, word [LineBuffer+edx*4+2]
        mov     cx, word [LineBuffer+edx*4+6]
        mov     dx, word [LineBuffer+edx*4]            ;X poedxtion is same for both
        cmp     word [EnemyPoint.X2], dx
        jne     .noColliedxon2                      ; No colliedxon if enemy does not have same xpos as line
        cmp     word [EnemyPoint.Y2], ax
        jbe     .yBelow2
        cmp     word [EnemyPoint.Y2], cx                         ;ypos is above both values
        ja      .noColliedxon2
        dec     byte [Lives]                    ;sub     lives, 1   player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
.yBelow2:
        cmp     word [Enemy.Y2], cx                        ; ypos is below both ax and cx
        jb      .noColliedxon2
        dec     byte [Lives]                    ;sub     lives, 1   player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
  
.noColliedxon2:
        cmp     edx, 50
        je      .endCheckEnemyColliedxon
        inc     edx
        jmp     .checkLineColliedxon2

.Enemy3:
        mov     ax, word [EnemyPoint.Y3]
        mov     dx, 680
        mul     dx
        movzx   ebx, word [EnemyPoint.X3]
        add     eax, ebx                 ; eax holds poedxtion of enemy on Territory Map
        cmp     byte [territoryMap+eax], 0     ; territoryMap will be a 0 if it is player's territory
        jne     .endCheckEnemyColliedxon       ; enemy collided with territory
        or      GameFlags, 00000000000010000000000000000000b
        xor edx, edx
.checkLineColliedxon3:
        mov     ax, word [LineBuffer+edx*4]      ; ax holds x pos of start of line
        mov     cx, word [LineBuffer+edx*4+4]    ; cx holds x pos of next line segment
        cmp     ax, cx
        je      .xSame3
        mov     dx, word [LineBuffer+edx*4+2]     ;Y poedxtion is same for both
        cmp     word [EnemyPoint.Y3], dx
        jne     .noColliedxon3                      ; No colliedxon if enemy does not have same ypos as line
        cmp     word [EnemyPoint.X3], ax
        jbe     .xBelow3
        cmp     word [EnemyPoint.X3], cx          ;Xpos is above both values
        ja      .noColliedxon3
        dec     byte [Lives]                        ;sub     lives, 1
        call    DieInitialize                           ;player dies
        jmp     .endCheckEnemyColliedxon           ; player must be initialized
.xBelow3:
        cmp     word [EnemyPoint.X3], cx                                       ; Xpos is below both ax and cx
        jb      .noColliedxon1
        dec     byte [Lives]                    ;sub     lives, 1  player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
.xSame3:
        mov     ax, word [LineBuffer+edx*4+2]
        mov     cx, word [LineBuffer+edx*4+6]
        mov     dx, word [LineBuffer+edx*4]     ;X poedxtion is same for both
        cmp     word [EnemyPoint.X3], dx
        jne     .noColliedxon3                      ; No colliedxon if enemy does not have same xpos as line
        cmp     word [EnemyPoint.Y3], ax
        jbe     .yBelow3
        cmp     word [EnemyPoint.Y3], cx                         ;ypos is above both values
        ja      .noColliedxon3
        dec     word [Lives]                    ;sub     lives, 1  player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
.yBelow3:
        cmp     word [EnemyPoint.Y3], cx                                       ; ypos is below both ax and cx
        jb      .noColliedxon3
        dec     byte [Lives]                    ;sub     lives, 1   player dies
        call    DieInitialize                           ;player must be initialized
        jmp     .endCheckEnemyColliedxon
  
.noColliedxon3:
        cmp     edx, 50
        je      .endCheckEnemyColliedxon
        inc     edx
        jmp     .checkLineColliedxon3
.endCheckEnemyColliedxon:
pop dx
pop ebx
pop eax
endproc


;---------------------------------------------------------------------------
;IntPlayer
;Purpose - initilize all variables and players
;Input - None
;Output - A whole ton
;written by Stu Johnson
;---------------------------------------------------------------------------
_IntPlayer
        mov     dword [GameFlags], 000000000000000000000100000000000b
        mov     byte [Lives], 3
        mov     byte [Level], 1
        mov     dword [Score], 0
        mov     byte [FinishPercent], 75
        mov     byte[PercentTaken], 0
        mov     dword [TimeLimit], 180
        mov     dword [TimeLeft], 180

        call    LevelInitialize    ; is this procedure or subroutine
        ret



;---------------------------------------------------------------------------
;All_Done
;Purpose - to determine when game is over (This function will be also
;       called from Keyboard Handler whenever ESCKEY is pressed.  As it calls
;       this function, Handler will set up the Lives equal to zero.)
;Input - lives
;Output - Set mainExitFlag
;written by Sung Kim
;---------------------------------------------------------------------------
_AllDone
        push    eax
        mov     al, byte [Lives]
        cmp     al, 0
        jne     .endAllDone
        or      dword [GameFlags], 00000000000000000000000000000001b
        ; this flag will be checked in the main function
.endAllDone:
        pop     eax
        ret




;---------------------------------------------------------------------------
;LevelInitialize
;Purpose - to initialize poedxtion of player and enemies on a new level
;Input - level, territoryMap
;Output - - XPos, YPos, XPosE1, YPosE1, XPosE2, YPosE2, XPosE3, YPosE3
;Written by Sung Kim
;---------------------------------------------------------------------------
_LevelInitialize
        push    eax
        mov     word [XPos], 0                           ; initalize x and y coordinates of player
        mov     word [YPos], 100
        mov     eax, dword [_EnemyPoint]
        xor     ebx, ebx
        mov     word [_EnemyPoint.X1], 45                        ;initialize x and y coordinates of enemies
        mov     word [_EnemyPoint.Y1], 425
        inc     ebx
        mov     word [_EnemyPoint.X2], 575
        mov     word [_EnemyPoint.Y2], 425
        inc     ebx
        mov     word [_EnemyPoint.X3], 575
        mov     word [_EnemyPoint.Y3], 150
        
        inc     byte [Level]                       ;increment the level
        pop     eax
        ret


;---------------------------------------------------------------------------
;Die_Initialize
;Purpose - to initialize coordinates of player after dying
;Input - territoryMap
;Output - XPos, YPos
;written by Sung Kim
;---------------------------------------------------------------------------
_DieInitialize
        mov     word [XPos], 0
        mov     word [YPos], 100
        ret



;--------------------------------------------------------------
;--                        ClearImage()                      --
;-- Input:  Current color
;-- Output:  None
;-- Purpose: Clear the "paint" area (_ImageBlock) to a solid color
;-- Notes:  The area you want to clear is 640 by 450 pixels
;-- Use a string operation to make this short and easy and worth full points
;--------------------------------------------------------------
proc _ClearImage
%$Color		arg	4

;	invoke	libClearImage, dword [ebp+%$Color]
        push	eax
	push	ecx
	push	edi
	push	es

	mov	ax, [_ImageBlock]
	mov	es, ax
	xor	edi, edi
	mov     ecx, 288000      ; 640*450
	mov	eax, [ebp + %$Color]
	cld
	rep     stosd		
	
	pop	es
	pop	edi
	pop	ecx
	pop	eax
endproc

;--------------------------------------------------------------
;--                        DrawChar()                        --
;Input: DestSel, destination selector to write character into
;       Dest, offset into DestSel
;       Char, ASCII character to write
;       CharPos, poedxtion to write character at: specified in character units, not pixels
;       Color, color to make text
;Output: Correct character written to correct location in DestSel
;Purpose: Writes a edxngle character. Used in both dialogs (typing in filenames)
;       and with the Text tool to write strings to the screen.
;Notes: Each character is 16x16.
;       Overwrite the color value of each pixel written with the Color argument,
;        but leave the alpha value intact: as the characters are antialiased,
;        when they are copied to the screen uedxng AlphaBlit, they will be correctly
;        blended onto the background.
;       MMX highly recommended, but not required. Use this function to familiarize
;        yourself with the MMX instructions and how to use them to modify 32-bit pixels
;        before diving into AlphaBlit.
;       The width of the destination bitmap is always 640 (pixels). You need to adjust
;        the destination pointer after every row so that the character is aligned
;        properly on the destination.
;       See Drawing Strings of Text for further information.
;--------------------------------------------------------------
proc _DrawChar
%$DestSel	arg	2
%$Dest		arg	4
%$Char		arg	2
%$CharNum	arg	4
%$Color		arg	4
_DrawChar_arglen equ 16

;	invoke	libDrawChar, word [ebp+%$DestSel], dword [ebp+%$Dest], word [ebp+%$Char], dword [ebp+%$CharNum], dword [ebp+%$Color]
	push	ds
	push	es
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	edi
	push	edx

	mov	ax, [_FontBlock]
	mov	es, ax			; es = [_FontBlock]
	mov	ax, [ebp + %$DestSel]
	mov	ds, ax			; ds = [ebp + %$DestSel]
	mov	edi, dword [ebp + %$Dest]
	mov	edx, dword [ebp + %$Color]
	movzx	edx, byte [ebp + %$Char]
	shl	edx, 6

	mov	ebx, 16			; word edxze
.PosY
	push	ebx
	mov	ebx, [ebp+%$CharNum]	; Get character
	shl	ebx, 4			; 4 bytes per character
	dec	ebx			; increased immediately in StringPosX
	xor	ecx, ecx
.PosX
	mov	eax, dword [es:edx + ecx*4]	; copy character pixel
	or	eax, edx		; adjust color
	inc	ebx			; copy dword by dword
	mov	dword [edi + ebx*4], eax	; copy character and color to buffer
	inc	ecx
	cmp	ecx, 16
	jne	.PosX

	add	edx, 8192	; 128*16*4
	add	edi, 2560	; 640*4
	pop	ebx
	dec	ebx
	jnz	.PosY

	pop edx
	pop	edi
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	pop	es
	pop	ds
endproc

;--------------------------------------------------------------
;--                        AlphaBlit()                       --
;Input: DestSel, selector containing destination image to blit onto
;       Dest, offset of start of image within DestSel
;       DestWidth, width of destination image in pixels
;       DestX, X coordinate of the upper-left corner of where the source image should be placed on the destination
;       DestY, Y coordinate of the upper-left corner of where the source image should be placed on the destination
;       SrcSel, selector containing source image to blit from
;       Src, offset of start of image within SrcSel
;       SrcWidth, width of source image in pixels
;       SrcHeight, height of source image in pixels
;Output: Source alpha-blended onto destination
;Purpose: Copy a source image over a destination image taking into account the alpha
;          value of each pixel in the source (the destination alpha values are ignored).
;Notes: DestWidth and SrcWidth will always be multiples of 2.
;       Provides the setup and loop for AlphaCompose()
;       You must correctly handle the source image going off the right of
;        the destination (don't worry about it going off the bottom).
;       You should load RoundingFactor into an MMX register in the setup here.
;       It will be used by AlphaCompose, but AlphaCompose doesn't know what
;        the real data segment (where RoundingFactor is stored) is, so it can't load it.
;        If you use the library AlphaCompose, load RoundingFactor into
;        mm4 and zero mm5 (pxor mm5, mm5) in AlphaBlit, before starting the loop
;        that calls AlphaCompose().
;       See Alpha Blitting for further information.
;--------------------------------------------------------------
proc _AlphaBlit
%$DestSel	arg	2
%$Dest		arg	4
%$DestWidth	arg	4
%$DestX		arg	2
%$DestY		arg	2
%$SrcSel	arg	2
%$Src		arg	4
%$SrcWidth	arg	4
%$SrcHeight	arg	4

;	invoke	libAlphaBlit, word [ebp+%$DestSel], dword [ebp+%$Dest], dword [ebp+%$DestWidth], word [ebp+%$DestX], word [ebp+%$DestY], word [ebp+%$SrcSel], dword [ebp+%$Src], dword [ebp+%$SrcWidth], dword [ebp+%$SrcHeight]
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	edi
	push edx

	mov	edx, dword [ebp + %$Src]	; set source address

	;set destination location
	movzx	edi, word [ebp + %$DestY]	
	imul	edi, dword [ebp + %$DestWidth]	; proper Y-coordinate in memory
	movzx	eax, word [ebp + %$DestX]
	add	edi, eax			; add DestX to get start of destination
	shl	edi, 2				; 32-bits, therefore multiply by 4
	add	edi, dword [ebp + %$Dest]	; add offset within DestSel to find start poiedxtion of picture
	movzx	ecx, word [ebp + %$DestX]	

	xor	ebx, ebx			; source row increment initialized

	; Set Source location
	add	ecx, dword [ebp + %$SrcWidth]		
	cmp	ecx, dword [ebp + %$DestWidth]	
	ja	.above	; SrcWidth > DestWidth

	mov	ecx, dword [ebp + %$SrcWidth]	
	jmp	.otherwise

.above		; source row increment changes, edx is modified
	mov	ecx, dword [ebp + %$DestWidth]	
	movzx	ebx, word [ebp + %$DestX]
	sub	ecx, ebx			; edx becomes modified destination width
	mov	ebx, dword [ebp + %$SrcWidth]
	sub	ebx, ecx
	shl	ebx, 2				; Source Row Increment = (source width - destination width) * 4

.otherwise			; Destination Row increment set
	mov	eax, dword [ebp + %$DestWidth]	
	sub	eax, ecx			; Destination width - (un)modified destination width
	shl	eax, 2				; Destination Row Increment = destination width * 4

	shr	ecx, 1				; copies per row = width(pixels) / 2
	mov	edx, dword [ebp + %$SrcHeight]	; rows to copy
	movq	mm4, [_RoundingFactor]		; If you use the library AlphaCompose, load RoundingFactor into mm4
	pxor	mm5, mm5			; and zero mm5 (pxor mm5, mm5) in AlphaBlit, before starting the loop that calls AlphaCompose()
	push	es				; setup for _AlphaCompose call
	mov	es, word [ebp + %$DestSel]
	push	ds
	mov	ds, word [ebp + %$SrcSel]
	push	ecx

.Loop
        call	_AlphaCompose
        add	edx, 8			; _AlphaCompose works on 8 bytes at a time
	add	edi, 8
	Loopnz	.Loop		; complete one line
	pop	ecx
	push	ecx
	add	edx, ebx
	add	edi, eax
	dec	edx				; do edx lines
	jnz	.Loop      

	pop	ecx
	pop	ds
	pop	es
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	pop edx
	pop	edi

	; restore stacks
	mov	esp, ebp
	pop	ebp
	emms
	ret
endproc

;--------------------------------------------------------------
;--                        AlphaCompose()                    --
;Input: ds:edx points to the source image double-pixel
;       es:edi points to the destination image double-pixel
;Output: Alpha Composed Source over Destination in Destination double-pixel
;Purpose: Perform the Over operation as a helper function to AlphaBlit()
;Notes: Use MMX for full points and speed
;       The Over operator is Dest = (alpha * Source) + ((1-alpha) * Dest)
;       See Alpha Blitting for further information and optimizations.
;--------------------------------------------------------------
_AlphaCompose

;	call	libAlphaCompose
	movq mm0, qword [ds:edx]
	movq mm1, qword [es:edi]

        movq mm2, mm0
	movq mm3, mm1

	punpckhbw mm2, mm5
	punpckhbw mm3, mm5
	movq mm6, mm2
	punpckhwd mm6, mm6
	punpckhwd mm6, mm6
	psubw mm2, mm3
	pmullw mm2, mm6
	psllw   mm3, 8                   ;shift left to align addition 
        paddw   mm3, mm2 
        paddw   mm3, mm4                 ;add rounding factor to destination for proper diviedxon
        psrlw   mm3, 8                   ;shift to divide by 256 to fit into one byte per channel

        punpcklbw       mm0, mm5        ;do again for second source and destination pixels 
        punpcklbw       mm1, mm5 
        movq            mm6, mm0 
        punpckhwd       mm6, mm6 
        punpckhdq       mm6, mm6 

        psubw   mm0, mm1 
        pmullw  mm0, mm6 
        psllw   mm1, 8 
        paddw   mm1, mm0 
        paddw   mm1, mm4 
        psrlw   mm1, 8 


        packuswb        mm1, mm3        ;pack words back into bytes 
        movq    [es:edi], qword mm1     ;write back into destination video memory 


        emms 	

	ret

;--------------------------------------------------------------
;--                        AALine()                          --
;Input: (x0,y0), starting coordinate of anti-aliased line
;       (x1,y1), ending coordinate of anti-aliased line
;       Color, color to draw line with
;Output: Anti-aliased line drawn in the current color
;Purpose: Draws an anti-aliased line in the current color by calling DrawPixelD()
;Notes: This function calls DrawPixelD in an irregular way!
;       Make sure to leave ES as passed, when you call DrawPixelD
;       See Anti-aliased Lines for further information and optimizations
;--------------------------------------------------------------
proc _AALine
%$x1	arg 2
%$y1	arg 2
%$x2	arg 2
%$y2	arg 2
%$color	arg 4

; These are local variables.. access them as [ebp+.varname]
; You need to uncomment the sub esp and mov esp lines to use these.
; Notice the last equ is the poedxtive veredxon of the last variable offset.

.du		equ	-4	;4 bytes
.dv		equ	-8	;4
.d		equ	-12	;4
.incrS		equ	-16	;4
.incrD		equ	-20	;4
.twovdu		equ	-24	;4
.u		equ	-28	;4
.v		equ	-32	;4
.invD		equ	-40	;8
.invD2du	equ	-48	;8
.uincr		equ	-52	;4
.vincr		equ	-56	;4
.uend		equ	-60	;4
.addr		equ	-64	;4
.vmax		equ	-68	;4
.temp		equ	-76	;8

;	invoke	libAALine, word [ebp+%$x1], word [ebp+%$y1], word [ebp+%$x2], word [ebp+%$y2], dword [ebp+%$color]

;	mov	esp, ebp
.StackFramedxze	equ	76
	sub	esp, .StackFramedxze

	push	eax
	push	ebx
	push	ecx
	push	edx
	push	edi
	push edx

;  int addr = (y1*640+x1)*4
	movzx	eax, word [ebp + %$y1]
	mov	ebx, 640
	imul	ebx			; eax = y1 * 640
	movzx	ebx, word [ebp + %$x1]
	add	eax, ebx
	shl	eax, 2
	mov	dword [ebp + .addr], eax
		
; int dx = x2-x1
	movzx	eax, word [ebp + %$x2]
	movzx	ebx, word [ebp + %$x1]
	sub	eax, ebx		; eax = dx
	mov	edi, eax
	cmp	edi, 0
	jge	.dy
	neg	edi			; edi = abs(dx)

.dy
;  int dy = y2-y1
	movzx	ebx, word [ebp + %$y2]
	movzx	edx, word [ebp + %$y1]	
	sub	ebx, edx		; ebx = dy
	mov	edx, ebx
	cmp	edx, 0
	jge	.Compare
	neg	edx			; edx = abs(dy)

.Compare
	cmp	edi, edx
        jle     near .DoElse

; if (abs(dx) > abs(dy))
	mov	dword [ebp + .du], edi	; int du = abs(dx);
	mov	dword [ebp + .dv], edx	; int dv = abs(dy);

	movzx	edx, word [ebp + %$x2]
	mov	dword [ebp + .u], edx	; int u = x2
	movzx	edx, word [ebp + %$y2]
	mov	dword [ebp + .v], edx	; int v = y2
	mov	dword [ebp + .uincr], 4	; int uincr = 4
	mov	dword [ebp + .vincr], 2560	; int vincr = 640*4
	cmp	eax, 0
	jge	.CheckVIncr1
	mov	dword [ebp + .uincr], -4	; if (dx < 0) uincr = -uincr
.CheckVIncr1
	cmp	ebx, 0
        jge     near .Continue
	mov	dword [ebp + .vincr], -2560	; if (dy < 0) vincr = -vincr
	jmp	.Continue

.DoElse
; if (abs(dx) <= abs(dy))
	mov	dword [ebp + .du], edx		; int du = abs(dy);
	mov	dword [ebp + .dv], edi		; int dv = abs(dx);
	movzx	edx, word [ebp + %$y2]
	mov	dword [ebp + .u], edx		; int u = y2
	movzx	edx, word [ebp + %$x2]
	mov	dword [ebp + .v], edx		; int v = x2
	mov	dword [ebp + .uincr], 2560	; int uincr = 640*4
	mov	dword [ebp + .vincr], 4		; int vincr = 4
	cmp	ebx, 0
	jge	.CheckVIncr2
	mov	dword [ebp + .uincr], -2560	; if (dx < 0) uincr = -uincr
.CheckVIncr2
	cmp	eax, 0
	jge	near .Continue
	mov	dword [ebp + .vincr], -4	; if (dy < 0) vincr = -vincr
	jmp	.Continue

.Continue
	mov	ebx, dword [ebp + .du]
	mov	edx, dword [ebp + .dv]		; saves repetitious memory accesses
; int uend = u + 2 * du
	mov	eax, ebx
	shl	eax, 1
	add	eax, dword [ebp + .u]
	mov	dword [ebp + .uend], eax

; int incrS = 2 * dv;	/* ?d for straight increments */
	mov	eax, edx
	shl	eax, 1
	mov	dword [ebp + .incrS], eax

; int d = (2 * dv) - du;	    /* Initial value as in Bresenham's */
	sub	eax, dword [ebp + .du]
	mov	dword [ebp + .d], eax

; int incrD = 2 * (dv - du);	/* ?d for diagonal increments */
	sub	eax, ebx
	mov	dword [ebp + .incrD], eax

; int twovdu = 0;	/* Numerator of distance; starts at 0 */
	mov	dword [ebp + .twovdu], 0

	finit
; double invD = 1.0 / (2.0*sqrt(du*du + dv*dv));   /* Precomputed inverse denominator */
	fild	dword [ebp + .dv]
	fild	dword [ebp + .dv]
	fmulp	st1	; dv*dv
	fild	dword [ebp + .du]
	fild	dword [ebp + .du]
	fmulp	st1	; du*du
	faddp	st1	; du*du + dv*dv
	fsqrt			; sqrt(du*du + dv*dv)
	fld1			; load 1 onto stack
	fld1
	faddp	st1
	fmulp	st1	; 2*sqrt(du*du + dv*dv)
	fld1
	fdivrp	st1
	fstp	qword [ebp + .invD]

; double invD2du = 2.0 * (du*invD);   /* Precomputed constant */
	finit
	fild	dword [ebp + .du]
	fmulp	st1
	fld1
	fld1
	fmulp	st1
	fstp	qword [ebp + .invD2du]

.DrawLine
; DrawPixelD(addr, twovdu*invD)
	finit
	fld	qword [ebp + .invD]
	fild	dword [ebp + .twovdu]
	fmulp	st1
	fabs					; must have poedxtive distance
	invoke	_DrawPixelD, dword [ebp + .addr], dword [ebp + %$color]

	xor	edx, edx
	mov	eax, dword [ebp + .addr]
	mov	ebx, 2560
	div	ebx
	cmp	ebx, 4
        je      near .DontDraw2
	cmp	ebx, 2556
        je      near .DontDraw2		; don't draw around the screen

; DrawPixelD(addr + vincr, invD2du - twovdu*invD)

	finit
	fld	qword [ebp + .invD]
	fild	dword [ebp + .twovdu]
	fmulp	st1
	fld	qword [ebp + .invD2du]
	fsubrp	st1
	fabs					; must have poedxtive distance
	mov	eax, [ebp + .addr]
	add	eax, [ebp + .vincr]
	cmp	eax, 0
	jl    near   .DontDraw1
	invoke	_DrawPixelD, eax, dword [ebp + %$color]


.DontDraw1
; DrawPixelD(addr - vincr, invD2du + twovdu*invD)

	finit
	fld	qword [ebp + .invD]
	fild	dword [ebp + .twovdu]
	fmulp	st1
	fld	qword [ebp + .invD2du]
	faddp	st1
	fabs					; must have poedxtive distance
	mov	eax, dword [ebp + .addr]
	sub	eax, dword [ebp + .vincr]
	cmp	eax, 0
	jl	near .DontDraw2
	invoke	_DrawPixelD, eax, dword [ebp + %$color]

.DontDraw2
	mov	eax, dword [ebp + .du]
	mov	ebx, dword [ebp + .d]
	cmp	dword [ebp + .d], 0
	jge    near  .DoElse2

; if (d < 0)
	; twovdu = d + du
	add	eax, ebx
	mov	dword [ebp + .twovdu], eax

	; d = d + incrS
	mov	eax, dword [ebp + .incrS]
	add	dword [ebp + .d], eax
	jmp	.Continue2
.DoElse2
; if (d >= 0)
	; twovdu = d - du
	sub	ebx, eax
	mov	dword [ebp + .twovdu], ebx

	; d = d + incrD
	mov	eax, dword [ebp + .incrD]
	add	dword [ebp + .d], eax
	
	; v = v + 1;
	inc	dword [ebp + .v]

	; addr = addr + vincr
	mov	eax, dword [ebp + .vincr]
	add	dword [ebp + .addr], eax

.Continue2
	; u = u+2
	inc	dword [ebp + .u]
	inc	dword [ebp + .u]

	; addr = addr+uincr
	mov	eax, dword [ebp + .uincr]
	add	dword [ebp + .addr], eax

	;  while (u < uend)
	mov	eax, dword [ebp + .u]
	cmp	eax, dword [ebp + .uend]
	jl	near .DrawLine		
pop edx
pop	edi
pop	edx
pop	ecx
pop	ebx
pop	eax
mov	esp, ebp
.end
endproc

;--------------------------------------------------------------
;--                        DrawPixelD()                      --
;Input: addr holds the pixel address
;       Color holds the base color to draw the pixel with
;       st0 holds the calculated distance
;Output: Compoedxted pixel for Anti-aliased line
;Purpose: Perform the one pixel Alpha Compoedxting with Alpha as a function of distance
;Notes: Don't use MMX in this function!
;       ES holds the selector to which you should draw. ([ES:addr])
;       This function is called irregularly! Nowhere else will you see a value passed on the FPU stack.
;       Use the Over operator, as above.
;--------------------------------------------------------------
_DrawPixelD_arglen equ 8
proc _DrawPixelD
%$addr	arg 4
%$color	arg 4

;	invoke	libDrawPixelD, dword [ebp+%$addr], dword [ebp+%$color]
       mov     ebp,esp
       push    edx
       mov     dword[ebp-12],255 
       mov     ebx,dword [ebp +%$addr] 
       cmp     ebx,12C000h 
       ja      near .Getdown
       mov     ecx,[es:ebx] 
       fld     ST0             	; dupblicate value of.distance. to stack 
       fld     qword [_MapTo1] 	; push Mapto1 on stack  that is 3/2 
       fdivp   ST1,ST0         	; fdiv    st(1), st(0)    ;st(1) := st(1)/st(0) 
       fabs                    	; round 
       fld1                    	; push 1 on stack 
       fsubrp  ST1             	; 1- disstance*2/3 
       fmul    to ST0          	; get square 
       fild    dword[ebp-12]   	; Multiply with 255 
       fmulp   ST1 
       frndint 
       fistp   dword[ebp-12] 	; get from stack value a 
       cmp     dword[ebp-12],0 	; if less than 0? 
       jnl     .Jumpjump 
       mov     dword[ebp-12],0 	; now we have a= 255 * (1 - (distance * 2/3))^2 
                               	; or a =0 
.Jumpjump
       xor     edx,edx
.Jumpup
       movzx   ax,[ebp+%$color+edx]
       movzx   dx,cl 
       sub     ax,dx 
       imul    word[ebp-12] 
       add     cl,ah 
       ror     ecx,8 
       inc     edx
       cmp     edx,4
       jc      .Jumpup 
       mov     [es:ebx],ecx 
.Getdown
      pop      edx


endproc






