(************************************************************ * PART OF OTHELLO.PAS see file for details **************************************************************) PROCEDURE calcmove( mover: color; VAR status: gamestatus; VAR legallist: movelist; VAR bestmove: movedesc); TYPE movearray = ARRAY[1..30] OF movedesc; VAR bestsofar,cornmoves,m,respcornmoves: INTEGER; move,movetemp: movedesc; aftermove: gamestatus; responses: movelist; PROCEDURE checkposition(VAR legallist: movelist; VAR cornmoves: INTEGER); VAR m,bestm,bestyet: INTEGER; BEGIN bestyet := -MAXINT; cornmoves := 0; FOR m := 1 TO legallist.movecount DO WITH legallist.okmove[m], board[moveloc.row,moveloc.col] DO BEGIN bordnoncorn := FALSE; IF incenter4by4 THEN points := points + 10 ELSE BEGIN IF corner THEN BEGIN points := points + 60; cornmoves := cornmoves + 1; END ELSE IF border THEN BEGIN bordnoncorn := TRUE; points := points + 25; END ELSE IF diagnexttocorner THEN points := points - 50; END; IF points > bestyet THEN BEGIN bestyet := points; bestm := m; end; END; (*FOR m := 1 TO legallist.movecount...*) movetemp := legallist.okmove[1]; legallist.okmove[1] := legallist.okmove[bestm]; legallist.okmove[bestm] := movetemp; END; (*checkposition*) PROCEDURE sortmoves(VAR okmove: movearray; l,r: INTEGER) (*into descending order by points*) ; VAR i,j,baseval: INTEGER; BEGIN i := l; j := r; baseval := okmove[(i+j) DIV 2].points; REPEAT WHILE okmove[i].points > baseval DO i := i+1; WHILE okmove[j].points < baseval DO j := j-1; IF i <= j THEN BEGIN movetemp := okmove[i]; okmove[i] := okmove[j]; okmove[j] := movetemp; i := i+1; j := j-1; END; UNTIL i > j; IF l < j THEN sortmoves(okmove, l, j ); IF i < r THEN sortmoves(okmove, i, r ) END (* sortmoves *) ; PROCEDURE checkresponses(mover: color; VAR move: movedesc; VAR responses: movelist; bestsofar: INTEGER); (*$G+*) LABEL 0; VAR contingent,c,r: INTEGER; x,y: coordinate; sq: squareloc; direc: direction; oppcolor: color; afterresp: gamestatus; cornercounter: BOOLEAN; respondmove: movedesc; counterresp: movelist; BEGIN oppcolor := flipof(mover); WITH move DO BEGIN contingent := 0; r := 1; REPEAT respondmove := responses.okmove[r]; IF NOT board[moveloc.row,moveloc.col].incenter4by4 THEN FOR direc := north TO nw DO WITH respondmove DO IF direc IN dirsflipped THEN WITH moveloc DO IF board[row,col].adjacentsq[direc] = move.moveloc THEN BEGIN move.points := move.points - 5; IF move.points <= bestsofar THEN EXIT(checkresponses); END; afterresp := aftermove; makemove(afterresp,respondmove,FALSE); IF bordnoncorn THEN WITH moveloc DO IF afterresp.boardstatus[row,col].occupier = oppcolor THEN BEGIN bordnoncorn := FALSE; points := points - 65; (*40, plus the 25 given in checkposition*) IF points <= bestsofar THEN EXIT(checkresponses); END ELSE contingent := contingent + 8*respondmove.bordrsqsflipped; WITH respondmove.moveloc DO IF board[row,col].corner THEN BEGIN points := points - 55; IF cornmoves > 1 THEN IF board[moveloc.row,moveloc.col].corner THEN points := points -20; IF points <= bestsofar THEN EXIT(checkresponses); END; FOR x:=1 TO 8 DO FOR y:=1 TO 8 DO WITH afterresp.boardstatus[x,y] DO IF occupied THEN IF occupier = mover THEN FOR direc := north TO nw DO WITH afterresp DO BEGIN sq.row := x; sq.col := y; REPEAT sq := board[sq.row,sq.col].adjacentsq[direc]; IF NOT sq.onboard THEN GOTO 0; IF NOT boardstatus[sq.row,sq.col].occupied THEN GOTO 0 UNTIL boardstatus[sq.row,sq.col].occupier = oppcolor; END; makemove(afterresp,respondmove,TRUE); findlegalmoves(afterresp,counterresp); cornercounter := FALSE; c := 1; WITH counterresp DO WHILE ( (c <= movecount) AND (NOT cornercounter) ) DO BEGIN WITH okmove[c].moveloc DO IF board[row,col].corner THEN cornercounter := TRUE; c := c + 1; END; IF NOT cornercounter THEN BEGIN points := points -190; IF points <= bestsofar THEN EXIT(checkresponses); END; 0: IF afterresp.score[mover] = 0 THEN BEGIN points := -MAXINT+1; (*might be our only choice, so +1*) EXIT(checkresponses); END; r := r + 1; UNTIL r > responses.movecount; IF bordnoncorn THEN BEGIN points := points - contingent; WITH board[moveloc.row,moveloc.col] DO IF specialbordersq THEN WITH otherofpair, status.boardstatus[row,col] DO IF occupied THEN IF occupier = mover THEN WITH status.boardstatus[between.row,between.col] DO IF NOT occupied THEN points := points - 90; END; END; (*WITH move...*) END; (*checkresponses*) BEGIN (*calcmove*) GOTOXY(0,23); WRITE('Calculating move for ',colorword[mover],'...'); checkposition(legallist,cornmoves); IF legallist.movecount > 2 THEN sortmoves(legallist.okmove,2,legallist.movecount); bestsofar := -MAXINT; FOR m := 1 TO legallist.movecount DO BEGIN move := legallist.okmove[m]; aftermove := status; makemove(aftermove,move,TRUE); findlegalmoves(aftermove,responses); WITH move DO BEGIN IF responses.movecount = 0 THEN points := points + 100 ELSE IF points > bestsofar THEN BEGIN checkposition(responses,respcornmoves); checkresponses(mover,move,responses,bestsofar); END; IF points > bestsofar THEN BEGIN bestsofar := points; bestmove := move; END; END; (*WITH move...*) END; (*FOR m := 1 TO legallist.movecount...*) END; (*calcmove*) PROCEDURE play(mover: color); BEGIN GOTOXY(0,20+ORD(mover)); IF legalmoves[mover] > 0 THEN BEGIN WRITE(spaces); IF mover = usercolor THEN inputmove(mover,legallist,move) ELSE calcmove(mover,status,legallist,move); makemove(status,move,TRUE); updatecrt(crtstatus,status); crtstatus := status; END ELSE BEGIN WRITE('(No legal moves for ',colorword[mover],')'); status.nextmover := flipof(mover); END; END; (*play*) FUNCTION userquits: BOOLEAN; VAR playagain: CHAR; BEGIN GOTOXY(0,20); WRITELN(spaces); WRITELN(spaces); WRITELN; WRITE(spaces); GOTOXY(0,23); WRITE('Start a new game? (y/n): '); READ(playagain); userquits := NOT (playagain IN ['Y','y']); END; (*userquits*) .