Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 30 → Rev 31

/programs/c4/trunk/Readme.txt
0,0 → 1,27
C4 0.1
Copyright (C) 2002 Thomas Mathys
killer@vantage.ch
 
 
What's this ?
-------------
 
C4 is a connect four clone for MenuetOS
(http://www.menuetos.org).
 
 
Installation
------------
 
Simply copy the executable (C4) onto your MenuetOS floppy.
You don't need to copy anything else, the image files are
linked into the executable.
 
If you want to compile C4 yourself you need NASM.
Get it from http://nasm.sourceforge.net.
 
Compile C4 using the following command:
 
nasm -f bin -o c4 c4.asm
(nasmw if you have the win32 version)
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/ai.inc
0,0 → 1,270
; 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 _AI_INC
%define _AI_INC
 
 
INFTY equ 1000000000
 
 
 
section .data
 
; table used to perform some primitive move "ordering":
; middle columns which are usually more important are
; searched first.
moveorder dd 1,7,2,6,3,5,4
 
; table used for static evaluation.
; this table is taken from 4st attack: it is ways better
; than the table i used before =)
evaltable: dd 0, 0, 0, 0, 0, 0, 0, 0, 0
dd 0, 3, 4, 5, 7, 5, 4, 3, 0
dd 0, 4, 6, 8,10, 8, 6, 4, 0
dd 0, 5, 8,12,13,12, 8, 5, 0
dd 0, 5, 8,12,13,12, 8, 5, 0
dd 0, 4, 6, 8,10, 8, 6, 4, 0
dd 0, 3, 4, 5, 7, 5, 4, 3, 0
dd 0, 0, 0, 0, 0, 0, 0, 0, 0
 
 
 
section .bss
 
cpulevel resd 1 ; level of current cpu player
bestval resd 1 ; value of best move found so far
nbestmoves resd 1 ; # of best moves found so far
bestmoves resd 7 ; array to hold all best moves
 
 
 
section .text
 
 
 
;**********************************************************
; aiGetMove
; returns a move for a computer player
;
; input : eax = cpu level ( >= 1)
; output : eax = move
; destroys : everything
;**********************************************************
aiGetMove:
 
; initialize variables
mov [cpulevel],eax
mov dword [bestval],-INFTY
mov dword [nbestmoves],0
; try every move
mov ecx,6
.evalmoves:
 
; get move to make from move order table
mov eax,[moveorder+ecx*4]
; if this is an invalid move, continue with next move
BOARDISVALIDMOVE eax
jz .nextmove
 
; make move for current player
mov ebx,[currentplayer]
call boardMakeMove
; evaluate move
push eax ; save move #
push ecx ; save loop counter
push dword [cpulevel] ; ply
mov ebx,[currentplayer] ; player
BOARDGETOTHERPLAYER ebx
push ebx
push dword -INFTY ; alpha
push dword INFTY ; beta
call alphabeta
neg eax ; damn, how could i forget this ???
mov ebx,eax ; save result for later
pop ecx ; restore loop counter
pop eax ; restore move #
; undo move (eax = move #)
call boardUndoMove
; let's see wether we have a new best move
cmp ebx,[bestval] ; new best value found ?
jle .nonewbestval
mov [bestval],ebx ; yes -> save it
mov dword [nbestmoves],1 ; delete everything that was in the list
mov [bestmoves+0],eax ; save move number in list
jmp short .nextmove ; continue with next move
.nonewbestval:
cmp ebx,[bestval] ; another best value found ?
jne .nextmove
mov ebx,[nbestmoves] ; yes -> add move to list
mov [bestmoves+ebx*4],eax
inc dword [nbestmoves]
 
.nextmove:
dec ecx
js .done
jmp .evalmoves
.done:
; randomly pick one of the best moves
call rand ; rand() % nbestmoves
xor edx,edx
div dword [nbestmoves]
mov eax,[bestmoves+edx*4] ; get move from list
ret
 
; test code : pick first move from list
mov eax,[bestmoves+0]
ret
 
 
 
;**********************************************************
; alphabeta
;
; input : see below
; output : eax = move value
; destroys : everything
;**********************************************************
alphabeta:
 
%define ply (ebp+20)
%define player (ebp+16)
%define alpha (ebp+12)
%define beta (ebp+ 8)
 
enter 0,0
; win for other player -> end search
mov eax,[player]
BOARDGETOTHERPLAYER eax
call boardIsWin
or eax,eax
jz .nowin
mov eax,-1000000
mov ebx,[ply]
shl ebx,10
sub eax,ebx
leave
ret 4*4
.nowin:
; board full but no win -> draw -> end search
BOARDISFULL
jnz .notfull
xor eax,eax
leave
ret 4*4
.notfull
; max search depth reached -> do static evaluation
cmp dword [ply],0
je .staticeval
 
; for each move
mov ecx,6
.evalmoves:
 
; while (alpha < beta)
mov eax,[alpha]
cmp eax,[beta]
jge .done
 
; pick move from move order table
mov eax,[moveorder+ecx*4]
; invalid move ? if so, continue with next move
BOARDISVALIDMOVE eax
jz .nextmove
; make move for current player
mov ebx,[player]
call boardMakeMove
; evaluate move
push eax
push ecx
mov eax,[ply] ; ply = ply-1
dec eax
push eax
mov ebx,[player] ; player = other player
BOARDGETOTHERPLAYER ebx
push ebx
mov ecx,[beta] ; alpha = -beta
neg ecx
push ecx
mov edx,[alpha] ; beta = -alpha
neg edx
push edx
call alphabeta
neg eax
; new alpha ?
cmp eax,[alpha]
jle .nonewalpha
mov [alpha],eax ; yes -> save it
.nonewalpha:
pop ecx
pop eax
; undo move
call boardUndoMove
 
.nextmove: ; evaluate next move
dec ecx
jns .evalmoves
.done:
mov eax,[alpha]
leave
ret 4*4
; static evaluation
.staticeval:
xor eax,eax
mov esi,BWIDTH*BHEIGHT-1
.l:
mov ebx,[board+esi*4] ; get stone from board
cmp ebx,[player] ; player's stone ?
jne .notplayer ; nope -> go on
add eax,[evaltable+esi*4] ; yes -> add stone value to eax
jmp .next ; next stone
.notplayer:
cmp ebx,EMPTY ; other player's stone ?
je .empty ; nope -> go on
sub eax,[evaltable+esi*4] ; yes -> sub stone value from eax
.empty:
.next: ; next stone
dec esi
jns .l
leave ; eax contains static value
ret 4*4
 
%undef ply
%undef player
%undef alpha
%undef beta
 
%endif
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/blue.pcx
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/c4/trunk/board.inc
0,0 → 1,318
; 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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/c4.asm
0,0 → 1,910
; 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
 
bits 32
%include 'mos.inc'
section .text
 
MOS_HEADER01 start,end
 
 
 
;**********************************************************
; magic numbers
;**********************************************************
 
; initial player types
PL1TYPE_INIT equ 0
PL2TYPE_INIT equ 4
 
; window
WND_WIDTH equ 259
WND_HEIGHT equ 300
WND_WORKCOLOR equ 0
 
; button dimensions
BUTTON_HEIGHT equ 12
 
BUTTON_NEW_X equ 14
BUTTON_NEW_Y equ 30
BUTTON_NEW_WIDTH equ 56
 
BUTTON_SPIN_WIDTH equ 8
BUTTON_PL1DN_X equ 228
BUTTON_PL1DN_Y equ 30
BUTTON_PL1UP_X equ (BUTTON_PL1DN_X + BUTTON_SPIN_WIDTH + 1)
BUTTON_PL1UP_Y equ BUTTON_PL1DN_Y
 
BUTTON_PL2DN_X equ BUTTON_PL1DN_X
BUTTON_PL2DN_Y equ (BUTTON_PL1DN_Y + 20)
BUTTON_PL2UP_X equ (BUTTON_PL2DN_X + BUTTON_SPIN_WIDTH + 1)
BUTTON_PL2UP_Y equ BUTTON_PL2DN_Y
 
; label dimensions
LABEL_PL1_X equ 90
LABEL_PL1_Y equ (1 + BUTTON_PL1DN_Y + (BUTTON_HEIGHT-8)/2)
LABEL_PL2_X equ LABEL_PL1_X
LABEL_PL2_Y equ (1 + BUTTON_PL2DN_Y + (BUTTON_HEIGHT-8)/2)
LABEL_PL1TYPE_X equ (LABEL_PL1_X + 10*6)
LABEL_PL1TYPE_Y equ LABEL_PL1_Y
LABEL_PL2TYPE_X equ LABEL_PL1TYPE_X
LABEL_PL2TYPE_Y equ LABEL_PL2_Y
LABEL_STATUS_X equ 14
LABEL_STATUS_Y equ 279
LABEL_STATUS_WIDTH equ 220
LABEL_STATUS_HEIGHT equ 8
 
 
 
; board and stones
STONESIZE equ 32 ; stone height and width
GRIDX equ 14 ; upper left corner
GRIDY equ 70
GRIDSPACING equ (STONESIZE + 1) ; space between lines
GRIDHEIGHT equ (6*GRIDSPACING+1) ; total grid width and height
GRIDWIDTH equ (7*GRIDSPACING+1)
GRIDCOLOR equ MOS_RGB(128,128,128)
 
 
 
; button id's
BT_QUIT equ 1
BT_NEW equ 2
BT_PLAYER1DN equ 3
BT_PLAYER1UP equ 4
BT_PLAYER2DN equ 5
BT_PLAYER2UP equ 6
 
 
start:
jmp main
 
%include "pcx.inc"
%include "windows.inc"
%include "board.inc"
%include "rng.inc"
; %include "randomai.inc"
%include "ai.inc"
 
 
 
;**********************************************************
; main program
;**********************************************************
main:
call randomize
call defineWindow
call decrunchImages
call newGame
 
.msgpump:
; wait for event
mov ebx,1
mov eax,MOS_SC_WAITEVENTTIMEOUT
int 0x40
 
; process events
cmp eax,MOS_EVT_REDRAW
je short .redraw
cmp eax,MOS_EVT_KEY
je short .key
cmp eax,MOS_EVT_BUTTON
je short .button
 
call pollMouse
call gameLoop
jmp short .msgpump
 
.redraw:
call defineWindow
jmp short .msgpump
.key:
call keyboardInput
jmp short .msgpump
.button:
call handleButton
jmp short .msgpump
 
 
 
;**********************************************************
; button handling function
;**********************************************************
handleButton:
mov eax,MOS_SC_GETPRESSEDBUTTON ; get button id
int 0x40
 
cmp al,1 ; button pressed ?
je short .bye ; nope -> nothing to do
 
cmp ah,BT_QUIT ; which button has been pressed ?
je short .quit
cmp ah,BT_NEW
je short .new
cmp ah,BT_PLAYER1DN
je short .player1dn
cmp ah,BT_PLAYER1UP
je short .player1up
cmp ah,BT_PLAYER2DN
je short .player2dn
cmp ah,BT_PLAYER2UP
je short .player2up
.bye:
ret
.quit:
MOS_EXIT
.new:
call newGame
ret
.player1dn:
mov eax,[player1_type] ; get current type
or eax,eax ; already zero ?
jz .bla
dec eax ; nope -> decrement
mov [player1_type],eax ; write back
mov edi,label_pl1type ; and update label
call updatePlayerType
.bla:
ret
.player1up:
mov eax,[player1_type] ; get current type
cmp eax,NPLAYERTYPES-1 ; already max ?
je .bla2
inc eax ; nope -> increment
mov [player1_type],eax ; write back
mov edi,label_pl1type ; update label
call updatePlayerType
.bla2:
ret
.player2dn:
mov eax,[player2_type] ; get current type
or eax,eax ; already zero ?
jz .bla3
dec eax ; nope -> decrement
mov [player2_type],eax ; write back
mov edi,label_pl2type ; and update label
call updatePlayerType
.bla3:
ret
.player2up:
mov eax,[player2_type]
cmp eax,NPLAYERTYPES-1
je .bla4
inc eax
mov [player2_type],eax
mov edi,label_pl2type
call updatePlayerType
.bla4:
ret
 
 
 
;**********************************************************
; window definition function
;**********************************************************
defineWindow:
MOS_STARTREDRAW
 
mov edi,window
call drawWindow
 
mov edi,buttons
mov ecx,NBUTTONS
call drawButtons
 
mov edi,labels
mov ecx,NLABELS
call drawLabels
 
xor eax,eax
call drawBoard
MOS_ENDREDRAW
ret
 
 
 
;**********************************************************
; updateStatusText
;
; input : esi = ptr to new string
; output : status bar is updated
; destroys : everything
;**********************************************************
updateStatusText:
 
; different text ?
cmp [statusbar + LABEL.caption],esi
je .bye ; nope -> bye
mov dword [statusbar + LABEL.caption],esi ; yeah -> save & redraw
 
; clear background
mov ebx,MOS_DWORD(LABEL_STATUS_X,LABEL_STATUS_WIDTH)
mov ecx,MOS_DWORD(LABEL_STATUS_Y,LABEL_STATUS_HEIGHT)
xor edx,edx
mov eax,MOS_SC_DRAWBAR
int 0x40
; redraw label
mov edi,statusbar
mov ecx,1
call drawLabels
.bye:
ret
 
 
 
;**********************************************************
; updatePlayerType
; update player type label
; input: eax = new type
; edi = address label structure to update
;**********************************************************
updatePlayerType:
mov ebx,PLAYERTYPELEN ; calculate type string address
mul ebx
add eax,playertypes
mov [edi + LABEL.caption],eax ; write address
mov ecx,1 ; and redraw label
call drawLabels
ret
 
 
 
;**********************************************************
; board drawing stuff
;**********************************************************
 
; drawBoard
; draw whole board
;
; input : eax nonzero = clear board background
drawBoard:
 
; clear background ?
or eax,eax
jz .noclear
mov ebx,MOS_DWORD(GRIDX,GRIDWIDTH)
mov ecx,MOS_DWORD(GRIDY,GRIDHEIGHT)
mov edx,WND_WORKCOLOR
mov eax,MOS_SC_DRAWBAR
int 0x40
.noclear:
call drawGrid
call drawStones
ret
 
 
 
drawGrid:
; vertical lines
mov ebx,MOS_DWORD(GRIDX,GRIDX)
mov ecx,MOS_DWORD(GRIDY,GRIDY+GRIDHEIGHT-1)
mov edx,GRIDCOLOR
mov eax,MOS_SC_DRAWLINE
mov esi,8
.vlines:
int 0x40
add ebx,MOS_DWORD(GRIDSPACING,GRIDSPACING)
dec esi
jnz .vlines
; horizontal lines
mov ebx,MOS_DWORD(GRIDX,GRIDX+GRIDWIDTH-1)
mov ecx,MOS_DWORD(GRIDY,GRIDY)
mov esi,7
.hlines:
int 0x40
add ecx,MOS_DWORD(GRIDSPACING,GRIDSPACING)
dec esi
jnz .hlines
ret
drawStones:
mov ebx,6
.col:
mov ecx,7
.row:
call drawStone
loop .row
dec ebx
jnz .col
ret
 
 
; ecx = column (1..7)
; ebx = row (1..6)
drawStone:
pushad
 
; see which image to draw.
; the image offset is stored in ebp
mov eax,BWIDTH ; calculate address
mul ebx
add eax,ecx
mov eax,[board+eax*4] ; get stone ?
cmp eax,EMPTY ; empty field -> nothing to do
je .bye
mov ebp,redstone ; assume red stone
cmp eax,PLAYER1 ; red ?
je .stoneok ; yeah -> continue
mov ebp,bluestone ; nope -> use blue stone
.stoneok:
 
; calculate image position (edx)
mov eax,GRIDSPACING
dec ecx
mul ecx
add eax,GRIDX + 1
shl eax,16
mov ecx,eax
mov eax,GRIDSPACING
dec ebx
mul ebx
add eax,GRIDY + 1
mov cx,ax
mov edx,ecx
 
; put image (position is already in edx)
mov ebx,ebp ; image address
mov ecx,MOS_DWORD(STONESIZE,STONESIZE) ; image dimensions
mov eax,MOS_SC_PUTIMAGE
int 0x40
 
.bye:
popad
ret
 
 
 
decrunchImages:
mov esi,redpcx ; red stone
mov edi,redstone
mov ebx,REDPCXSIZE
call loadPCX
mov esi,bluepcx ; blue stone
mov edi,bluestone
mov ebx,BLUEPCXSIZE
call loadPCX
ret
 
 
 
resetInput:
mov dword [playerinput],0 ; no player input
mov dword [mouseinput],0
ret
 
 
 
;**********************************************************
; newGame
; set up everything for a game
;
; input : nothing
; output : nothing
; destroys : everything
;**********************************************************
newGame:
call boardReset ; reset and redraw board
mov eax,1
call drawBoard
call resetInput ; reset input
mov dword [gameover],0 ; game is running
ret
 
 
 
;**********************************************************
; pollMouse
; mouse polling routine
;
; input : nothing
; output : playerinput will be updated, if
; the player clicked on a valid
; field
; destroys : everything
;**********************************************************
pollMouse:
mov ebx,2
mov eax,MOS_SC_GETMOUSEPOSITION
int 0x40
and eax,1
jz .mousenotpressed
.mousepressed:
mov dword [mouseinput],0
call isActiveApp
or al,al
jz .notactive1
call getMouseCol
mov [mouseinput],eax
.notactive1:
ret
.mousenotpressed:
call isActiveApp
or al,al
jz .notactive2
call getMouseCol
cmp eax,[mouseinput]
jne .nonewinput
cmp dword [playerinput],0
jne .nonewinput
mov [playerinput],eax
.nonewinput:
.notactive2:
mov dword [mouseinput],0
ret
 
 
 
;**********************************************************
; getMouseCol
; calculate in which column the mouse is. or so.
;
; input : nothing
; output : eax = 0 -> mouse outside board
; eax = 1..7 -> column
; destroys : everything
;**********************************************************
getMouseCol:
 
mov ebx,1 ; get mouse position, window relative
mov eax,MOS_SC_GETMOUSEPOSITION
int 0x40
 
movzx ebx,ax ; y clipping
cmp ebx,GRIDY
jl .outside
cmp ebx,GRIDY + GRIDHEIGHT - 1
jg .outside
 
shr eax,16 ; calculate column from x coordinate
sub eax,GRIDX
js .outside ; negative -> outside of board (left)
cdq ; !
mov ebx,GRIDSPACING
div ebx
cmp eax,BWIDTH-3 ; right outside of board ?
jg .outside ; yes -> bye
inc eax ; xform into range [1,7]
ret
.outside
xor eax,eax
ret
 
 
 
;**********************************************************
; isActiveApp
; check wether we're the active application
;
; input : nothing
; output : al nonzero -> we are the active app
; destroys : everything
;**********************************************************
isActiveApp:
 
%define PROCINFO (ebp-MOS_PROCESSINFO_size)
 
enter MOS_PROCESSINFO_size,0
; get process information
mov eax,MOS_SC_GETPROCESSINFO
lea ebx,[ebp-MOS_PROCESSINFO_size]
mov ecx,-1
int 0x40
 
; set al to 1 if we are the active application
cmp ax,[PROCINFO+MOS_PROCESSINFO.windowStackPos]
sete al
leave
ret
%undef PROCINFO
 
 
 
;**********************************************************
; keyboardInput
; keyboard input handler, called from main loop
;
; input : nothing
; output : playerinput is updated
; destroys : everything
;**********************************************************
keyboardInput:
mov eax,MOS_SC_GETKEY ; get key
int 0x40
or al,al ; key available ?
jnz .bye ; no -> bye
cmp dword [playerinput],0 ; unprocessed input available ?
jne .bye ; yes -> bye
 
sub ah,'1' ; valid key ?
cmp ah,BWIDTH-3
ja .bye ; treat as unsigned : keys below '1' will
; be greater too =)
 
mov al,ah ; save input
and eax,255
inc eax
mov [playerinput],eax
 
.bye:
ret
 
 
 
;**********************************************************
; gameLoop
; game logic code or however you wish to call it.
; actually this is not a loop, but is called from
; the main loop
;**********************************************************
gameLoop:
 
; if the game is over, return
cmp dword [gameover],0
je .gamerunning
ret
.gamerunning:
 
call updatePlayerStatusText
 
; get move
call getMoveForCurrentPlayer
or eax,eax
jnz .moveok
ret ; no move available -> bye
.moveok:
 
; make move and update board graphics
mov ebx,[currentplayer] ; ebx = current player, eax contains already move
call boardMakeMove
call drawStones
 
; check wether game is over (either by a win or because the board is full)
mov eax,[currentplayer] ; win for current player ?
call boardIsWin
or eax,eax
jz .nowin ; no -> continue
mov esi,player1wins ; yes -> display message...
cmp dword [currentplayer],PLAYER1
je .blubb
mov esi,player2wins
.blubb:
call updateStatusText
mov dword [gameover],1 ; ...and end game
ret
.nowin:
BOARDISFULL ; board full, but no win ?
jnz .notfull ; no -> continue
mov esi,itisadraw ; yes -> display message...
call updateStatusText
mov dword [gameover],1 ; ...and end game
ret
.notfull:
 
; switch players and return to main loop
BOARDSWITCHPLAYERS
ret
 
 
 
;**********************************************************
; getMoveForCurrentPlayer
; returns the move made by the current player
; (either cpu or human)
;
; input : nothing
; output : eax = 0 -> no move made. this is
; usually the case for human players,
; when no valid input is available.
; else eax = move number
;**********************************************************
getMoveForCurrentPlayer:
 
; get type of current player
mov eax,[player1_type]
cmp dword [currentplayer],PLAYER1
je .ok
mov eax,[player2_type]
.ok:
 
; get move for human/cpu player
or eax,eax
jnz .cpu
.human:
mov eax,[playerinput] ; get input
or eax,eax ; input available ?
jz .nomove ; no -> return no move available
call resetInput ; !
BOARDISVALIDMOVE eax ; valid move `?
jz .nomove ; no -> return no move available
ret ; valid move available -> return it (eax)
 
.cpu:
call dword [aicode] ; call ai machine. cpu level is already in eax
ret
.nomove:
xor eax,eax
ret
 
 
 
;**********************************************************
; update status bar : which player's turn it is
;**********************************************************
updatePlayerStatusText:
cmp dword [currentplayer],PLAYER2
je .player2
mov esi,player1hmnprmpt
cmp dword [player1_type],0
je .statustextok
mov esi,player1cpuprmpt
jmp short .statustextok
.player2:
mov esi,player2hmnprmpt
cmp dword [player2_type],0
je .statustextok
mov esi,player2cpuprmpt
.statustextok:
call updateStatusText
ret
 
 
 
;**********************************************************
; initialized data
;**********************************************************
 
section .data
 
;
; window definition
;
windowtitle db "C4 0.1",0
window:
istruc WND
at WND.xposandsize, dd MOS_DWORD(0,WND_WIDTH)
at WND.yposandsize, dd MOS_DWORD(0,WND_HEIGHT)
at WND.workcolor, dd 0x03000000 | WND_WORKCOLOR
at WND.grabcolor, dd 0
at WND.framecolor, dd 0
at WND.caption, dd windowtitle
at WND.captioncolor, dd 0
at WND.flags, dd WND_CENTER | WND_DEFAULT_GRABCOLOR | WND_DEFAULT_FRAMECOLOR | WND_DEFAULT_CAPTIONCOLOR
iend
 
;
; button table
;
buttons:
istruc BUTTON ; new
at BUTTON.xposandsize
dd MOS_DWORD(BUTTON_NEW_X,BUTTON_NEW_WIDTH)
dd MOS_DWORD(BUTTON_NEW_Y,BUTTON_HEIGHT)
dd BT_NEW
dd BUTTON_COLOR_WORK
iend
istruc BUTTON ; player 1 down
at BUTTON.xposandsize
dd MOS_DWORD(BUTTON_PL1DN_X,BUTTON_SPIN_WIDTH)
dd MOS_DWORD(BUTTON_PL1DN_Y,BUTTON_HEIGHT)
dd BT_PLAYER1DN
dd BUTTON_COLOR_WORK
iend
istruc BUTTON ; player 1 up
at BUTTON.xposandsize
dd MOS_DWORD(BUTTON_PL1UP_X,BUTTON_SPIN_WIDTH)
dd MOS_DWORD(BUTTON_PL1UP_Y,BUTTON_HEIGHT)
dd BT_PLAYER1UP
dd BUTTON_COLOR_WORK
iend
istruc BUTTON ; player 2 down
at BUTTON.xposandsize
dd MOS_DWORD(BUTTON_PL2DN_X,BUTTON_SPIN_WIDTH)
dd MOS_DWORD(BUTTON_PL2DN_Y,BUTTON_HEIGHT)
dd BT_PLAYER2DN
dd BUTTON_COLOR_WORK
iend
istruc BUTTON ; player 2 up
at BUTTON.xposandsize
dd MOS_DWORD(BUTTON_PL2UP_X,BUTTON_SPIN_WIDTH)
dd MOS_DWORD(BUTTON_PL2UP_Y,BUTTON_HEIGHT)
dd BT_PLAYER2UP
dd BUTTON_COLOR_WORK
iend
NBUTTONS equ (($-buttons)/BUTTON_size)
 
 
;
; label table
;
 
newgame db "New game",0
down db "<",0
up db ">",0
pl1 db "Player 1:",0
pl2 db "Player 2:",0
 
 
playertypes:
db "Human ",0
PLAYERTYPELEN equ ($ - playertypes)
db "CPU level 1 ",0
db "CPU level 2 ",0
db "CPU level 3 ",0
db "CPU level 4 ",0
db "CPU level 5 ",0
db "CPU level 6 ",0
db "CPU level 7 ",0
db "CPU level 8 ",0
NPLAYERTYPES equ (($-playertypes)/PLAYERTYPELEN)
 
labels:
istruc LABEL ; new
at LABEL.position
dd MOS_DWORD(BUTTON_NEW_X+4,1+BUTTON_NEW_Y+(BUTTON_HEIGHT-8)/2)
dd newgame
dd LABEL_COLOR_WORKBUTTON
dd LABEL_BGCOLOR_TRANSPARENT
iend
istruc LABEL ; player 1 down
at LABEL.position
dd MOS_DWORD(BUTTON_PL1DN_X+(BUTTON_SPIN_WIDTH-4)/2,1+BUTTON_PL1DN_Y+(BUTTON_HEIGHT-8)/2)
dd down
dd LABEL_COLOR_WORKBUTTON
dd LABEL_BGCOLOR_TRANSPARENT
iend
istruc LABEL ; player 1 up
at LABEL.position
dd MOS_DWORD(1+BUTTON_PL1UP_X+(BUTTON_SPIN_WIDTH-4)/2,1+BUTTON_PL1UP_Y+(BUTTON_HEIGHT-8)/2)
dd up
dd LABEL_COLOR_WORKBUTTON
dd LABEL_BGCOLOR_TRANSPARENT
iend
istruc LABEL ; player 2 down
at LABEL.position
dd MOS_DWORD(BUTTON_PL2DN_X+(BUTTON_SPIN_WIDTH-4)/2,1+BUTTON_PL2DN_Y+(BUTTON_HEIGHT-8)/2)
dd down
dd LABEL_COLOR_WORKBUTTON
dd LABEL_BGCOLOR_TRANSPARENT
iend
istruc LABEL ; player 2 up
at LABEL.position
dd MOS_DWORD(1+BUTTON_PL2UP_X+(BUTTON_SPIN_WIDTH-4)/2,1+BUTTON_PL2UP_Y+(BUTTON_HEIGHT-8)/2)
dd up
dd LABEL_COLOR_WORKBUTTON
dd LABEL_BGCOLOR_TRANSPARENT
iend
istruc LABEL ; player 1
at LABEL.position
dd MOS_DWORD(LABEL_PL1_X,LABEL_PL1_Y)
dd pl1
dd MOS_RGB(255,255,255)
dd LABEL_BGCOLOR_TRANSPARENT
iend
istruc LABEL ; player 2
at LABEL.position
dd MOS_DWORD(LABEL_PL2_X,LABEL_PL2_Y)
dd pl2
dd MOS_RGB(255,255,255)
dd LABEL_BGCOLOR_TRANSPARENT
iend
statusbar: ; status bar
istruc LABEL
at LABEL.position
dd MOS_DWORD(LABEL_STATUS_X,LABEL_STATUS_Y)
dd 0
dd MOS_RGB(255,255,255)
dd LABEL_BGCOLOR_TRANSPARENT
iend
label_pl1type:
istruc LABEL
at LABEL.position
dd MOS_DWORD(LABEL_PL1TYPE_X,LABEL_PL1TYPE_Y)
dd playertypes+PL1TYPE_INIT*PLAYERTYPELEN
dd MOS_RGB(255,255,255)
dd MOS_RGB(0,0,0)
iend
label_pl2type:
istruc LABEL
at LABEL.position
dd MOS_DWORD(LABEL_PL2TYPE_X,LABEL_PL2TYPE_Y)
dd playertypes+PL2TYPE_INIT*PLAYERTYPELEN
dd MOS_RGB(255,255,255)
dd MOS_RGB(0,0,0)
iend
NLABELS equ (($-labels)/LABEL_size)
 
 
; player types
player1_type dd PL1TYPE_INIT
player2_type dd PL2TYPE_INIT
 
 
; status messages
player1hmnprmpt db "Make your move, player 1.",0
player2hmnprmpt db "Make your move, player 2.",0
player1cpuprmpt db "Player 1 is thinking, please wait...",0
player2cpuprmpt db "Player 2 is thinking, please wait...",0
itisadraw db "It's a draw.",0
player1wins db "Player 1 wins.",0
player2wins db "Player 2 wins.",0
 
 
; pointer to ai player. future releases C4 might
; or might not support different ai players =)
aicode dd aiGetMove
 
 
; button images
redpcx: incbin "red.pcx"
REDPCXSIZE equ ($ - redpcx)
bluepcx: incbin "blue.pcx"
BLUEPCXSIZE equ ($ - bluepcx)
 
 
 
;**********************************************************
; uninitialized data
;**********************************************************
 
section .bss
 
; player input
; 0 : no input available
; 1..7 : column to drop stone into
playerinput resd 1
 
mouseinput resd 1
gameover resd 1
 
redstone resb STONESIZE*STONESIZE*3
bluestone resb STONESIZE*STONESIZE*3
 
end:
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/mos.inc
0,0 → 1,305
; mos.inc 0.0.2
; Copyright (c) 2002 Thomas Mathys
; killer@vantage.ch
;
; This program 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.
;
; This program 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 this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;
;
;
; revision history
; ----------------
;
; 10-04-2002 version 0.0.2
; - removed MOS_WNDCOLORS_SIZE and similar constants.
; while reading the docs i realized that NASM creates
; such symbols already itself...
; + macros: MOS_WAITEVENT, MOS_WAITEVENT_S, MOS_STARTREDRAW,
; MOS_STARTREDRAW_S, MOS_ENDREDRAW, MOS_ENDREDRAW_S,
; MOS_GETSCREENMAX, MOS_GETSCREENMAX_S, MOS_EXIT, MOS_EXIT_S
; + event bit masks
; + some syscall numbers
; + process info structure
;
; 08-??-2002 version 0.0.1
; first release
;
%ifndef _MOS_INC
%define _MOS_INC
 
 
 
;**********************************************************
; generates a menuetos 01 header
; takes 2-6 parameters:
;
; MOS_HEADER01 start,end[,appmem,esp,i_param,i_icon]
;**********************************************************
 
%macro MOS_HEADER01 2-6 0x100000,0x7fff0,0,0
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd %1 ; start of code
dd %2 ; image size
dd %3 ; application memory
dd %4 ; esp
dd %5 ; i_param
dd %6 ; i_icon
%endmacro
 
 
;**********************************************************
; MOS_DWORD
; packs 2 words into a double word
;**********************************************************
 
%define MOS_DWORD(hi,lo) ((((hi) & 0xffff) << 16) + ((lo) & 0xffff))
 
 
;**********************************************************
; MOS_RGB
; creates a menuet os compatible color (0x00RRGGBB)
;**********************************************************
 
%define MOS_RGB(r,g,b) ((((r) & 255) << 16) + (((g) & 255) << 8) + ((b) & 255))
 
 
;**********************************************************
; window color structure
;**********************************************************
 
struc MOS_WNDCOLORS
.frame: resd 1
.grab: resd 1
.grabButton: resd 1
.grabButtonText: resd 1
.grabText: resd 1
.work: resd 1
.workButton: resd 1
.workButtonText: resd 1
.workText: resd 1
.workGraphics: resd 1
endstruc
 
 
;**********************************************************
; process info structure
;**********************************************************
 
struc MOS_PROCESSINFO
.CPUUsage: resd 1 ; cpu usage
.windowStackPos: resw 1 ; process' position in windowing stack
.windowStackVal: resw 1 ; window stack value at ecx
.reserved1: resw 1
.processName: resb 12 ; process name
.memStart: resd 1 ; start of process memory
.memUsed: resd 1 ; memory used by the process
.pid: resd 1 ; process id
.reserved2: resb (1024-34)
endstruc
 
 
 
;**********************************************************
; system call numbers
;**********************************************************
 
MOS_SC_EXIT equ -1
MOS_SC_DEFINEWINDOW equ 0
MOS_SC_PUTPIXEL equ 1
MOS_SC_GETKEY equ 2
MOS_SC_GETSYSCLOCK equ 3
MOS_SC_WRITETEXT equ 4
MOS_SC_DELAY equ 5
MOS_SC_OPENFILEFLOPPY equ 6
MOS_SC_PUTIMAGE equ 7
MOS_SC_DEFINEBUTTON equ 8
MOS_SC_GETPROCESSINFO equ 9
MOS_SC_WAITEVENT equ 10
MOS_SC_CHECKEVENT equ 11
MOS_SC_REDRAWSTATUS equ 12
MOS_SC_DRAWBAR equ 13
MOS_SC_GETSCREENMAX equ 14
MOS_SC_SETBACKGROUND equ 15
MOS_SC_GETPRESSEDBUTTON equ 17
MOS_SC_SYSTEMSERVICE equ 18
MOS_SC_STARTPROGRAM equ 19
MOS_SC_MIDIINTERFACE equ 20
MOS_SC_DEVICESETUP equ 21
MOS_SC_WAITEVENTTIMEOUT equ 23
MOS_SC_CDAUDIO equ 24
MOS_SC_SB16MIXER1 equ 25
MOS_SC_GETDEVICESETUP equ 26
MOS_SC_WSS equ 27
MOS_SC_SB16MIXER2 equ 28
MOS_SC_GETDATE equ 29
MOS_SC_READHD equ 30
MOS_SC_STARTPROGRAMHD equ 31
MOS_SC_GETSCREENPIXEL equ 35
MOS_SC_GETMOUSEPOSITION equ 37
MOS_SC_DRAWLINE equ 38
MOS_SC_GETBACKGROUND equ 39
MOS_SC_SETEVENTMASK equ 40
MOS_SC_WRITENUMBER equ 47
MOS_SC_WINDOWPROPERTIES equ 48
 
 
;**********************************************************
; event numbers
;**********************************************************
 
MOS_EVT_NONE equ 0
MOS_EVT_REDRAW equ 1
MOS_EVT_KEY equ 2
MOS_EVT_BUTTON equ 3
 
 
;**********************************************************
; event bits
;**********************************************************
 
MOS_EVTBIT_REDRAW equ (1 << 0)
MOS_EVTBIT_KEY equ (1 << 1)
MOS_EVTBIT_BUTTON equ (1 << 2)
MOS_EVTBIT_ENDREQUEST equ (1 << 3)
MOS_EVTBIT_BGDRAW equ (1 << 4)
MOS_EVTBIT_MOUSECHANGE equ (1 << 5)
MOS_EVTBIT_IPCEVENT equ (1 << 6)
MOS_EVTBIT_IRQ0 equ (1 << 16)
MOS_EVTBIT_IRQ1 equ (1 << 17)
MOS_EVTBIT_IRQ2 equ (1 << 18)
MOS_EVTBIT_IRQ3 equ (1 << 19)
MOS_EVTBIT_IRQ4 equ (1 << 20)
MOS_EVTBIT_IRQ5 equ (1 << 21)
MOS_EVTBIT_IRQ6 equ (1 << 22)
MOS_EVTBIT_IRQ7 equ (1 << 23)
MOS_EVTBIT_IRQ8 equ (1 << 24)
MOS_EVTBIT_IRQ9 equ (1 << 25)
MOS_EVTBIT_IRQ10 equ (1 << 26)
MOS_EVTBIT_IRQ11 equ (1 << 27)
MOS_EVTBIT_IRQ12 equ (1 << 28)
MOS_EVTBIT_IRQ13 equ (1 << 29)
MOS_EVTBIT_IRQ14 equ (1 << 30)
MOS_EVTBIT_IRQ15 equ (1 << 31)
 
 
;**********************************************************
; exit application (syscall -1)
;**********************************************************
 
; exit application
%macro MOS_EXIT 0
mov eax,MOS_SC_EXIT
int 0x40
%endmacro
 
; exit application, smaller version
%macro MOS_EXIT_S 0
xor eax,eax
dec eax
int 0x40
%endmacro
 
 
;**********************************************************
; wait event stuff
; (MOS_SC_WAITEVENT, syscall 10)
;**********************************************************
 
; wait for event
; destroys : nothing
; returns : eax = event type
%macro MOS_WAITEVENT 0
mov eax,MOS_SC_WAITEVENT
int 0x40
%endmacro
 
; wait for event, smaller version
; destroys : flags
; returns : eax = event type
%macro MOS_WAITEVENT_S 0
xor eax,eax
mov al,MOS_SC_WAITEVENT
int 0x40
%endmacro
 
 
;**********************************************************
; window redraw status stuff
; (MOS_SC_REDRAWSTATUS, syscall 12)
;**********************************************************
 
MOS_RS_STARTREDRAW equ 1
MOS_RS_ENDREDRAW equ 2
 
; start window redraw
; destroys: eax,ebx
%macro MOS_STARTREDRAW 0
mov ebx,MOS_RS_STARTREDRAW
mov eax,MOS_SC_REDRAWSTATUS
int 0x40
%endmacro
 
; start window redraw, smaller version
; destroys: eax,ebx,flags
%macro MOS_STARTREDRAW_S 0
xor ebx,ebx
inc ebx
xor eax,eax
mov al,MOS_SC_REDRAWSTATUS
int 0x40
%endmacro
 
; end window redraw
; destroys: eax,ebx
%macro MOS_ENDREDRAW 0
mov ebx,MOS_RS_ENDREDRAW
mov eax,MOS_SC_REDRAWSTATUS
int 0x40
%endmacro
 
; end window redraw, smaller version
; destroys: eax,ebx,flags
%macro MOS_ENDREDRAW_S 0
xor ebx,ebx
mov bl,MOS_RS_ENDREDRAW
xor eax,eax
mov al,MOS_SC_REDRAWSTATUS
int 0x40
%endmacro
 
 
;**********************************************************
; get screen max stuff (syscall 14)
;**********************************************************
 
; get screen dimensions in eax
; destroys: nothing
%macro MOS_GETSCREENMAX 0
mov eax,MOS_SC_GETSCREENMAX
int 0x40
%endmacro
 
; get screen dimensions in eax, smaller version
; destroys: flags
%macro MOS_GETSCREENMAX_S 0
xor eax,eax
mov al,MOS_SC_GETSCREENMAX
int 0x40
%endmacro
 
 
 
%endif
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/pcx.inc
0,0 → 1,137
; pcx.inc
; Copyright (c) 2002 Thomas Mathys
; killer@vantage.ch
;
; This program 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.
;
; This program 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 this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
%ifndef _PCX_INC
%define _PCX_INC
 
 
;**********************************************************
; pcx header
;**********************************************************
 
PCXHEADER_SIZE equ 128
struc PCXHEADER
.id: resb 1 ; id, should be 10
.version: resb 1 ; pcx version
.encoding: resb 1 ; 1 = rle
.bpp: resb 1 ; bits per pixel
.xmin: resw 1 ; image dimensions
.ymin: resw 1
.xmax: resw 1
.ymax: resw 1
.hdpi: resw 1 ; horizontal resolution in dpi
.vdpi: resw 1 ; verttical resolution in dpi
.colormap: resb 48 ; 16 color palette
.reserved1: resb 1
.nplanes: resb 1 ; # of color planes
.bytesperline: resw 1 ; # of bytes per scanline. always even
.palinfo: resw 1 ; 1 = color/bw, 2 = grayscale
.hscreensize: resw 1 ; horizontal screen size
.vscreensize: resw 1 ; vertical screen size
.reserved2: resb 54
endstruc
 
 
section .text
 
 
 
;**********************************************************
; lousy pcx decoder. reads only 8 bit rle packed color images (pcx version 5)
; oh, and yes, currently it can't read images with an odd width.
;
; the routine does not only decode the image data, it converts
; it also to a menuetos putimage compatible format (24 bit, rrggbb)
;
; input : esi address of the pcx file in memory
; edi pointer to the memory where the depacked
; image data should go. (width*height*3 bytes)
; ebx file size in bytes
;
; output : decoded image in [edi]
;
; destroys : nothing
;
;**********************************************************
 
loadPCX:
pushad
pushfd
 
; calculate number of pixels to decode.
; this is actually wrong, because if the image has an odd
; width, there will be an unused pixel at the end of each
; scanline.
movzx eax,word [esi+PCXHEADER.xmax] ; eax = image width
sub ax,[esi+PCXHEADER.xmin]
inc eax
movzx ecx,word [esi+PCXHEADER.ymax] ; ecx = image height
sub cx,[esi+PCXHEADER.ymin]
inc ecx
mul ecx
mov ebp,eax ; ebp = # of pixels to decode
 
; move ebx to beginning of palette and
; esi to beginning of packed image data
sub ebx,768
add ebx,esi
add esi,PCXHEADER_SIZE
; decode image data
xor ecx,ecx ; clear bits 8..31 !
xor eax,eax ; "
.decode:
lodsb ; read byte from input stream
cmp al,192 ; encoded/unencoded byte ?
jae short .encoded
lea edx,[eax*2+eax] ; read color values from
mov al,[ebx+edx+2] ; palette and store them
stosb ; in the destination image
mov al,[ebx+edx+1]
stosb
mov al,[ebx+edx+0]
stosb
dec ebp ; one less to go...
jmp short .continue
.encoded:
and al,00111111b ; calc # of times to repeat
mov cl,al
lodsb ; read data byte
lea edx,[eax*2+eax] ; read color values from palette
mov al,[ebx+edx+2]
mov ah,[ebx+edx+1]
mov dl,[ebx+edx+0]
.bla: ; write color values
stosb
mov [edi],ah
inc edi
mov [edi],dl
inc edi
dec ebp ; one less to go...
loop .bla
xor ah,ah ; reset ah to 0 !
.continue:
or ebp,ebp ; all pixels decoded ?
jnz short .decode
 
popfd
popad
ret
 
 
%endif
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/randomai.inc
0,0 → 1,50
; 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
 
%infdef _RANDOMAI_INC
%define _RANDOMAI_INC
 
section .text
 
 
 
;**********************************************************
; randomaiGetMove
; getmove routine for random "ai" player
;
; input : eax = cpu level (ignored by this player:)
; output : eax = move
; destroys : everything
;**********************************************************
randomaiGetMove
 
.l:
call rand ; get random number in the range [1,7]
xor edx,edx ; !
mov ebx,7
div ebx
inc edx
BOARDISVALIDMOVE edx ; is this a valid move ?
jz .l ; no -> try again
 
mov eax,edx ; return move
ret
 
%endif
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/red.pcx
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/c4/trunk/rng.inc
0,0 → 1,76
; 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 _RNG_INC
%define _RNG_INC
 
section .data
 
 
; random seed
seed dd 0
 
 
 
section .text
 
 
;**********************************************************
; randomize
; initialize random number generator.
; initialization is done using the get system clock syscall
;
; input : nothing
; output : nothing
; destroys : nothing
;**********************************************************
randomize:
push eax
mov eax,MOS_SC_GETSYSCLOCK
int 0x40
mov [seed],eax
pop eax
ret
 
 
 
;**********************************************************
; rand
; return an unsigned 32 bit "random" number
;
; input : nothing
; output : eax = unsigned 32 bit random number
; destroys : nothing
;**********************************************************
rand:
pushfd
push edx
mov eax,32719
mul dword [seed]
add eax,123
xchg al,ah
rol eax,16
xchg al,ah
mov [seed],eax
pop edx
popfd
ret
%endif
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
/programs/c4/trunk/windows.inc
0,0 → 1,356
; windows.inc
; Copyright (c) 2002 Thomas Mathys
; killer@vantage.ch
;
; This program 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.
;
; This program 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 this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
%ifndef _WINDOWS_INC
%define _WINDOWS_INC
 
 
WND_CENTER equ (1 << 0)
WND_DEFAULT_WORKCOLOR equ (1 << 1)
WND_DEFAULT_GRABCOLOR equ (1 << 2)
WND_DEFAULT_FRAMECOLOR equ (1 << 3)
WND_DEFAULT_CAPTIONCOLOR equ (1 << 4)
WND_DEFAULT_COLORS equ (WND_DEFAULT_WORKCOLOR | WND_DEFAULT_GRABCOLOR | WND_DEFAULT_FRAMECOLOR | WND_DEFAULT_CAPTIONCOLOR)
 
 
struc WND
.xposandsize resd 1 ; x position and size (like syscall)
.yposandsize resd 1 ; y position and size (like syscall)
.workcolor resd 1 ; work area color (like syscall)
.grabcolor resd 1 ; grab bar color (like syscall)
.framecolor resd 1 ; frame color (like syscall)
.caption resd 1 ; pointer to caption (zero terminated)
; can be zero, if no caption is desired.
.captioncolor resd 1 ; caption color
.flags resd 1 ; combination of WND_xxx flags, or zero.
endstruc
 
 
BUTTON_COLOR_GRAB equ 0x01000000
BUTTON_COLOR_WORK equ 0x02000000
 
 
struc BUTTON
.xposandsize resd 1 ; x position and size (like syscall)
.yposandsize resd 1 ; y position and size (like syscall)
.id resd 1 ; button id
.color resd 1 ; button color. can be a real color
; or one of the BUTTON_COLOR_xxx constants
endstruc
 
 
LABEL_COLOR_GRABBUTTON equ 0x01000000 ; use grab button text default color
LABEL_COLOR_GRAB equ 0x02000000 ; use grab text default color
LABEL_COLOR_WORKBUTTON equ 0x03000000 ; use work button text default color
LABEL_COLOR_WORK equ 0x04000000 ; use work text default color
LABEL_BGCOLOR_TRANSPARENT equ 0x01000000 ; transparent
LABEL_BGCOLOR_WORK equ 0x02000000 ; use work area color
 
 
struc LABEL
.position resd 1 ; position, x in upper word, y in lower word
.caption resd 1 ; pointer to caption (zero terminated)
; if this is field is zero, the label will
; not be drawn.
.color resd 1 ; text color, or a LABEL_COLOR_xxx constant
.bgcolor resd 1 ; background color, or a LABEL_BGCOLOR_xxx constant
endstruc
 
 
section .text
 
 
;***********************************************************
; draw a window
;
; input: edi = pointer to a WND structure
; output: nothing
; destroys: nothing
; notes: you must call begin redraw/end redraw
; yourself, before and after calling
; this function.
;***********************************************************
drawWindow:
 
%define WNDCOLORS ebp-MOS_WNDCOLORS_size
 
enter MOS_WNDCOLORS_size,0
pushfd
pushad
 
; get default window colors
mov ebx,3
lea ecx,[WNDCOLORS]
mov edx,MOS_WNDCOLORS_size
mov eax,MOS_SC_WINDOWPROPERTIES
int 0x40
 
;
; window position
;
test dword [edi + WND.flags],WND_CENTER ; center window ?
jnz short .center
mov ebx,[edi + WND.xposandsize] ; nope -> just load dimensions
mov ecx,[edi + WND.yposandsize]
jmp short .positionok
.center: ; so let's center this window...
MOS_GETSCREENMAX ; get screen dimensions
mov ebx,eax ; xpos = (screenx-width)/2
shr ebx,16
sub bx,[edi + WND.xposandsize]
jns short .xok
xor ebx,ebx
.xok:
shl ebx,15 ; / 2, move result to hi-word
mov bx,[edi + WND.xposandsize]
movzx ecx,ax ; same for ypos
sub cx,[edi + WND.yposandsize]
jns short .yok
xor ecx,ecx
.yok:
shl ecx,15
mov cx,[edi + WND.yposandsize]
.positionok: ; ebx/ecx contain dimensions
 
;
; colors
;
push edi
mov edx,[edi + WND.workcolor]
test dword [edi + WND.flags],WND_DEFAULT_WORKCOLOR
jz short .workcolorok
and edx,0xff000000
or edx,[WNDCOLORS + MOS_WNDCOLORS.work]
.workcolorok:
mov esi,[edi + WND.grabcolor]
test dword [edi + WND.flags],WND_DEFAULT_GRABCOLOR
jz short .grabcolorok
and esi,0xff000000
or esi,[WNDCOLORS + MOS_WNDCOLORS.grab]
.grabcolorok:
test dword [edi + WND.flags],WND_DEFAULT_FRAMECOLOR
mov edi,[edi + WND.framecolor]
jz short .framecolorok
and edi,0xff000000
or edi,[WNDCOLORS + MOS_WNDCOLORS.frame]
.framecolorok:
 
; define window
mov eax,MOS_SC_DEFINEWINDOW
int 0x40
pop edi
 
;
; caption
;
cmp dword [edi + WND.caption],0 ; is there a caption ?
je short .captionok ; nope -> do nothing
mov ebx,MOS_DWORD(8,8) ; ebx = position
mov edx,[edi + WND.caption] ; edx -> string
push edi ; get string length
mov edi,edx
mov ecx,-1
xor al,al ; scan for zero byte
repne scasb
sub edi,edx
dec edi
mov esi,edi
pop edi ; esi = string length
mov ecx,[edi + WND.captioncolor]
test dword [edi + WND.flags],WND_DEFAULT_CAPTIONCOLOR
jz short .captioncolorok
mov ecx,[WNDCOLORS + MOS_WNDCOLORS.grabText]
.captioncolorok:
mov eax,MOS_SC_WRITETEXT
int 0x40
.captionok:
 
popad
popfd
leave
ret
%undef WNDCOLORS
 
 
;***********************************************************
; draw a bunch of buttons
;
; input: edi = pointer to an array of BUTTON structs
; ecx = # of buttons to draw
; output: nothing
; destroys: nothing
; notes: you must call begin redraw/end redraw yourself
;***********************************************************
 
drawButtons:
 
%define WNDCOLORS ebp-MOS_WNDCOLORS_size
 
or ecx,ecx
jnz short .ok
ret
.ok:
enter MOS_WNDCOLORS_size,0
pushfd
pushad
; get default window colors
push ecx
mov ebx,3
lea ecx,[WNDCOLORS]
mov edx,MOS_WNDCOLORS_size
mov eax,MOS_SC_WINDOWPROPERTIES
int 0x40
pop ecx
.drawall:
push ecx
mov ebx,[edi + BUTTON.xposandsize]
mov ecx,[edi + BUTTON.yposandsize]
mov edx,[edi + BUTTON.id]
mov esi,[edi + BUTTON.color]
cmp esi,BUTTON_COLOR_GRAB ; use a default color ?
jne .ok1
mov esi,[WNDCOLORS + MOS_WNDCOLORS.grabButton]
.ok1:
cmp esi,BUTTON_COLOR_WORK
jne .ok2
mov esi,[WNDCOLORS + MOS_WNDCOLORS.workButton]
.ok2:
mov eax,MOS_SC_DEFINEBUTTON
int 0x40
add edi,BUTTON_size
pop ecx
loop .drawall
popad
popfd
leave
ret
%undef WNDCOLORS
 
 
;***********************************************************
; draw a bunch of labels
;
; input: edi = pointer to an array of LABEL structs
; ecx = # of labels to draw
; output: nothing
; destroys: nothing
;***********************************************************
 
drawLabels:
 
%define WNDCOLORS ebp-MOS_WNDCOLORS_size
 
or ecx,ecx
jnz short .ok
ret
.ok:
enter MOS_WNDCOLORS_size,0
pushfd
pushad
; get default window colors
push ecx
mov ebx,3
lea ecx,[WNDCOLORS]
mov edx,MOS_WNDCOLORS_size
mov eax,MOS_SC_WINDOWPROPERTIES
int 0x40
pop ecx
.drawall:
push ecx
cmp dword [edi + LABEL.caption],0
jne short .notnull
jmp .next
.notnull:
; get caption length
push edi
mov edi,[edi + LABEL.caption]
mov ecx,-1
xor al,al
repne scasb ; search for zero byte
mov esi,edi
pop edi
sub esi,[edi + LABEL.caption]
dec esi ; esi = string length
; clear background, if necessary
cmp dword [edi + LABEL.bgcolor],LABEL_BGCOLOR_TRANSPARENT
je .clearok
mov ebx,[edi + LABEL.position] ; ebx = xstart/width
mov eax,esi ; width = stringlength * 6
mov edx,6
mul edx
mov bx,ax
mov ecx,[edi + LABEL.position] ; ecx = ystart/height
shl ecx,16
mov cx,8
mov edx,[edi + LABEL.bgcolor]
cmp edx,LABEL_BGCOLOR_WORK
jne short .bgcolorok
mov edx,[WNDCOLORS + MOS_WNDCOLORS.work]
.bgcolorok:
mov eax,MOS_SC_DRAWBAR
int 0x40
.clearok:
 
; draw label
mov ebx,[edi + LABEL.position] ; ebx = label position
mov edx,[edi + LABEL.caption] ; edx -> caption
mov ecx,[edi + LABEL.color] ; ecx = color
cmp ecx,LABEL_COLOR_GRABBUTTON
jne short .ok1
mov ecx,[WNDCOLORS + MOS_WNDCOLORS.grabButtonText]
.ok1:
cmp ecx,LABEL_COLOR_GRAB
jne short .ok2
mov ecx,[WNDCOLORS + MOS_WNDCOLORS.grabText]
.ok2:
cmp ecx,LABEL_COLOR_WORKBUTTON
jne short .ok3
mov ecx,[WNDCOLORS + MOS_WNDCOLORS.workButtonText]
.ok3:
cmp ecx,LABEL_COLOR_WORK
jne short .ok4
mov ecx,[WNDCOLORS + MOS_WNDCOLORS.workText]
.ok4:
mov eax,MOS_SC_WRITETEXT
int 0x40
 
.next
add edi,LABEL_size ; next label
pop ecx
dec ecx
jz .done
jmp .drawall
.done:
 
popad
popfd
leave
ret
%undef WNDCOLORS
 
 
%endif
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property