/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 |