kolibrios-fun/programs/c4/trunk/board.inc
Andrey Halyavin (halyavin) 065b8d32b2 programs sources added
git-svn-id: svn://kolibrios.org@31 a494cfbc-eb01-0410-851d-a64ba20cac60
2006-01-03 09:43:31 +00:00

318 lines
6.6 KiB
PHP

; C4
; Copyright (c) 2002 Thomas Mathys
; killer@vantage.ch
;
; This file is part of C4.
;
; C4 is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; C4 is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with C4; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
%ifndef _BOARD_INC
%define _BOARD_INC
;**********************************************************
; magic numbers
;**********************************************************
EMPTY equ 0
PLAYER1 equ 1
PLAYER2 equ 2
; board dimensions (+2 for border)
BWIDTH equ 9
BHEIGHT equ 8
;**********************************************************
; uninitialized data
;**********************************************************
section .bss
board resd BHEIGHT*BWIDTH ; the board
free resd BWIDTH ; # of free fields for each column
totalfree resd 1 ; total # of free fields
currentplayer resd 1 ; player to make next move
lastmove resd 1 ; last move done on the board
; (0 if no last move available)
;**********************************************************
; code
;**********************************************************
section .text
;**********************************************************
; boardReset
; reset board for new game
;
; input : nothing
; output : nothing
; destroys : nothing
;**********************************************************
boardReset:
pushfd
pushad
; clear all fields
mov edi,board
mov ecx,BHEIGHT * BWIDTH
mov eax,EMPTY
rep stosd
; init free array
mov edi,free
mov ecx,BWIDTH
mov eax,BHEIGHT - 2
rep stosd
mov dword [totalfree],(BWIDTH-2)*(BHEIGHT-2)
mov dword [currentplayer],PLAYER1
mov dword [lastmove],0
popad
popfd
ret
;**********************************************************
; BOARDISVALIDMOVE
; checks wether a move is valid
;
; input : 32 bit register containing a move
; number (1..7)
; output : zero flag set -> move is invalid
; zero flag clear -> move is valid
; destroys : nothing
;**********************************************************
%macro BOARDISVALIDMOVE 1
cmp dword [free+%1*4],0
%endmacro
;**********************************************************
; boardMakeMove
; make a move
;
; input : eax = move number (1..7)
; ebx = PLAYER1/PLAYER2
; output : nothing
; destroys : edi, flags
;**********************************************************
boardMakeMove:
mov edi,[free+eax*4] ; place stone
imul edi,BWIDTH
add edi,eax
mov [board+edi*4],ebx
dec dword [free+eax*4] ; one stone more in this column
dec dword [totalfree] ; one stone more on the board
mov [lastmove],eax ; store move for undo
ret
;**********************************************************
; boardUndoMove
; undo a move
;
; input : eax = move number to undo (1..7)
; output : move is undone
; destroys : edi, flags
;**********************************************************
boardUndoMove:
inc dword [free+eax*4] ; one stone less in this column
inc dword [totalfree] ; one stone less on the board
mov dword [lastmove],0 ; no last move available
mov edi,[free+eax*4] ; remove stone from board
imul edi,BWIDTH
add edi,eax
mov dword [board+edi*4],EMPTY
ret
;**********************************************************
; BOARDSWITCHPLAYERS
; switch current player
;
; input : nothing
; output : current player is switched
; destroys : flags
;**********************************************************
%macro BOARDSWITCHPLAYERS 0
xor dword [currentplayer],(PLAYER1 ^ PLAYER2)
%endmacro
;**********************************************************
; BOARDGETOTHERPLAYER
; get other player =)
;
; input : 32 bit register or variable
; output : player changed
; destroys : flags
;**********************************************************
%macro BOARDGETOTHERPLAYER 1
xor %1,(PLAYER1 ^ PLAYER2)
%endmacro
;**********************************************************
; BOARDISFULL
; check wether board is full
;
; input : nothing
; output : zero flag set -> board is full
; zero flag clear -> board isn't full
;**********************************************************
%macro BOARDISFULL 0
cmp dword [totalfree],0
%endmacro
;**********************************************************
; boardIsWin
; check wether the current board state is a win for the
; given player
;
; input : eax = player
; output : eax = nonzero -> win for player
; destroys : everything
;**********************************************************
boardIsWin:
; check wether last move is available
cmp dword [lastmove],0
jne .lastmoveok
xor eax,eax
ret
.lastmoveok:
; calculate the address of the most recently placed stone (edi)
mov edi,[lastmove]
mov esi,[free + edi*4]
inc esi
imul esi,BWIDTH
add edi,esi
shl edi,2
add edi,board
; check vertically
xor ecx,ecx ; reset counter
mov esi,edi ; start at last stone
.vertical:
cmp [esi],eax ; loop as long the stone [esi] belongs to player
jne .verticalend
add esi,BWIDTH*4 ; move to next stone
inc ecx ; one stone more in row
jmp short .vertical
.verticalend:
cmp ecx,4 ; 4 or more stones ?
jl .nope1 ; nope -> continue
mov eax,1 ; yeah -> tell caller =)
ret
.nope1:
; check horizontally
xor ecx,ecx
mov esi,edi
.horizontal1: ; left
cmp [esi],eax
jne .horizontalend1
sub esi,4
inc ecx
jmp short .horizontal1
.horizontalend1:
lea esi,[edi+4] ; right
.horizontal2:
cmp [esi],eax
jne .horizontalend2
add esi,4
inc ecx
jmp short .horizontal2
.horizontalend2:
cmp ecx,4
jl .nope2
mov eax,1
ret
.nope2:
; diagonally forward
xor ecx,ecx
mov esi,edi
.forward1:
cmp [esi],eax
jne .forwardend1
sub esi,(1+BWIDTH)*4
inc ecx
jmp short .forward1
.forwardend1:
lea esi,[edi+(1+BWIDTH)*4]
.forward2:
cmp [esi],eax
jne .forwardend2
add esi,(1+BWIDTH)*4
inc ecx
jmp short .forward2
.forwardend2:
cmp ecx,4
jl .nope3
mov eax,1
ret
.nope3:
; diagonally backward
xor ecx,ecx
mov esi,edi
.backward1:
cmp [esi],eax
jne .backwardend1
add esi,(1-BWIDTH)*4
inc ecx
jmp short .backward1
.backwardend1:
lea esi,[edi+(BWIDTH-1)*4]
.backward2:
cmp [esi],eax
jne .backwardend2
add esi,(BWIDTH-1)*4
inc ecx
jmp short .backward2
.backwardend2:
cmp ecx,4
jl .nope4
mov eax,1
ret
.nope4:
; no win for this player
xor eax,eax
ret
%endif