;---------------------------------------------------------------------- ;// 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, push reg ENDM ENDM PushReg MACRO PopReg registers IRP reg, 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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 ;// 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 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