IS THERE A WAY, that I can convert this to a CODE that does not use stack, or use Array instead.
can u help me start with the RE-COde process.PLS.
Any help will do,.THANKS IN ADVANCE.
|
|
|
pop ebp retshould be this:
mov esp, ebp pop ebp ret
%include "asm_io.inc"
%define FALSE 0
%define TRUE 1
;for comparison
%define PLAYER 0
%define COMP 1
%define UNOCCUPIED 2
;Game state
%define ONGOING 0
%define DRAWN 1
%define PLAYER_WON 2
%define COMP_WON 3
;for spacing
%define NL 10
%define TAB 9
segment .data
Title db "This is the Tic Tac Toe Game!", NL, 0
segment .text
global asm_main
asm_main:
mov eax,Title
call print_string
call prompt_difficulty
mov esi, eax ;difficulty choosen is moved to esi
call clear_screen ; clear the screen from the instructions
xor ebx, ebx ; num_games = 0 ;number of games already played. Used to determine who should go first
m_game_loop:
mov ecx, ebx ;ecx = first
and ecx, 0x1 ; ecx = ebx % 2; ;for change of player or computer will input first
;; okay, so it looks like play_game() has two arguments, player (0 or 1) and difficulty (1 or 2)
push esi ;push esi = depende sa difficulty na gn choose nya
push ecx ;push ecx = depende kung pampila na nga game kung round 1, una user, then bulos bulos lng
call play_game
add esp, 8 ;clear out ang stack
;; it's also a cdecl function, rather than stdcall
;; why not just use 'inc ebx' ?
add ebx, 1 ; INCREMENT EBX or num_games
;Loop AGAIN TO PLAY. (DRI TA DAPAT MA BUTANG SCANNER na Q to quit)
jmp m_game_loop
; should never be reached, but for the sake of completeness...
;; what? but you don't even have a prologue for this 'start' code, how come you have an epilogue?
xor eax, eax
pop ebp
ret ; EXIT
;*------------------------------------CHOOSE OF DIFFICULTY-----------------------------------------------------------*
segment .data
; strings
level_msg1 db "Select a difficulty -", NL, 0
level_msg2 db TAB, "1. God. The computer plays perfect games. ", NL, TAB, " You have no mathematical chance of winning or maybe there is.", NL, 0
level_msg3 db TAB, "2. Devil. Thought God mode was too hard? Now try to lose :).", NL, 0
level_msg4 db "choice? ", 0
pd_str5 db "Enter a number between 1 and 2 inclusive.", NL, "? ", 0
pd_scanf_format_str db "%d", 0
segment .bss
pd_rtn resd 1
segment .text
global prompt_difficulty
extern printf, scanf, getchar
prompt_difficulty:
; print out the lines for difficulty level
mov eax,level_msg1
call print_string
mov eax,level_msg2
call print_string
mov eax,level_msg3
call print_string
mov eax,level_msg4
call print_string
; get the choice from the user
pd_scanf_loop:
call read_int
mov dword [pd_rtn],eax
pd_check_range: ; has to be 1 or 2
;; why not just compare EAX to 1 and 2?
cmp dword [pd_rtn], 1
jz pd_out_of_scanf_loop
cmp dword [pd_rtn], 2
jz pd_out_of_scanf_loop
mov eax,pd_str5
call print_string
jmp pd_scanf_loop
pd_out_of_scanf_loop:
;; come on, seriously? EAX is already equal to [pd_rtn]
mov eax, dword [pd_rtn]
; epilog
ret
;*-----------------------------------------------------------------------------------------------*
;*--------------------------------------PLAY GAME---------------------------------------------------------*
segment .data
; strings
pg_str1 db "The game was drawn.", NL, 0
pg_str2 db "Computer won :(", NL, 0
pg_str3 db "OMG!!Congratulations! You won!", NL, 0
segment .text
global play_game
%define pg_first [ebp+8]
%define pg_difficulty [ebp+12]
; stack variables
; ebp-36 to ebp-4
%define pg_board_array [ebp-36]
%define pg_turn [ebp-40]
%define pg_state [ebp-44]
%define pg_player_symbol [ebp-48]
%define pg_comp_symbol [ebp-52]
;%define pg_i [ebp-56]
%define pg_move [ebp-60]
play_game:
; prolog
push ebp
mov ebp, esp
sub esp, 60
push ebx
push edi
mov eax, pg_first ;turn = ECX (first);
mov dword pg_turn, eax
mov dword pg_state, ONGOING ;state = ONGOING(0)
lea ebx, pg_board_array ;board_array[ebx]
cmp dword pg_first, PLAYER
jz pg_player_first ;jmp to ang symbols if user ang una
mov dword pg_player_symbol, 'X' ;kapag PC naman una, amu ni ang symbols
mov dword pg_comp_symbol, 'O'
jmp pg_symbols_choosing_end
pg_player_first:
mov dword pg_player_symbol, 'O'
mov dword pg_comp_symbol, 'X'
;Tapus na ang pagpili sng symbols
pg_symbols_choosing_end:
;so ma initialize ta anay na wala pa unod ang ang board
;for (edi = 0; edi < 9; ++edi) {
; board[edi] = UNOCCUPIED;}
; initialize the board
cld
mov edi, ebx
mov ecx, 9
mov eax, UNOCCUPIED
rep stosd
pg_game_loop:
push ebx ;push naman kung ikapila na nga game EBX==NUmgames
call game_state ;b4 mag proceed check anay if may daug na
pop ecx ;OKAY NATAPUS NA CHECK
mov pg_state, eax ; so kung anu man result dd2 gna if 0,1,2,3
cmp eax, ONGOING ; compare ta sya sa ONGOING(2)
jnz pg_game_loop_end ;pag dili sya ongoing, ma END na ang ROUND
cmp dword pg_turn, PLAYER ;proceed ta d if ONGOING sya GYAPUN
jnz pg_game_loop_comp_turn ; Sa round 1 syempre ma una gd ang player kay ang value sng pg_turn ta diri is 0, kasi wala pa ma increment
; it's the player's turn
push dword pg_comp_symbol
push dword pg_player_symbol
push ebx
call prompt_move ;CALL PROMPT_MOVE, DIRI MA MAGALAIN ANG BOARD DIRI NAMAN DAUN MA PRINT SNG GAME BOARD
add esp, 12
mov dword [ebx + eax*4], PLAYER
call clear_screen
jmp pg_game_loop_endif
pg_game_loop_comp_turn:
push dword pg_difficulty
push ebx
call comp_move
add esp, 8
mov dword [ebx + eax*4], COMP
pg_game_loop_endif:
xor dword pg_turn, 1
jmp pg_game_loop
pg_game_loop_end:
call clear_screen
push dword FALSE
push dword pg_comp_symbol
push dword pg_player_symbol
push ebx
call print_board
add esp, 16
cmp dword pg_state, COMP_WON ;check if PC ang winner
jnz pg_declare_result_check2 ;
mov eax,pg_str2
call print_string
jmp pg_declare_result_end
pg_declare_result_check2:
cmp dword pg_state, PLAYER_WON ;check liwat if USER na gd man ang winner
jnz pg_declare_result_draw
mov eax,pg_str3
call print_string
jmp pg_declare_result_end
pg_declare_result_draw:
mov eax,pg_str1
call print_string
pg_declare_result_end:
; epilog
pop edi
pop ebx
add esp, 60
pop ebp
ret
;*----------------------------------------GAME STATE-------------------------------------------------------*
segment .data
; { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, /* horizontal */
; { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, /* vertical */
; { 0, 4, 8 }, { 2, 4, 6 } /* diagonals */
gs_groups dd 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 3, 6, 1, 4, 7, 2, 5, 8, 0, 4, 8, 2, 4, 6
segment .text
global game_state
; FUNCTION int game_state(int *board)
; determines the state of the game (PLAYER_WON, COMP_WON, or DRAWN)
; PARAMETERS board ([ebp+8]) - the current board
; RETURN the state of the game
%define gs_board [ebp+8]
game_state:
; prolog
push ebp
mov ebp, esp
push edi
push esi
mov edi, gs_board
mov esi, gs_groups
mov ecx, 8
gs_combo_loop:
mov edx, [esi] ;ang ESI amu na sya ang DIFFICULTY dbala
;; what's EDX supposed to be at this point?
mov eax, [edi + edx*4] ;VEN BULIG D DANAY D KO MA FIGURE OUT ja
cmp eax, UNOCCUPIED ;UNOCCUPIED = 2
jz gs_combo_loop_continue ;continue lng, we won't get a win by UNOCCUPIED
mov edx, [esi+4]
cmp [edi + edx*4], eax
jnz gs_combo_loop_continue
mov edx, [esi+8]
cmp [edi + edx*4], eax
jnz gs_combo_loop_continue
;dapat ma satisfy nya na ang conditions
;para mabalan na may winner
; we have a winner!
;if (board[combinations[i][0]] == PLAYER
; && board[combinations[i][1]] == PLAYER
; && board[combinations[i][2]] == PLAYER) {
;return PLAYER_WON;
;else if (board[combinations[i][0]] == COMP
; && board[combinations[i][1]] == COMP
; && board[combinations[i][2]] == COMP) {
;return COMP_WON;
cmp eax, PLAYER
jnz gs_determine_winner_comp
mov eax, PLAYER_WON ;eax = 2
jmp gs_epilog ;go to ret
gs_determine_winner_comp:
mov eax, COMP_WON ;eax = 3
jmp gs_epilog ;goto ret
gs_combo_loop_continue:
add esi, 12
loop gs_combo_loop ;ga liwat2x sya yata check
; drawn or ongoing
cld
mov eax, UNOCCUPIED
mov ecx, 9
repne scasd
jnz gs_not_found
mov eax, ONGOING ;set value of EAX = 2, kay wala pa may nagdaug, so continue gyapun
jmp gs_epilog
gs_not_found:
mov eax, DRAWN
gs_epilog:
pop esi
pop edi
;; what about the 'mov esp, ebp' right before this ?!!!!
pop ebp
ret
;*-------------------------------------------PROMPT MOVE----------------------------------------------------*
segment .data
pm_prompt db "Your move: ", 0
pm_prompt_err db "Enter the number of an empty square.", NL, 0
pm_format db "%d", 0
segment .text
global prompt_move
; FUNCTION int prompt_move(int *board, int player_symbol, int comp_symbol)
; prompt a legal move (for the board) from the user
; PARAMETERS board ([ebp+8]) - the current board
; player_symbol ([ebp+12]) - symbol for the player
; comp_symbol ([ebp+16]) - symbol for the comp
; RETURN the move entered
%define pm_board [ebp+8]
%define pm_player_symbol [ebp+12]
%define pm_comp_symbol [ebp+16]
%define pm_move [ebp-4]
prompt_move:
push ebp
mov ebp, esp
sub esp, 4
; print out the board first
push dword TRUE
push dword pm_comp_symbol
push dword pm_player_symbol
push dword pm_board
call print_board ;PRINT MUNA ANG GAMEBOARD
add esp, 16
jmp pm_input_loop
pm_input_loop_err:
push pm_prompt_err
call printf
pop ecx
pm_input_loop:
push pm_prompt
call printf
pop ecx
lea eax, pm_move
push eax
push pm_format
call scanf
add esp, 8
cmp eax, 1
jz pm_input_loop_check_range
jmp pm_input_loop_cleanup
pm_input_loop_check_range:
cmp dword pm_move, 9
jg pm_input_loop_err
cmp dword pm_move, 1
jl pm_input_loop_err
mov eax, pm_move
mov edx, pm_board
sub eax, 1
cmp dword [edx + eax*4], UNOCCUPIED
jnz pm_input_loop_err
jmp pm_input_loop_out
pm_input_loop_cleanup:
call getchar
cmp eax, NL
jnz pm_input_loop_cleanup
jmp pm_input_loop_err
pm_input_loop_out:
mov eax, pm_move
sub eax, 1
; epilog
add esp, 4
pop ebp
ret
;*---------------------------------------COMP_MOVE------------------------------------*
segment .text
global comp_move
; FUNCTION int comp_move(int *board, int difficulty)
; generate a move for the computer player, for difficulty level specified
; PARAMETERS board ([ebp+8]) - the current board
; difficulty ([ebp+12]) - the difficulty level (1 or 2)
; RETURN the move to be made
%define cm_board [ebp+8]
%define cm_difficulty [ebp+12]
%define cm_best_score [ebp-4]
%define cm_best_move [ebp-8]
comp_move:
; prolog
push ebp
mov ebp, esp
sub esp, 8
; we need to preserve ebx
push ebx
mov ebx, cm_board
; initialize the variables
mov dword cm_best_score, -999
mov ecx, 9
xor edx, edx
cm_loop:
cmp dword [ebx + edx*4], UNOCCUPIED
jnz cm_loop_continue
mov dword [ebx + edx*4], COMP
push ecx
push edx
push dword cm_difficulty
push dword PLAYER
push ebx
call minimax
add esp, 12
pop edx
pop ecx
neg eax
mov dword [ebx + edx*4], UNOCCUPIED
cmp eax, cm_best_score
jle cm_loop_continue
mov cm_best_score, eax
mov cm_best_move, edx
cm_loop_continue:
add edx, 1
loop cm_loop
mov eax, cm_best_move
jmp cm_epilog
cm_epilog:
pop ebx
add esp, 8
pop ebp
ret
;*-----------------------------------------MINIMAX--------------------------------
segment .data
; memory jump table!! =D
mm_jump_table dd mm_ongoing, mm_drawn, mm_player_won, mm_comp_won
segment .text
global minimax
; FUNCTION int minimax(int *board, int stm, int difficulty)
; evaluate the current board in stm's perspective
; 0 means draw
; 10 means win on board
; 9 means win in 1
; ...
; -10 means loss on board
; -9 means loss in 1
; ...
; PARAMETERS board ([ebp+8]) - the current board
; stm ([ebp+12]) - side to move
; difficulty ([ebp+16]) - difficulty level (1 or 2)
; RETURN the score
%define mm_board [ebp+8]
%define mm_stm [ebp+12]
%define mm_difficulty [ebp+16]
%define mm_bestmove [ebp-4]
%define mm_bestscore [ebp-8]
minimax:
; prolog
push ebp
mov ebp, esp
sub esp, 8
; we need to preserve ebx
push ebx
mov ebx, mm_board
mov dword mm_bestscore, -999
; call game_state
push ebx
call game_state
pop ecx
jmp [mm_jump_table + eax*4]
mm_ongoing:
mov ecx, 9
xor edx, edx
mm_recurse_loop:
cmp dword [ebx + edx*4], UNOCCUPIED
jnz mm_recurse_loop_continue
push ecx
push edx
mov eax, mm_stm
mov dword [ebx + edx*4], eax
push dword mm_difficulty
xor dword mm_stm, 1
push dword mm_stm
xor dword mm_stm, 1
push ebx
call minimax
add esp, 12
pop edx
pop ecx
neg eax
mov dword [ebx + edx*4], UNOCCUPIED
cmp eax, mm_bestscore
jle mm_recurse_loop_continue
mov mm_bestscore, eax
mov mm_bestmove, edx
mm_recurse_loop_continue:
add edx, 1
loop mm_recurse_loop
cmp dword mm_bestscore, 0
jle mm_ongoing_le
sub dword mm_bestscore, 1
jmp mm_ongoing_end
mm_ongoing_le:
cmp dword mm_bestscore, 0
jz mm_ongoing_end
add dword mm_bestscore, 1
mm_ongoing_end:
mov eax, mm_bestscore
jmp mm_epilog
mm_drawn:
xor eax, eax
jmp mm_epilog
mm_player_won:
; if the sum of stm and difficulty is odd, return 10, else -10
mov eax, dword mm_stm
add eax, mm_difficulty
test eax, 0x1
jnz mm_return_10
jmp mm_return_n10
mm_comp_won:
; if the sum of stm and difficulty is even, return 10, else -10
mov eax, dword mm_stm
add eax, mm_difficulty
test eax, 0x1
jz mm_return_10
jmp mm_return_n10
mm_return_10:
mov eax, 10
jmp mm_epilog
mm_return_n10:
mov eax, -10
jmp mm_epilog
mm_epilog:
pop ebx
add esp, 8
pop ebp
ret
;----------------------------------------'PRINT BOARD'-------------------------------------
segment .data
pb_f_beg db NL, NL, NL, NL, 0
pb_f_val db TAB, " %c | %c | %c", NL, 0
pb_f_sep db TAB, "------------", NL, 0
pb_f_end db NL, 0
segment .text
global print_board
; FUNCTION void print_board(int *board, int player_symbol, int comp_symbol, int print_numbers)
; print the board to stdout in a human readable format
; PARAMETERS board ([ebp+8]) - the current board
; player_symbol ([ebp+12]) - the symbol used to represent the player
; comp_symbol ([ebp+16]) - the symbol used to represent the computer
; print_numbers ([ebp+20]) - boolean. whether numbers should be used for unoccupied squares
; RETURN none
%define pb_board [ebp+8]
%define pb_player_symbol [ebp+12]
%define pb_comp_symbol [ebp+16]
%define pb_print_numbers [ebp+20]
%define pb_print_table [ebp-36]
print_board:
;prolog
push ebp
mov ebp, esp
sub esp, 36
push edi
push esi
lea edi, pb_print_table
mov esi, pb_board
mov ecx, 9 ;serves as the counter
xor edx, edx ;edx = 0
pb_loop:
;char print_bd[9]
;int i
;for (i = 0; i < 9; ++i) {
; if (board[i] == UNOCCUPIED) {
; if (print_numbers) {
; print_bd[i] = i + '1';
; } else {
; print_bd[i] = ' ';
; }
; } else if (board[i] == PLAYER) {
; print_bd[i] = player_symbol;
; } else if (board[i] == COMP) {
; print_bd[i] = comp_symbol;
; }
;}
cmp dword [esi + edx*4], UNOCCUPIED
jnz pb_loop_occupied
cmp dword pb_print_numbers, 0
jnz pb_loop_print_numbers
mov dword [edi + edx*4], ' '
jmp pb_loop_continue
pb_loop_print_numbers:
mov dword [edi + edx*4], '1'
add dword [edi + edx*4], edx
jmp pb_loop_continue
pb_loop_occupied:
cmp dword [esi + edx*4], PLAYER
jnz pb_loop_comp
mov eax, pb_player_symbol
mov dword [edi + edx*4], eax
jmp pb_loop_continue
pb_loop_comp:
mov eax, pb_comp_symbol
mov dword [edi + edx*4], eax
jmp pb_loop_continue
pb_loop_continue:
add edx, 1
loop pb_loop
pb_loop_end:
push pb_f_beg
call printf
push dword [edi + 8]
push dword [edi + 4]
push dword [edi + 0]
push pb_f_val
call printf
push pb_f_sep
call printf
push dword [edi + 20]
push dword [edi + 16]
push dword [edi + 12]
push pb_f_val
call printf
push pb_f_sep
call printf
push dword [edi + 32]
push dword [edi + 28]
push dword [edi + 24]
push pb_f_val
call printf
push pb_f_end
call printf
add esp, 64
pop esi
pop edi
add esp, 36
pop ebp
ret
;----------------------------------------------'SYSTEM CLEAR'---------------------------------
segment .data
cs_cmd db "clear", 0
;cs_cmd db "cls", 0
; use the second one for Windows
segment .text
global clear_screen
extern system
; FUNCTION void clear_screen()
; clear the screen using OS functions
; PARAMETERS none
; RETURN none
clear_screen:
; prolog
push ebp
mov ebp, esp
push cs_cmd
call system
pop ecx
pop ebp
ret
Note, however, that all the 'je' and 'jne' instructions are 'jz' and 'jnz' , in the text above. That's because to go over it, I had to do such a change, because I'm used to working with 'jz' and 'jnz' . In case you're wondering, 'je' is a mnemonic synonym for 'jz' , and 'jne' is a mnemonic synonym for 'jnz' , which means that it doesn't matter which you use - the assembler will still convert either ('je' or 'jz' , for example) to the same opcode (0x74, and then a byte that specifies the relative-to-the-next-instruction offset of where to jump). je one jz one one:assemble to the same opcode, as can be seen, when disassembled:
00000000 7402 jz 0x4 00000002 7400 jz 0x4(at offset 0, 'jz 4' assembles to 0x74 (which is JZ), relative 0x02; at offset 2, 'jz 4' assembles to 0x74, relative 0x00)
%define ONGOING 0 %define DRAWN 1 %define PLAYER_WON 2 %define COMP_WON 3return 0, 1, 2, or 3, depending on what the board has. And each slot in the board (obviously) should have one of these values:
%define PLAYER 0 %define COMP 1 %define UNOCCUPIED 2(0, 1, or 2)
a b c d e f g h i
[a, b, c, d, e, f, g, h, i]
0 members, 1 guests, 0 anonymous users