;----------------------------------------------------------------------
;// PROGRAM DESCIRPTION
;// -=================-
; This is an interactive battleship game. The user must place their
; ships on the left hand part of the screen, then guess where the
; computer has placed it's ships by shooting at the right hand of the
; screen's grid. The game is played with one user against the computer.
; The game ends when either the computer ships or the users ships have
; all been sunk.
;----------------------------------------------------------------------
;// HIGH-LEVEL ALGORITHIM
;// -===================-
; seed random number generator
; load in all sprite data
; change video mode to 320x200 256color mode (mode 13h)
; display the title screen to the user
; wait for the user to hit a key
; clear the screen
; display the background for the game
; enable the mouse
; limit the mouse to ship placement grid
; GET THE USER TO ADD SHIPS
; update display
; if all ships have been placed
; end loop
; check if user has hit mouse button
; check which ship is being positioned
; if user pressed right mouse button add 1 to ship value
; if coordinate is invalid
; goto GET_THE USER TO ADD SHIPS
; put the ship at the selected coordinates
; loop
; GET THE COMP TO ADD SHIPS
; if all ships placed
; end loop
; check which ship to place
; get a random number between 0 and 1 to determine if the ship
; will be vertical or horizontal
; get a random x and y coordinate between 0 and 9
; if x and y are not valid
; goto GET THE COMP TO ADD SHIPS
; place the ship on to the computer grid at x y
; loop
; GAME LOOP
; draw screen
; if user wins
; show picture win.pcx
; if computer wins
; show picture lose.pcx
; wait for a mouse button
; get the x and y of where the mouse is pointing
; convert the x and y screen pos to x and y cell
; read the x and y data from the computer and user grid
; if cell(x,y) was hit before
; goto GAME LOOP
; if computer cell(x,y) = ship
; put explostion
; increment the user hit total
; else
; put miss
; MAKE COMPUTER SHOOT
; get a random x and y between 0 and 9
; read the x and y data from the computer and user grid
; if cell(x,y) was hit before
; goto MAKE COMPUTER SHOOT
; if user cell(x,y) = ship
; put explostion
; increment the computer hit total
; else
; put miss
; loop
;
; Ask if the user wants to play again
; if y
; clear the grids
; goto GET THE USER TO ADD SHIPS
; else end the program
;
;----------------------------------------------------------------------
;// PROGRAM STATUS
;// -============-
;// * Ship Placement *
;// Ships can be placed verticaly and horizontaly by the user and the
;// computer with no problem at all.
;// Collision detection works perfect
;// Bounds checking works fine
;// UNUSUAL: Computer tends to add vertical ships VERY often but not
;// all the time.
;// * Computer and User Shooting *
;// Computer and user only shoot where they havent shot before
;// Impossible to shoot out of bounds
;// Ships are hit propper
;// All necessary updating is done when a ship is hit
;// * End of Game *
;// User can press ESC to quit game any time except when placing ships
;// Actually, user can press any key to quit
;// User can choose not to play another game - works perfect
;// User can choose to play another game - works perfect
;// * Pictures *
;// All pictures display propper
;// Pictures could be of better quality
;// Images are put way too slow, however the lag does not interfere
;// with the running of the program
;// Special Thanks to Adrian for pointing out that DOS can be real
;// stupid and not accept file names longer than 8 characters
;----------------------------------------------------------------------
;// REGISTER TABLE
;// -============-
;// AX - Call DOS IO and VIDEO functions
;// AL - Stores the result of a user input
;// BH - Select page 0 for border color call
;// BL - Select color for border
;// DX - Used to pass the X and Y coordinates for move cursor
;----------------------------------------------------------------------
%TITLE ""
IDEAL
MODEL small
STACK 256
;--------------------------------------------------------
; equate section
;--------------------------------------------------------
DOS_READ EQU 1
DOS_WRITE EQU 2
DOS_EXIT EQU 4Ch
DOScall EQU 21h
CR EQU 0Dh
LF EQU 0Ah
TRUE EQU 1
FALSE EQU 0
CHANGE_VIDEO EQU 0000h
DOS_VIDEO EQU 10h
TEXT_MODE EQU 0003h
GRAPH_MODE EQU 0013h
MOUSE_BUTTON_LEFT EQU 0001h
MOUSE_BUTTON_RIGHT EQU 0002h
MOUSE_POS_BUTTON EQU 0003h
DOS_MOUSE EQU 33h
DOS_VIDEO EQU 10h
GRID_SIZE EQU 100
WATER_ EQU 1
;--------------------------------------------------------
; Macro Section
;--------------------------------------------------------
MACRO Array_2d Array_name, LBR, UBR, LBC, UBC, Size, Init
dw LBR
dw UBR
dw LBC
dw UBC
dw Size
Array_name dw ( (UBR - LBR + 1)*(UBC - LBC + 1) * Size) DUP (Init)
endm Array_2d
MACRO sprite s_name, s_wide, s_high
dw s_wide
dw s_high
s_name db ( s_wide * s_high) DUP (3) ;Blue filler
endm sprite
MACRO PushReg registers
IRP reg, <registers>
push reg
ENDM
ENDM PushReg
MACRO PopReg registers
IRP reg, <registers>
pop reg
ENDM
ENDM PopReg
DATASEG
; User Grid containing users ships and where has been hit on grid
; There are 2 spaces in each cell
; 1) If a ship is in the cell
; 2) If the cell has been hit
; The initialization is all cells set to (0,0)
Array_2d U_Grid, 0, 9, 'a', 'j', 2, 1
; Computer Grid
Array_2d C_Grid, 0, 9, 'a', 'j', 2, 1
;// Create the sprites
sprite ptboat_h , 28, 14
sprite ptboat_v , 14, 28
sprite cruiser_h, 42, 14
sprite cruiser_v, 14, 42
sprite bship_h , 56, 14
sprite bship_v , 14, 56
sprite ac_h , 70, 14
sprite ac_v , 14, 70
sprite water , 14, 14
sprite hit1 , 14, 14
sprite miss , 14, 14
fourteen db 14
fire db "fire.pcx",0
water_pcx db "water.pcx",0
background db "background.pcx",0
hit1_pcx db "hit.pcx",0
miss_pcx db "miss.pcx",0
;// BOATS
ptboat_h_pcx db "ptboat_h.pcx",0
ptboat_v_pcx db "ptboat_v.pcx",0
cruiser_h_pcx db "c_h.pcx",0
cruiser_v_pcx db "c_v.pcx",0
bship_h_pcx db "bship_h.pcx",0
bship_v_pcx db "bship_v.pcx",0
ac_h_pcx db "ac_h.pcx",0
ac_v_pcx db "ac_v.pcx",0
win_pcx db "win.pcx",0
lose_pcx db "lose.pcx",0
help_pcx db "help.pcx",0
c_ship_data dw ?
c_hit_data dw ?
u_ship_data dw ?
u_hit_data dw ?
comp_hits dw 0
user_hits dw 0
curr_ship dw 0
curr_turn dw 0
button dw 0
play_again db "Do you want to play another game? ", '$'
grid_pos dw 0
; ------------------------------------------------------------------------
; MAIN
; ------------------------------------------------------------------------
CODESEG
start:
mov ax,@data
mov ds,ax
mov es,ax
;// Seed the random number Generator
call _seed_ran
; Initialize the sprites
; ----- WATER ----------
push offset water_pcx
push offset water
call load_sprite
add sp, 4
; ---- PATROL BOAT -----
push offset ptboat_h_pcx
push offset ptboat_h
call load_sprite
add sp, 4
push offset ptboat_v_pcx
push offset ptboat_v
call load_sprite
add sp, 4
; ---- CRUISER -----
push offset cruiser_h_pcx
push offset cruiser_h
call load_sprite
add sp, 4
push offset cruiser_v_pcx
push offset cruiser_v
call load_sprite
add sp, 4
; ---- BATTLE SHIP -----
push offset bship_h_pcx
push offset bship_h
call load_sprite
add sp, 4
push offset bship_v_pcx
push offset bship_v
call load_sprite
add sp, 4
; -- AIRCRAFT CARRIER -----
push offset ac_h_pcx
push offset ac_h
call load_sprite
add sp, 4
push offset ac_v_pcx
push offset ac_v
call load_sprite
add sp, 4
; ---- MISS BOAT -----
push offset miss_pcx
push offset miss
call load_sprite
add sp, 4
; ---- HIT BOAT -----
push offset hit1_pcx
push offset hit1
call load_sprite
add sp, 4
restart_game:
;// Set the video mode
mov ah, CHANGE_VIDEO
mov al, GRAPH_MODE
int DOS_VIDEO
;// show_pcx("fire.pcx",0)
push offset fire
call show_pcx
add sp, 2
;// Wait for a keyhit
mov ah, 7
int 21h
;clrscr(0)
push 0
call clrscr
add sp, 2
;// show_pcx("background.pcx",0)
push offset background
call show_pcx
add sp, 2
;// draw_screen(U_Grid, 5, 5)
push 5
push 5
push offset U_Grid
call draw_screen
add sp, 6
;// Enable the mouse
mov ax, 0001h
int 33h
;// Limit the mouse movement
mov ax, 0007h ;// Horizontal
mov cx, 5 ;// MIN
mov dx, 144 ;// MAX
shl cx, 1 ;// Multiply by 2 for 640 resolution
shl dx, 1 ;// Multiply by 2 for 640 resolution
int 33h
mov ax, 0008h ;// Vertical
mov cx, 5 ;// MIN
mov dx, 144 ;// MAX
int 33h
;// Position the mouse pointer within the box
mov ax, 0004h ;// Mouse pos
mov cx, 50 ;// Column
shl cx, 1
mov dx, 50 ;// Row
int 33h
;// Get the user to add ships
loop_put_ship_user:
mov bx, 0 ;// Clear the mouse output
;// draw_screen(U_Grid, 5, 5)
push 5
push 5
push offset U_Grid
call draw_screen
add sp, 6
cmp [curr_turn], 5
jne not_five
jmp loop_put_ship_user_done
not_five:
;// Reset to the default of left button pressed
mov [button], MOUSE_BUTTON_LEFT
;// Check if a mouse button was pressed
mov ax, MOUSE_POS_BUTTON
int DOS_MOUSE
cmp bx, MOUSE_BUTTON_LEFT
je left_button_pressed_ship
cmp bx, MOUSE_BUTTON_RIGHT
jne loop_put_ship_user
mov [button], MOUSE_BUTTON_RIGHT
left_button_pressed_ship:
;// Figure out which ship is being placed
cmp [curr_turn], 0
jne not_zero
mov [curr_ship], 2
not_zero:
cmp [curr_turn], 1
jne not_one
mov [curr_ship], 2
not_one:
cmp [curr_turn], 2
jne not_two
mov [curr_ship], 4
not_two:
cmp [curr_turn], 3
jne not_three
mov [curr_ship], 6
not_three:
cmp [curr_turn], 4
jne not_four
mov [curr_ship], 8
not_four:
inc [curr_turn]
;// Check if the ship is vertical or horizontal
mov ax, [button]
add [curr_ship], ax
dec [curr_ship]
;// cx contains x
shr cx, 1 ;// divide x by 2
sub cx, 5
sub dx, 5
mov bx, dx ;// Store dx so i can do divide
mov dx, 0
mov ax, cx
div [fourteen] ;// I couldnt fit 16 on screen
;shr ax, 3
mov cx, 0
mov cl, al
mov dx, 0
mov ax, bx
div [fourteen]
;shr ax, 4
mov dl, al
;// Now dx, contains the row and (y)
;// cx, contains the column (x)
;// ax = validate(U_Grid, [curr_ship], x, y)
push ax ;// Make room for return value
push dx
push cx
push [curr_ship]
push offset U_Grid
call validate
add sp, 8
pop ax ;// AX knows if the placement is valid
cmp ax, TRUE
je valid_position
dec [curr_turn]
jmp loop_put_ship_user
valid_position:
;// putship(U_Grid, bship_h, x, y)
push dx
push cx
push [curr_ship] ;// bship_h
push offset U_Grid
call put_ship
add sp, 8
jmp loop_put_ship_user
loop_put_ship_user_done:
;// ---------- COMPUTER PLACEMENT OF SHIPS ------------------------
;// INITIALIZE THE VARIABLES
mov [curr_turn], 0
loop_put_ship_comp:
mov bx, 0 ;// Clear the mouse output
;// draw_screen(C_Grid, 5, 5)
;push 5
;push 5
;push offset C_Grid
;call draw_screen
;add sp, 6
;// DONE INSERTING THE COMPUTERS PLAYERS
cmp [curr_turn], 5
jne not_five_comp
jmp loop_put_ship_comp_done
not_five_comp:
cmp [curr_turn], 0
jne not_zero_comp
mov [curr_ship], 2
not_zero_comp:
cmp [curr_turn], 1
jne not_one_comp
mov [curr_ship], 2
not_one_comp:
cmp [curr_turn], 2
jne not_two_comp
mov [curr_ship], 4
not_two_comp:
cmp [curr_turn], 3
jne not_three_comp
mov [curr_ship], 6
not_three_comp:
cmp [curr_turn], 4
jne not_four_comp
mov [curr_ship], 8
not_four_comp:
inc [curr_turn]
;// Figure out which ship is being placed WITH A RANDOM NUMBER
;// button = _get_ran(2)
push 0 ;// Make room for the return value
push 2
call _get_ran
add sp, 2
pop [button]
mov dx, 0
mov bx, 2
div bx
mov ax, dx
;// Check if the ship is vertical or horizontal
; mov ax, [button]
add [curr_ship], ax
;// GET A RANDOM X NUMBER AND STORE IT TO CX
;// ax = _get_ran(8)
push 0 ;// make room for the return value
push 8
call _get_ran
add sp, 2
pop ax
mov dx, 0
mov bx, 10
div bx
mov cx, dx
;// GET A RANDOM Y NUMBER AND STORE IT TO DX
;// ax = _get_ran(8)
push 0 ;// make room for the return value
push 8
call _get_ran
add sp, 2
pop ax
mov dx, 0
mov bx, 10
div bx
;// Remainder is stored to DX!
;// Now dx, contains the row and (y)
;// cx, contains the column (x)
;// ax = validate(C_Grid, [curr_ship], x, y)
push ax ;// Make room for return value
push dx
push cx
push [curr_ship]
push offset C_Grid
call validate
add sp, 8
pop ax ;// AX knows if the placement is valid
cmp ax, TRUE
je valid_position_comp
dec [curr_turn]
jmp loop_put_ship_comp
valid_position_comp:
;// putship(C_Grid, bship_h, x, y)
push dx
push cx
push [curr_ship] ;// bship_h
push offset C_Grid
call put_ship
add sp, 8
jmp loop_put_ship_comp
loop_put_ship_comp_done:
;------------------------------ DONE COMPUTER PLACEMENT -----------
;// Limit the mouse movement ----------------------------------
mov ax, 0007h ;// Horizontal
mov cx, 160 ;// MIN
mov dx, 300 ;// MAX
shl cx, 1 ;// Multiply by 2 for 640 resolution
shl dx, 1 ;// Multiply by 2 for 640 resolution
int 33h
mov ax, 0008h ;// Vertical
mov cx, 5 ;// MIN
mov dx, 144 ;// MAX
int 33h
;// Position the mouse pointer within the box
mov ax, 0004h ;// Mouse pos
mov cx, 200 ;// Column
shl cx, 1
mov dx, 50 ;// Row
int 33h
;// ----------THIS PART IS THE ACTUALL GAME LOOP!! ------------------
mov [comp_hits], 0
mov [user_hits] ,0
loop_key:
;// draw_screen(U_Grid, 5, 5)
push 5
push 5
push offset U_Grid
call draw_screen
add sp, 6
;// CHECK IF THE USER HAS WON (PREFERENCE IS GIVEN TO THE USER)
cmp [user_hits], 16
jne not_user_hits
jmp user_wins
not_user_hits:
;// CHECK IF THE COMPUTER WINS (IN A TIE WIN GOES TO USER
cmp [comp_hits], 16
jne not_comp_hits
jmp comp_wins
not_comp_hits:
;// ------------ LET THE USER TAKE A SHOT -------------------------
; Check for mouse button
mov ax, MOUSE_POS_BUTTON
int DOS_MOUSE
cmp bx, MOUSE_BUTTON_LEFT
je left_button_pressed
jmp no_button
left_button_pressed:
shr cx, 1 ;// divide x by 2
sub cx, 160
sub dx, 5
mov bx, dx ;// Store dx so i can do divide
mov dx, 0
mov ax, cx
div [fourteen] ;// I couldnt fit 16 on screen
;shr ax, 3
mov cx, 0
mov cl, al
mov dx, 0
mov ax, bx
div [fourteen]
;shr ax, 4
mov dl, al
;// ------- FIRST ADD DATA TO THE COMPUTER GRID ------------
;//read_2d(C_Grid,y,x)
push 0 ;// First return value pos "ship_data"
push 0 ;// Second return value pos "hit_data"
push dx
push cx
push offset C_Grid
call read_2d
add sp, 6
pop [c_hit_data]
pop [c_ship_data]
;//read_2d(U_Grid,y,x)
push 0 ;// First return value pos "ship_data"
push 0 ;// Second return value pos "hit_data"
push dx
push cx
push offset U_Grid
call read_2d
add sp, 6
pop [u_hit_data]
pop [u_ship_data]
cmp [u_hit_data], WATER_
je hit_water
jmp loop_key ;// THEY ALREADY HIT THIS PLACE
hit_water:
;//insert(C_Grid, x, y, 0, 1);
; Put (1,2) at location (0,1)
cmp [c_ship_data], WATER_
jne ship_hit
push [c_hit_data]
push 10
jmp continue_ship_hit
ship_hit:
inc [user_hits]
push [c_hit_data]
push 11
continue_ship_hit:
push dx ;y
push cx ;x
push offset C_Grid
call insert_2d
add sp, 10
;//insert(U_Grid, x, y, 0, 1);
; Put (1,2) at location (0,1)
cmp [c_ship_data], WATER_
jne ship_hit2
push 10
push [u_ship_data]
jmp continue_ship_hit2
ship_hit2:
push 11
push [u_ship_data]
continue_ship_hit2:
push dx ;y
push cx ;x
push offset U_Grid
call insert_2d
add sp, 10
;// ------------ LET THE COMPUTER TAKE A SHOT -------------------------
computer_shot:
;// GET A RANDOM X NUMBER AND STORE IT TO CX
;// ax = _get_ran(8)
push 0 ;// make room for the return value
push 8
call _get_ran
add sp, 2
pop ax
mov dx, 0
mov bx, 10
div bx
mov cx, dx
;// GET A RANDOM Y NUMBER AND STORE IT TO DX
;// ax = _get_ran(8)
push 0 ;// make room for the return value
push 8
call _get_ran
add sp, 2
pop ax
mov dx, 0
mov bx, 10
div bx
;// Remainder is stored to DX!
;// ------- FIRST ADD DATA TO THE COMPUTER GRID ------------
;//read_2d(C_Grid,y,x)
push 0 ;// First return value pos "ship_data"
push 0 ;// Second return value pos "hit_data"
push dx
push cx
push offset C_Grid
call read_2d
add sp, 6
pop [c_hit_data]
pop [c_ship_data]
;//read_2d(U_Grid,y,x)
push 0 ;// First return value pos "ship_data"
push 0 ;// Second return value pos "hit_data"
push dx
push cx
push offset U_Grid
call read_2d
add sp, 6
pop [u_hit_data]
pop [u_ship_data]
;// Check if that position has already been shot at
cmp [c_hit_data], WATER_
je hit_water_comp
jmp computer_shot ;// THEY ALREADY HIT THIS PLACE
hit_water_comp:
;//insert(C_Grid, x, y, 0, 1);
; Put (1,2) at location (0,1)
cmp [u_ship_data], WATER_
jne ship_hit_comp
push 10
push [c_ship_data]
jmp continue_ship_hit_comp
ship_hit_comp:
inc [comp_hits]
push 11
push [c_ship_data]
continue_ship_hit_comp:
push dx ;y
push cx ;x
push offset C_Grid
call insert_2d
add sp, 10
;//insert(U_Grid, x, y, SHIP, HIT);
; Put (HIT/MISS,HIT_DATA) at location (x,y)
cmp [u_ship_data], WATER_
jne ship_hit2_comp
push [u_hit_data]
push 10
jmp continue_ship_hit2_comp
ship_hit2_comp:
push [u_hit_data]
push 11
continue_ship_hit2_comp:
push dx ;y
push cx ;x
push offset U_Grid
call insert_2d
add sp, 10
no_button:
;// Check if there is a key to get
mov ah, 000Bh; KEYBOARD_STATUS
int 21h
cmp al, 00h
je no_key_available
jmp loop_key_done
no_key_available:
jmp loop_key ;// END OF GAME LOOP
;// Wait for a keyhit
mov ah, 7
int 21h
loop_key_done:
jmp done_wins
;// DISPLAY THE USER WIN SCREEN
user_wins:
;//clrscr(0);
push 0
call clrscr
add sp, 2
;//showpcx("win.pcx");
push offset win_pcx
call show_pcx
add sp, 2
jmp done_wins
;// DISPLAY THE COMPUTER WIN SCREEN
comp_wins:
;//clrscr(0);
push 0
call clrscr
add sp, 2
;//showpcx("lose.pcx");
push offset lose_pcx
call show_pcx
add sp, 2
done_wins:
;// Wait for the user to hit a key
;// Wait for a keyhit
mov ah, 7
int 21h
;// CHECK IF THE USER WANTS TO PLAY ANOTHER GAME
;// CHANGE SCREEN TO TEXT MODE
mov ah, CHANGE_VIDEO
mov al, TEXT_MODE
int DOS_VIDEO
play_again_loop:
;// ASK THE USER IF THEY WANT TO PLAY AGAIN
mov ah, 09h
mov dx, offset play_again
int 21h
mov ah, 01h
int 21h
;// AL now contains the character
cmp al, 'y'
je yes
jmp not_yes
yes:
;// Empty out the two grids
mov [grid_pos], 0
grid_empty:
;insert_2d(U_Grid, grid_pos, 0, 1, 1)
push WATER_
push WATER_
push 0
push [grid_pos]
push offset U_Grid
call insert_2d
add sp, 10
;insert_2d(C_Grid, grid_pos, 0, 1, 1)
push WATER_
push WATER_
push 0
push [grid_pos]
push offset C_Grid
call insert_2d
add sp, 10
inc [grid_pos]
cmp [grid_pos], GRID_SIZE
jb grid_empty
mov [comp_hits], 0
mov [user_hits], 0
mov [curr_ship], 0
mov [curr_turn], 0
jmp restart_game
not_yes:
mov ah, DOS_EXIT
mov al, 0
int DOSCALL
; ------------------------------------------------------------------------
; A Function to determine if a ship can be placed at a spot
; int validate(int *v_grid, int v_ship, int v_x, int v_y)
; int *v_grid - The grid containing ships, and hits
; int v_ship - The ship to be added to the graph
; int v_x - The row to add the info to
; int v_y - The col to add the info to
; -------------------------------
; RETURNS 1 if valid; 0 if invalid
; ------------------------------------------------------------------------
; EQUATE SECTION
V_SIZE EQU -2
V_ARRAY_POS EQU 0
V_PTBOAT_H EQU 2
V_PTBOAT_V EQU 3
V_CRUISER_H EQU 4
V_CRUISER_V EQU 5
V_BSHIP_H EQU 6
V_BSHIP_V EQU 7
V_AC_H EQU 8
V_AC_V EQU 9
V_PTBOAT_SIZE EQU 2
V_CRUISER_SIZE EQU 3
V_BSHIP_SIZE EQU 4
V_AC_SIZE EQU 5
V_WATER EQU 1
V_GRID_HIGH EQU 10
V_GRID_WIDE EQU 10
;// PARAMETERS
V_GRID_POS EQU 4
V_SHIP_POS EQU 6
V_X_POS EQU 8
V_Y_POS EQU 10
V_RESULT EQU 12
DATASEG
v_x dw 0
v_y dw 0
v_val1 dw 0
v_val2 dw 0
v_size_of_word dw 2
v_ship_size dw ?
v_ship dw ?
v_curr_size dw 0
CODESEG
proc validate
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si,di>
;// Get The Parameters From the Stack
mov ax, [bp + V_Y_POS] ; The row to add information to
mov [v_y ], ax
mov ax, [bp + V_X_POS] ; The col to add information to
mov [v_x ], ax
mov ax, [bp + V_SHIP_POS] ; Ship Type Information
mov [v_ship], ax
;// make si point to the start of the grid object
mov si, [bp + V_GRID_POS]
;// Find the size of the ship
cmp [v_ship], V_PTBOAT_H
jne v_not_ptboat_h
mov [v_ship_size], V_PTBOAT_SIZE
v_not_ptboat_h:
cmp [v_ship], v_PTBOAT_V
jne v_not_ptboat_v
mov [v_ship_size], V_PTBOAT_SIZE
v_not_ptboat_v:
cmp [v_ship], V_CRUISER_H
jne v_not_cruiser_h
mov [v_ship_size], V_CRUISER_SIZE
v_not_cruiser_h:
cmp [v_ship], V_CRUISER_V
jne v_not_cruiser_v
mov [v_ship_size], V_CRUISER_SIZE
v_not_cruiser_v:
cmp [v_ship], V_BSHIP_H
jne v_not_bship_h
mov [v_ship_size], V_BSHIP_SIZE
v_not_bship_h:
cmp [v_ship], V_BSHIP_V
jne v_not_bship_v
mov [v_ship_size], V_BSHIP_SIZE
v_not_bship_v:
cmp [v_ship], V_AC_H
jne v_not_ac_h
mov [v_ship_size], V_AC_SIZE
v_not_ac_h:
cmp [v_ship], V_AC_V
jne v_not_ac_v
mov [v_ship_size], V_AC_SIZE
v_not_ac_v:
;// Initialize the loop
mov [v_curr_size], 0
mov [WORD bp + V_RESULT], TRUE
v_loop:
mov ax, [v_curr_size]
cmp ax, [v_ship_size]
jae v_loop_done
;// val1 val2 read_2d(sp, v_x, v_y)
push ax ; Make room for the return values
push ax ;
push [v_y]
push [v_x]
push si
call read_2d
add sp, 6
pop [v_val2]
pop [v_val1]
;// Make sure the ship will sail on water
cmp [v_val1], V_WATER
je v_on_water
mov [WORD bp + V_RESULT], FALSE
jmp v_loop_done
v_on_water:
;// Set the curr ship to nothing
inc [v_curr_size]
mov dx, 0
mov ax, [v_ship]
mov bx, 2
div bx
cmp dx, 0
je v_even
inc [v_y]
;// Check if the boat is being placed off the grid
cmp [v_y], V_GRID_HIGH
jbe v_on_grid_y
mov [WORD bp + V_RESULT], FALSE
jmp v_loop_done
v_on_grid_y:
jmp v_loop
v_even:
inc [v_x]
cmp [v_x], V_GRID_WIDE
jbe v_on_grid_x
mov [WORD bp + V_RESULT], FALSE
jmp v_loop_done
v_on_grid_x:
jmp v_loop
v_loop_done:
;// Pop Registers Off the Stack
PopReg <di,si,dx,cx,bx,ax>
pop bp;
ret
endp validate
; ------------------------------------------------------------------------
; A Function to put a ship to a grid
; void insert_2d(int *puts_grid, int puts_ship, int puts_x, int puts_y)
; int *puts_grid - The grid containing ships, and hits
; int puts_ship - The ship to be added to the graph
; int puts_x - The row to add the info to
; int puts_y - The col to add the info to
; ------------------------------------------------------------------------
; EQUATE SECTION
PUTS_SIZE EQU -2
PUTS_ARRAY_POS EQU 0
PUTS_PTBOAT_H EQU 2
PUTS_PTBOAT_V EQU 3
PUTS_CRUISER_H EQU 4
PUTS_CRUISER_V EQU 5
PUTS_BSHIP_H EQU 6
PUTS_BSHIP_V EQU 7
PUTS_AC_H EQU 8
PUTS_AC_V EQU 9
PUTS_PTBOAT_SIZE EQU 2
PUTS_CRUISER_SIZE EQU 3
PUTS_BSHIP_SIZE EQU 4
PUTS_AC_SIZE EQU 5
;// PARAMETERS
PUTS_GRID_POS EQU 4
PUTS_SHIP_POS EQU 6
PUTS_X_POS EQU 8
PUTS_Y_POS EQU 10
DATASEG
puts_x dw 0
puts_y dw 0
puts_val1 dw 0
puts_val2 dw 0
puts_size_of_word dw 2
puts_ship_size dw ?
puts_ship dw ?
puts_curr_size dw 0
CODESEG
proc put_ship
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si,di>
;// Get The Parameters From the Stack
mov ax, [bp + PUTS_Y_POS] ; The row to add information to
mov [puts_y ], ax
mov ax, [bp + PUTS_X_POS] ; The col to add information to
mov [puts_x ], ax
mov ax, [bp + PUTS_SHIP_POS] ; Ship Type Information
mov [puts_ship], ax
;// make si point to the start of the grid object
mov si, [bp + PUTS_GRID_POS]
;// Find the size of the ship
cmp [puts_ship], PUTS_PTBOAT_H
jne puts_not_ptboat_h
mov [puts_ship_size], PUTS_PTBOAT_SIZE
puts_not_ptboat_h:
cmp [puts_ship], PUTS_PTBOAT_V
jne puts_not_ptboat_v
mov [puts_ship_size], PUTS_PTBOAT_SIZE
puts_not_ptboat_v:
cmp [puts_ship], PUTS_CRUISER_H
jne puts_not_cruiser_h
mov [puts_ship_size], PUTS_CRUISER_SIZE
puts_not_cruiser_h:
cmp [puts_ship], PUTS_CRUISER_V
jne puts_not_cruiser_v
mov [puts_ship_size], PUTS_CRUISER_SIZE
puts_not_cruiser_v:
cmp [puts_ship], PUTS_BSHIP_H
jne puts_not_bship_h
mov [puts_ship_size], PUTS_BSHIP_SIZE
puts_not_bship_h:
cmp [puts_ship], PUTS_BSHIP_V
jne puts_not_bship_v
mov [puts_ship_size], PUTS_BSHIP_SIZE
puts_not_bship_v:
cmp [puts_ship], PUTS_AC_H
jne puts_not_ac_h
mov [puts_ship_size], PUTS_AC_SIZE
puts_not_ac_h:
cmp [puts_ship], PUTS_AC_V
jne puts_not_ac_v
mov [puts_ship_size], PUTS_AC_SIZE
puts_not_ac_v:
;// Initialize the loop
mov [puts_curr_size], 0
puts_loop:
mov ax, [puts_curr_size]
cmp ax, [puts_ship_size]
jae puts_loop_done
mov bx, [puts_ship]
cmp ax, 0
je puts_first_cell
mov bx, 0
puts_first_cell:
;// insert_2d(sp, puts_x, puts_y, puts_ship, 1)
push 1
push bx ; The variable [puts_ship] or 0
push [puts_y]
push [puts_x]
push si
call insert_2d
add sp, 10
;// Set the curr ship to nothing
inc [puts_curr_size]
mov dx, 0
mov ax, [puts_ship]
mov bx, 2
div bx
cmp dx, 0
je puts_even
inc [puts_y]
jmp puts_loop
puts_even:
inc [puts_x]
jmp puts_loop
puts_loop_done:
;// Pop Registers Off the Stack
PopReg <di,si,dx,cx,bx,ax>
pop bp;
ret
endp put_ship
; ------------------------------------------------------------------------
; A Function to index into a 2D array
; int index(int *i_grid, int i_x, int i_y)
; int *in_grid - The grid containing ships, and hits
; int in_x - The column to check
; int in_y - The row to check
; ------------------------------------------------------------------------
; EQUATE SECTION
IN_LBR EQU -10
IN_UBR EQU -8
IN_LBC EQU -6
IN_UBC EQU -4
IN_SIZE EQU -2
IN_ARRAY_POS EQU 0
IN_SHIP EQU 0
IN_HIT EQU 2
;// PARAMETERS
IN_GRID_POS EQU 4
IN_X_POS EQU 6
IN_Y_POS EQU 8
IN_RETURN EQU 10
DATASEG
in_x dw 0
in_y dw 0
in_size_of_word dw 2
CODESEG
proc index
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si,di>
;// Get The Parameters From the Stack
mov ax, [bp + IN_Y_POS] ; The row to add information to
mov [in_y ], ax
mov ax, [bp + IN_X_POS] ; The col to add information to
mov [in_x ], ax
;// make si point to the start of the grid object
mov si, [bp + IN_GRID_POS]
;// Find the width of each row - store it in bx
mov bx, [si + IN_UBC]
sub bx, [si + IN_LBC]
inc bx ;// Include '0'
;// Get the row to add the information to
mov ax, [in_y]
;// Multiply the row by the size of a row
mul bx
;// Find out how far right to move in the current row
mov bx, [in_x] ;// NOTE: i_x is a letter like 'a' or 'd'
; sub bx, [si + IN_LBC] ;// Convert the char value to a # value
add ax, bx
;// Correct for the size of the cells
mul [in_size_of_word] ;// Each data member is a word
mul [WORD si + IN_SIZE] ;// The number of elements per cell
mov [bp + IN_RETURN], ax
;// Pop Registers Off the Stack
PopReg <di,si,dx,cx,bx,ax>
pop bp;
ret
endp index
; ------------------------------------------------------------------------
; A Function to Insert into a 2D array
; void insert_2d(int *i_grid, int i_x, int i_y, int i_v1, int i_v2)
; int *i_grid - The grid containing ships, and hits
; int i_x - The column to add the info to
; int i_y - The row to add the info to
; int i_v1 - The first data member of the cell (Ship type)
; int i_v2 - The second data member of the cell (Hit info)
; ------------------------------------------------------------------------
; EQUATE SECTION
I_LBR EQU -10
I_UBR EQU -8
I_LBC EQU -6
I_UBC EQU -4
I_SIZE EQU -2
I_ARRAY_POS EQU 0
I_SHIP EQU 0
I_HIT EQU 2
;// PARAMETERS
I_GRID_POS EQU 4
I_X_POS EQU 6
I_Y_POS EQU 8
I_V1_POS EQU 10
I_V2_POS EQU 12
DATASEG
i_x dw 0
i_y dw 0
i_v1 dw 0
i_v2 dw 0
size_of_word dw 2
CODESEG
proc insert_2d
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si,di>
;// Get The Parameters From the Stack
mov ax, [bp + I_Y_POS] ; The row to add information to
mov [i_y ], ax
mov ax, [bp + I_X_POS] ; The col to add information to
mov [i_x ], ax
mov ax, [bp + I_V1_POS] ; Ship Type Information
mov [i_v1], ax
mov ax, [bp + I_V2_POS] ; Grid Hit Information
mov [i_v2], ax
;// make si point to the start of the grid object
mov si, [bp + I_GRID_POS]
;// ax = index(si, x,y)
push ax ;// Create a space for the return value
push [i_y]
push [i_x]
push si
call index
add sp, 6
pop ax
;// Make si point to the correct place in the array
add si, ax
;// Move the data into its correct place
mov ax, [i_v1];
mov [si + I_SHIP], ax;
mov ax, [i_v2];
mov [si + I_HIT ], ax;
;// Pop Registers Off the Stack
PopReg <di,si,dx,cx,bx,ax>
pop bp;
ret
endp insert_2d
; ------------------------------------------------------------------------
; A Function to read from a 2D array
; int int read_2d(int *i_grid, int i_x, int i_y)
; int *i_grid - The grid containing ships, and hits
; int i_x - The column to read the info from
; int i_y - The row to read the info from
; ------------------------------------------------------------------------
; EQUATE SECTION
R_LBR EQU -10
R_UBR EQU -8
R_LBC EQU -6
R_UBC EQU -4
R_SIZE EQU -2
R_ARRAY_POS EQU 0
R_SHIP EQU 0
R_HIT EQU 2
;// PARAMETERS
R_GRID_POS EQU 4
R_X_POS EQU 6
R_Y_POS EQU 8
;// Return Value Positions
R_H_RESULT EQU 10 ;// The hit result
R_S_RESULT EQU 12 ;// The ship result
DATASEG
r_x dw 0
r_y dw 0
r_size_of_word dw 2
CODESEG
proc read_2d
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si,di>
;// Get The Parameters From the Stack
mov ax, [bp + R_Y_POS] ; The row to add information to
mov [r_y ], ax
mov ax, [bp + R_X_POS] ; The col to add information to
mov [r_x ], ax
;// make si point to the start of the grid object
mov si, [bp + R_GRID_POS]
;// ax = index(si, x,y)
push ax ;// Create a space for the return value
push [r_y]
push [r_x]
push si
call index
add sp, 6
pop ax
;// Make si point to the correct place in the array
add si, ax
;// Move the data into its correct place
mov ax, [si + I_SHIP]
mov [bp + R_S_RESULT], ax
mov ax, [si + I_HIT ]
mov [bp + R_H_RESULT], ax
;// Pop Registers Off the Stack
PopReg <di,si,dx,cx,bx,ax>
pop bp;
ret
endp read_2d
; ------------------------------------------------------------------------
; A Function to draw a pixel to the screen
; void put_pixel(int pp_x, int pp_y, int pp_color)
; int pp_x - The column to add the pixel to
; int pp_y - The row to add the pixel to
; int pp_color - The color to put at the location
; ------------------------------------------------------------------------
; EQUATE SECTION
;// PARAMETERS
PP_X_POS EQU 4
PP_Y_POS EQU 6
PP_COLOR_POS EQU 8
DATASEG
pp_x dw 0
pp_y dw 0
pp_color dw 0
CODESEG
proc put_pixel
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,cx,dx>
;// Get The Parameters From the Stack
mov ax, [bp + PP_Y_POS] ; The row to add information to
mov [pp_y ], ax
mov ax, [bp + PP_X_POS] ; The col to add information to
mov [pp_x ], ax
mov ax, [bp + PP_COLOR_POS] ; Ship Type Information
mov [pp_color], ax
;// Call the BIOS functoin
mov ax, [pp_color]
mov ah, 0Ch ;// Put Pixel to mode 13 screen
mov cx, [pp_x]
mov dx, [pp_y]
int 10h
;// Pop Registers Off the Stack
PopReg <dx,cx,ax>
pop bp;
ret
endp put_pixel
; ------------------------------------------------------------------------
; A Function to clear the screen to a specific color
; void clrscr(char c_color)
; int c_color - The color to put to the screen
; ------------------------------------------------------------------------
; EQUATE SECTION
;// PARAMETERS
C_COLOR_POS EQU 4
C_SCREEN_SIZE EQU 64000
DATASEG
c_color dw 0
c_x dw 0
CODESEG
proc clrscr
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx>
;// Get The Parameters From the Stack
mov ax, [bp + C_COLOR_POS] ; Color
mov [c_color], ax
;// Set the x variable
mov [c_x], 0
c_loop:
mov bx, [c_x]
cmp bx, C_SCREEN_SIZE
jae c_loop_done
;// Call the BIOS functoin
mov ax, [c_color]
mov ah, 0Ch ;// Put Pixel to mode 13 screen
mov cx, [c_x]
mov dx, [0]
int 10h
;// Incriment the pixel count
inc [c_x]
jmp c_loop
c_loop_done:
;// Pop Registers Off the Stack
PopReg <dx,cx,bx,ax>
pop bp;
ret
endp clrscr
; ------------------------------------------------------------------------
; A Function to show a 320x200 PCX to the screen
; void show_pcx(char* filename)
; char* sp_filename - The name of the file to display
; ------------------------------------------------------------------------
; EQUATE SECTION
;// PARAMETERS
SP_PCX_FILENAME EQU 4
SP_PCX_HEADER_SIZE EQU 128
SP_PCX_SIZE EQU 64000
DATASEG
sp_x dw 0
sp_y dw 0
sp_color db 0
sp_count dw 0
sp_filehandle dw ?
sp_num_bytes dw 0
sp_256 dw 0ffh
sp_palette db 3 dup(60)
CODESEG
proc show_pcx
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si>
;// Get The Parameters From the Stack
mov dx, [bp + SP_PCX_FILENAME] ; The row to add information to
;// Open the file
mov ah, 3Dh ;// Open file
mov al, 00h ;// Read only
int 21h ;// Call BIOS function to open file
mov [sp_filehandle], ax ; Save the file handle
;// LOAD THE PALETTE
;// Reset the counter
mov [sp_count],0
;// Move the file pos to the right location
mov ah, 42h
mov al, 02h
mov bx, [sp_filehandle]
mov dx, 0FD00h
mov cx, 0FFFFh
int 21h
;// Load the palette
sp_load_pal:
cmp [sp_count],255
jae sp_load_pal_done
; Get a character (R)
mov ah, 3fh
mov bx, [sp_filehandle]
mov cx, 3 ;// Read 3 bytes at a time
mov dx, offset sp_palette
int 21h
mov si, offset sp_palette
mov dx, 3C8h
mov ax, [sp_count]
out dx, al
inc dx
mov al, [si]
shr al, 2
out dx, al
mov al, [si+1]
shr al, 2
out dx, al
mov al, [si+2]
shr al, 2
out dx, al
inc [sp_count]
jmp sp_load_pal
sp_load_pal_done:
;// Move the file pos to the right location
mov ah, 42h
mov al, 00h
mov bx, [sp_filehandle]
mov dx, SP_PCX_HEADER_SIZE
mov cx, 0
int 21h
;// Set the counter variable
mov [sp_count], 0
sp_loop:
mov bx, [sp_count]
cmp bx, SP_PCX_SIZE
jae sp_loop_done
mov ah, 3fh
mov bx, [sp_filehandle]
mov cx, 1 ;// Read one byte at a time
mov dx, offset sp_color
int 21h
cmp [sp_color], 192
jb sp_raw_data
;// Must decode the RLE info
mov ah, 0
mov al, [sp_color]
sub ax, 192
mov [sp_num_bytes], ax
;// Get another character
mov ah, 3fh
mov bx, [sp_filehandle]
mov cx, 1 ;// Read one byte at a time
mov dx, offset sp_color
int 21h
sp_RLE:
cmp [sp_num_bytes], 0
jbe sp_loop
;// Put pixel
mov al, [sp_color]
mov ah, 0Ch ;// Put Pixel to mode 13 screen
mov cx, [sp_count]
mov dx, 0
int 10h
inc [sp_count]
dec [sp_num_bytes]
jmp sp_RLE
sp_raw_data:
;// Call the BIOS function
mov al, [sp_color]
mov ah, 0Ch ;// Put Pixel to mode 13 screen
mov cx, [sp_count]
mov dx, 0
int 10h
;// Increment the count
inc [sp_count]
jmp sp_loop
sp_loop_done:
;// Close the file
mov ah, 3Eh
mov bx, [sp_filehandle]
int 21h ;// KILL the handle
;// Pop Registers Off the Stack
PopReg <si,dx,cx,bx,ax>
pop bp;
ret
endp show_pcx
; ------------------------------------------------------------------------
; A Function to load a sprite from a pcx file
; void load_sprite(char* ls_sprite, char* ls_filename, int ls_wide,
; int ls_high)
; int ls_sprite - The memory location to save the sprite to
; int ls_filename - The name of the file containing the sprite
; int ls_wide - The width of the pcx file
; int ls_high - The height of the pcx file
; ------------------------------------------------------------------------
; EQUATE SECTION
;// PARAMETERS
LS_SPRITE_POS EQU 4
LS_FILENAME_POS EQU 6
LS_WIDE_POS EQU -4
LS_HIGH_POS EQU -2
LS_PCX_HEADER_SIZE EQU 128
DATASEG
ls_color dw 0
ls_count dw 0
ls_total dw 0
ls_filehandle dw 0
ls_num_bytes dw 0
ls_wide dw 0
ls_x dw 0
CODESEG
proc load_sprite
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si>
;// Get The Parameters From the Stack
mov dx, [bp + LS_FILENAME_POS]
;// Open the file
mov ah, 3Dh ;// Open file
mov al, 00h ;// Read only
int 21h ;// Call BIOS function to open file
mov [ls_filehandle], ax ;// Store the file handle
;// Move the file pos to the right location
mov ah, 42h
mov al, 00h
mov bx, [ls_filehandle]
mov dx, LS_PCX_HEADER_SIZE
mov cx, 0
int 21h
;// Set the counter variable
mov [ls_count], 0
mov [ls_x], 0
;// Find the number of bytes in the pic
mov si, [bp + LS_SPRITE_POS]
mov ax, [si + LS_WIDE_POS]
mov [ls_wide], ax
mov bx, [WORD si + LS_HIGH_POS]
mul bx
mov [ls_total], ax
ls_loop:
mov bx, [ls_count]
cmp bx, [ls_total]
jb ls_loop_continue
jmp ls_loop_done
ls_loop_continue:
mov ah, 3fh
mov bx, [ls_filehandle]
mov cx, 1 ;// Read one byte at a time
mov dx, offset ls_color
int 21h
cmp [ls_color], 192
jb ls_raw_data
;// Must decode the RLE info
mov ax, [ls_color]
sub ax, 192
mov [ls_num_bytes], ax
;// Get another character
mov ah, 3fh
mov bx, [ls_filehandle]
mov cx, 1 ;// Read one byte at a time
mov dx, offset ls_color
int 21h
ls_RLE:
cmp [ls_num_bytes], 0
jbe ls_loop
;// Store the byte to the sprite
mov ax, [ls_color]
mov [si], al
inc [ls_count]
inc si
inc [ls_x]
dec [ls_num_bytes]
jmp ls_RLE
ls_raw_data:
mov ax, [ls_color]
mov [si], al
inc si
inc [ls_count]
inc [ls_x]
jmp ls_loop
ls_loop_done:
;// Close the file
mov ah, 3Eh
mov bx, [ls_filehandle]
int 21h ;// KILL the handle
;// Pop Registers Off the Stack
PopReg <si,dx,cx,bx,ax>
pop bp;
ret
endp load_sprite
; ------------------------------------------------------------------------
; A Function to put a sprite to the screen
; void put_sprite(char* ps_sprite, int ps_x, int ps_y)
; char* ps_sprite - The picture to show to the screen
; int ps_x - The x pos to show the pic to
; int ps_y - The y pos to show the pic to
; ------------------------------------------------------------------------
; EQUATE SECTION
;// PARAMETERS
PS_SPRITE_POS EQU 4
PS_X_POS EQU 6
PS_Y_POS EQU 8
PS_WIDE_POS EQU -4
PS_HIGH_POS EQU -2
DATASEG
ps_x dw 0
ps_x_start dw 0
ps_y dw 0
ps_wide dw 0
ps_color db 0
ps_count dw 0
ps_total dw 0
CODESEG
proc put_sprite
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si>
;// Get the parameters
mov ax, [bp + PS_X_POS]
mov [ps_x], ax
mov [ps_x_start], ax
mov ax, [bp + PS_Y_POS]
mov [ps_y], ax
mov si, [bp + PS_SPRITE_POS]
;// The total bytes in the image
mov ax, [si + PS_WIDE_POS]
mov [ps_wide], ax
mul [WORD si + PS_HIGH_POS]
mov [ps_total], ax
;// Set the counter variable
mov [ps_count], 0
ps_loop:
mov bx, [ps_count]
cmp bx, [ps_total]
jae ps_loop_done
;// Get the current color
mov al, [si]
mov [ps_color], al
;// Put pixel
mov al, [ps_color]
mov ah, 0Ch ;// Put Pixel to mode 13 screen
mov cx, [ps_x]
mov dx, [ps_y]
int 10h
;// Increment all the variables
inc [ps_count]
inc [ps_x]
inc si
mov ax, [ps_x]
sub ax, [ps_x_start]
cmp ax, [ps_wide]
jb ps_loop
mov ax, [ps_x_start]
mov [ps_x], ax
inc [ps_y]
jmp ps_loop
ps_loop_done:
;// Pop Registers Off the Stack
PopReg <si,dx,cx,bx,ax>
pop bp;
ret
endp put_sprite
; ------------------------------------------------------------------------
; A Function to draw the screen
; void draw_screen(char* ds_dgrid, int ds_x_pos, int ds_y_pos)
; char* ds_grid - The defense grid
; int ds_x_pos - The col to place the grid at
; int ds_y_pos - The row to place the grid at
; ------------------------------------------------------------------------
; EQUATE SECTION
;// PARAMETERS
DS_Y_PARAMETER EQU 8
DS_X_PARAMETER EQU 6
DS_GRID_POS EQU 4
DS_CELL_SIZE EQU 14
DS_DGRID_X EQU 5
DS_DGRID_Y EQU 5
DS_TGRID_X EQU 160
DS_TGRID_Y EQU 5
DS_NOTHING EQU 0
DS_WATER EQU 1
DS_PTBOAT_H EQU 2
DS_PTBOAT_V EQU 3
DS_CRUISER_H EQU 4
DS_CRUISER_V EQU 5
DS_BSHIP_H EQU 6
DS_BSHIP_V EQU 7
DS_AC_H EQU 8
DS_AC_V EQU 9
DS_MISS EQU 10
DS_HIT1 EQU 11
DS_GRID_LBR EQU -10
DS_GRID_UBR EQU -8
DS_GRID_LBC EQU -6
DS_GRID_UBC EQU -4
DS_GRID_SIZE EQU -2
DATASEG
ds_x dw 0
ds_x_pos dw 0
ds_x_start dw 0
ds_y dw 0
ds_y_pos dw 0
ds_ship dw 0
ds_hit dw 0
ds_count dw 0
ds_size dw ?
ds_d_LBR dw ?
ds_d_UBR dw ?
ds_d_LBC dw ?
ds_d_UBC dw ?
ds_d_grid_wide dw ?
ds_d_total dw ?
ds_d_grid_cell_wide dw ?
CODESEG
proc draw_screen
;// Create a Base Pointer
push bp;
mov bp, sp;
;// Push Registers Onto Stack
PushReg <ax,bx,cx,dx,si>
;// Get the grid
mov si, [bp + DS_GRID_POS]
mov ax, [si + DS_GRID_SIZE]
mov [ds_size], ax
mov ax, [si + DS_GRID_LBR]
mov [ds_d_LBR], ax
mov ax, [si + DS_GRID_UBR]
mov [ds_d_UBR], ax
mov ax, [si + DS_GRID_LBC]
mov [ds_d_LBC], ax
mov ax, [si + DS_GRID_UBC]
mov [ds_d_UBC], ax
;// Get the screen position to add the graph to
mov ax, [bp + DS_X_PARAMETER]
mov [ds_x_pos], ax
mov ax, [bp + DS_Y_PARAMETER]
mov [ds_y_pos], ax
;// Find the width of the grid
mov ax, [ds_d_UBC]
sub ax, [ds_d_LBC]
inc ax ; Include '0'
mov [ds_d_grid_wide], ax
mov ax, [ds_d_UBR]
sub ax, [ds_d_LBR]
inc ax ; Include '0'
mul [ds_d_grid_wide]
mov [ds_d_total], ax
mov ax, DS_CELL_SIZE
mul [ds_d_grid_wide]
mov [ds_d_grid_cell_wide], ax
;// Put the grid to the screen
;// Set the counter variable
mov [ds_count], 0
mov [ds_x], 0
mov [ds_y], 0
ds_loop:
mov ax, [ds_count]
cmp ax, [ds_d_total]
jb ds_continue
jmp ds_loop_done ; Relative jump fix
ds_continue:
;// Get the current Ship Data
mov ax, [si]
mov [ds_ship], ax
;// Get the current Hit Data
add si, [ds_size]
mov ax, [si]
mov [ds_hit], ax
;// Check if anything needs to be drawn
cmp [ds_ship], DS_NOTHING
jne ds_do_put_sprite
jmp ds_no_put_sprite
ds_do_put_sprite:
;// Put Ship Data
mov ax, [ds_y]
add ax, [ds_y_pos] ;// Offset from edge of screen
push ax
mov ax, [ds_x]
add ax, [ds_x_pos] ;// Offset from edge of screen
push ax
;// Figure out what to draw
cmp [ds_ship], DS_PTBOAT_H
jne ds_not_ptboat_h
push offset ptboat_h
ds_not_ptboat_h:
cmp [ds_ship], DS_PTBOAT_V
jne ds_not_ptboat_v
push offset ptboat_v
ds_not_ptboat_v:
cmp [ds_ship], DS_CRUISER_H
jne ds_not_cruiser_h
push offset cruiser_h
ds_not_cruiser_h:
cmp [ds_ship], DS_CRUISER_V
jne ds_not_cruiser_v
push offset cruiser_v
ds_not_cruiser_v:
cmp [ds_ship], DS_BSHIP_H
jne ds_not_bship_h
push offset bship_h
ds_not_bship_h:
cmp [ds_ship], DS_BSHIP_V
jne ds_not_bship_v
push offset bship_v
ds_not_bship_v:
cmp [ds_ship], DS_AC_H
jne ds_not_ac_h
push offset ac_h
ds_not_ac_h:
cmp [ds_ship], DS_AC_V
jne ds_not_ac_v
push offset ac_v
ds_not_ac_v:
cmp [ds_ship], DS_MISS
jne ds_not_miss
push offset miss
ds_not_miss:
cmp [ds_ship], DS_WATER
jne ds_not_water
push offset water
ds_not_water:
cmp [ds_ship], DS_HIT1
jne ds_not_hit1
push offset hit1
ds_not_hit1:
call put_sprite
add sp, 6
ds_no_put_sprite:
;// Put Hit Data
;// put_sprite(water, DS_DGRID_X + ds_x, DS_DGRID_Y + ds_y)
mov ax, [ds_y]
add ax, DS_TGRID_Y
push ax
mov ax, [ds_x]
add ax, DS_TGRID_X
push ax
cmp [ds_hit], DS_WATER
jne ds_not_water2
push offset water
ds_not_water2:
cmp [ds_hit], DS_HIT1
jne ds_not_hit2
push offset hit1
ds_not_hit2:
cmp [ds_hit], DS_MISS
jne ds_not_miss2
push offset miss
ds_not_miss2:
call put_sprite
add sp, 6
;// Increment all the variables
inc [ds_count]
add [ds_x], DS_CELL_SIZE
add si, [ds_size]
;// Check if it is time to move down a row
mov ax, [ds_x]
cmp ax, [ds_d_grid_cell_wide]
jae ds_wrap
jmp ds_loop
ds_wrap:
;// The end of the line has been reached
;// Move y down 1 and reset x
mov [ds_x], 0
add [ds_y], DS_CELL_SIZE
jmp ds_loop
ds_loop_done:
;// Pop Registers Off the Stack
PopReg <si,dx,cx,bx,ax>
pop bp;
ret
endp draw_screen
;=====================================================================
; Random Number Subroutines Implementation by: R.F. Genovese, Ph.D.
; TEKNOMETRIKA
; L-15, S-123
; 11160 Veirs Mill Road
; Wheaton, MD 20902
;=====================================================================
;we used tasm /ml /w
;---------------------------------------------------------------------
; void _seed_ran(void)
; unsigned int _get_ran(unsigned char bitsize)
;---------------------------------------------------------------------
DATASEG
PUBLIC _r_seed
_r_seed DD 55aaaaaah ;31 bit shift register
CODESEG
;---------------------------------------------------------------------
; void _seed_ran(void)
; seeds the 31 bit shift register used by the pseudorandom generator
; from BIOS ticks counter at 40h:6ch
;---------------------------------------------------------------------
PROC _seed_ran
mov ax,40h ;BIOS segment
mov es,ax
mov ax,[es:6ch] ;get ticks
mov [WORD LOW _r_seed],ax ;into lsw shift register
; we rather cheaply toggle ax and stick it in the high word
not ax
mov [WORD HIGH _r_seed],ax ;into msw shift register
ret ;that's it
ENDP _seed_ran
;---------------------------------------------------------------------
; unsigned int _get_ran(unsigned char bitsize)
; returns a pseudorandom number as an unsigned integer with
; bitsize number of bits. Maximum value of bitsize is 16. Larger
; values will be truncated to 16 bits (i.e. unsigned int size) as
; will a bitsize=0.
;---------------------------------------------------------------------
GR_BITSIZE EQU 4
GR_RESULT EQU 6
PROC _get_ran
push bp
mov bp,sp
push cx
push bx
push ax
;first get and check bitsize from caller
mov cl,[bp + GR_BITSIZE]
xor ch,ch
jcxz @@truncate
cmp cx,10h
jle @@size_ok
@@truncate:
mov cx,10h ;force 16 bit size
@@size_ok:
xor ax,ax ;initalize return value
@@gen_num:
;generate bitsize pseudorandom bits into ax by the result of
;(bit three xor bit six) of the high byte of the shift register
;the result is shifted into the cf and then into ax.
mov bx,[WORD HIGH _r_seed]
and bh,048h ;08h or 40h is result=1 else 0
cmp bh,08h
jz xor1
cmp bh,40h
jz xor1
clc ;xor result=0 so clear carry
jmp short shift_bits
xor1:
stc ;xor result=1 so set carry
;rotate the shift register with the cf becoming the lsb.
shift_bits:
rcl [WORD LOW _r_seed],1
rcl [WORD HIGH _r_seed],1
;rotate cf into our pseudorandom number in ax.
rcl ax,1
loop @@gen_num ;get all of the bits
mov [bp + GR_RESULT], ax
pop cx
pop bx
pop ax
pop bp ;clean up and pass the
ret ;number in ax to C
ENDP _get_ran
;webedone
END start