home *** CD-ROM | disk | FTP | other *** search
- /* LORD OF HOSTS - moves.c --- Verarbeitung der Spielzüge */
-
- #include "Lord.h"
-
- extern UBYTE whatsonboard[8][8];
- extern UBYTE fval[16][8][8];
- extern UBYTE kval[16][8][8];
- extern struct Piece ThePieces[16];
- extern int status;
-
- struct Move Moves[MAXUNDO];
- int undopos,redotop,undobot,last_error;
-
- int NumPieces[2]= { 8,8 };
-
- int check_move(UBYTE board[][8], struct Piece *Pieces, int Num,
- UBYTE tox, UBYTE toy)
- {
- int i,result=0, value = Pieces[Num].Value;
- UBYTE fromx = Pieces[Num].x ,fromy = Pieces[Num].y,
- base= (Num<8 ? 0 : 8);
- /* Stimmt die Entfernung ? */
- if (ABS(fromx-tox) + ABS(fromy-toy) < value) result = MUST_MOVE_FARTHER;
- if (ABS(fromx-tox) + ABS(fromy-toy) > value) result = DIST_EXCEEDED;
- /* Sitzt am Ende ein eigener Spielstein ? */
- if (whatsonboard[tox][toy] >= base && whatsonboard[tox][toy] <= base+7)
- result |= CANT_BEAT_BUDDY;
- /* Ist der Weg frei ? */
- result |= how_to_move(board,fromx,fromy,tox,toy);
- /* Gerät durch diesen Zug der eigene King in Gefahr ? */
- if (result == MOVE_X_FIRST || result == MOVE_Y_FIRST)
- result |= check_check(board,Pieces,Num,tox,toy);
- return result;
- }
-
- int how_to_move(UBYTE board[][8],
- UBYTE fromx, UBYTE fromy, UBYTE tox, UBYTE toy)
- {
- int xdist = tox-fromx, ydist = toy-fromy,
- xstep = 0, ystep = 0, i;
- BOOL freexfirst = TRUE, freeyfirst = TRUE;
- if (xdist) xstep = xdist / ABS(xdist);
- if (ydist) ystep = ydist / ABS(ydist);
- /* Ohne Abbiegen ? */
- if (!ydist)
- {
- for (i=fromx+xstep; i!=tox; i+=xstep)
- if (board[i][fromy] != NOT_OCCUPIED) freexfirst = FALSE;
- if (freexfirst) return MOVE_X_FIRST; else return WAY_BLOCKED;
- }
- if (!xdist)
- {
- for (i=fromy+ystep; i!=toy; i+=ystep)
- if (board[fromx][i] != NOT_OCCUPIED) freeyfirst = FALSE;
- if (freeyfirst) return MOVE_Y_FIRST; else return WAY_BLOCKED;
- }
- /* Mit Abbiegen */
- /* Geht's, wenn wir zuerst in x-Richtung laufen ? */
- for (i=fromx+xstep; i!=tox+xstep; i+=xstep)
- if (board[i][fromy] != NOT_OCCUPIED) freexfirst = FALSE;
- if (freexfirst)
- for (i=fromy+ystep; i!=toy; i+=ystep)
- if (board[tox][i] != NOT_OCCUPIED) freexfirst = FALSE;
- if (!freexfirst) /* Wenn nicht, geht's dann mit y zuerst ? */
- {
- for (i=fromy+ystep; i!=toy+ystep; i+=ystep)
- if (board[fromx][i] != NOT_OCCUPIED) freeyfirst = FALSE;
- if (freeyfirst)
- for (i=fromx+xstep; i!=tox; i+=xstep)
- if (board[i][toy] != NOT_OCCUPIED) freeyfirst = FALSE;
- }
-
- if (freexfirst) return MOVE_X_FIRST;
- if (freeyfirst) return MOVE_Y_FIRST;
- return WAY_BLOCKED;
- }
-
- int check_check(UBYTE board[][8], struct Piece *Pieces, int Num,
- UBYTE tox, UBYTE toy)
- {
- UBYTE checkboard[8][8], checkx, checky, fromx, fromy;
- int i,j,result,base = (Num<8 ? 0 : 8), value;
- for (i=0; i<=7; ++i)
- for (j=0; j<=7; ++j)
- checkboard[i][j] = board[i][j];
- checkboard[tox][toy] = Num;
- checkboard[Pieces[Num].x][Pieces[Num].y] = NOT_OCCUPIED;
- if (Num != base)
- {
- checkx = Pieces[base].x;
- checky = Pieces[base].y;
- }
- else
- {
- checkx = tox;
- checky = toy;
- }
- j = 8 - base;
- for (i=j; i<=j+7; ++i)
- {
- fromx = Pieces[i].x;
- fromy = Pieces[i].y;
- value = Pieces[i].Value;
- if (Pieces[i].StillAlive == TRUE)
- if (!(fromx == tox && fromy == toy))
- {
- if (ABS(fromx-checkx) + ABS(fromy-checky) == value)
- {
- result = how_to_move(checkboard,fromx,fromy,checkx,checky);
- if (result == MOVE_X_FIRST || result == MOVE_Y_FIRST)
- return KING_IN_DANGER;
- }
- }
- }
- return 0;
- }
-
- int do_move(UBYTE board[][8], struct Piece *Pieces, int Num,
- UBYTE tox, UBYTE toy, BOOL x_first)
- {
- UBYTE fromx = Pieces[Num].x, fromy = Pieces[Num].y,checkvalue;
- int result=0,color,base,p,i,j,r2,beaten;
- SetPiece(Pieces[Num], FALSE, TRUE);/* nicht einblenden, Ausblendfarbe an */
- if (x_first)
- {
- MovePiece(fromx,fromy,tox-fromx,0,TRUE);
- if (toy != fromy) MovePiece(tox,fromy,0,toy-fromy,FALSE);
- }
- else
- {
- MovePiece(fromx,fromy,0,toy-fromy,TRUE);
- if (tox != fromx) MovePiece(fromx,toy,tox-fromx,0,FALSE);
- }
- board[fromx][fromy] = NOT_OCCUPIED;
- beaten = NOBODY;
- if (board[tox][toy] != NOT_OCCUPIED)
- {
- beaten = board[tox][toy];
- result |= ENEMY_KNIGHT_BEATEN;
- Pieces[board[tox][toy]].StillAlive = FALSE;
- color = (Num < 8 ? 1 : 0); /* color = Farbe des Gegners */
- --NumPieces[color];
- if (NumPieces[color] < 3)
- result |= ENEMY_OUT_OF_KNIGHTS; /* Spiel gewonnen */
- }
- board[tox][toy] = Num;
- Pieces[Num].x = tox;
- Pieces[Num].y = toy;
- Pieces[Num].Value = fval[Num][tox][toy];
- SetPiece(Pieces[Num], TRUE, FALSE); /* einblenden, keine Ausblendfarbe */
- /* Moves[] für Undo/Redo setzen */
- Moves[undopos].fromx = fromx;
- Moves[undopos].fromy = fromy;
- Moves[undopos].tox = tox;
- Moves[undopos].toy = toy;
- Moves[undopos].Beaten= beaten;
- Moves[undopos].x_first = x_first;
- Moves[undopos].status = status | WAITING_FOR_PICK;
- Moves[undopos].status &= (~(WAITING_FOR_DEST|WAITING_FOR_CONF));
- /* undopos : Position im Undo/Redo-Puffer
- * redotop : wenn undopos == redotop, dann ist kein Redo möglich
- * undobot : wenn undopos == undobot, dann ist kein Undo möglich */
- undopos = (undopos+1) % MAXUNDO;
- if (undopos == undobot) undobot = (undobot+1) % MAXUNDO;
- redotop = undopos;
- /* Check, ob Check */
- base = (Num < 8 ? 0 : 8);
- tox = Pieces[8-base].x;
- toy = Pieces[8-base].y;
- for (i=base; i<=base+7; ++i)
- {
- fromx=Pieces[i].x;
- fromy=Pieces[i].y;
- if (Pieces[i].StillAlive == TRUE)
- {
- checkvalue = Pieces[i].Value;
- if (checkvalue == 0) checkvalue =kval[i][Pieces[i].x][Pieces[i].y];
- if (ABS(fromx-tox) + ABS(fromy-toy) == checkvalue)
- { /* Pieces[i].Value geht nicht, da er mit
- kval[i][x][y] ausgetauscht sein könnte ! */
- r2 = how_to_move(board,fromx,fromy,tox,toy);
- if (r2 == MOVE_X_FIRST || r2 == MOVE_Y_FIRST)
- result |= ENEMY_KING_BEATABLE;
- }
- }
- }
- /* Check, ob Matt */
- if (result & ENEMY_KING_BEATABLE)
- {
- r2=1;
- for (p = 8-base; p<=15-base && r2 > 0; ++p) /* gegnerische Spielsteine */
- {
- if (Pieces[p].StillAlive)
- {
- for (i=-Pieces[p].Value; i<=Pieces[p].Value && r2 > 0; ++i)
- {
- j=Pieces[p].Value-ABS(i); /* ABS(i)+ABS(j) = Value */
- if (Pieces[p].x+i >=0 && Pieces[p].x+i <=7
- && Pieces[p].y+j >=0 && Pieces[p].y+j <=7)
- {
- r2 = check_move(board,Pieces,p,Pieces[p].x+i,Pieces[p].y+j);
- if (r2 == MOVE_X_FIRST || r2 == MOVE_Y_FIRST)
- r2=-1;
- }
- if (r2 > 0)
- {
- j=-Pieces[p].Value+ABS(i); /* ABS(i)+ABS(j) = Value */
- if (Pieces[p].x+i >=0 && Pieces[p].x+i <=7
- && Pieces[p].y+j >=0 && Pieces[p].y+j <=7)
- {
- r2 = check_move(board,Pieces,p,Pieces[p].x+i,Pieces[p].y+j);
- if (r2 == MOVE_X_FIRST || r2 == MOVE_Y_FIRST)
- r2=-1;
- }
- }
- }
- }
- }
- if (r2 != -1)
- result |= ENEMY_MATED;
- }
- if (result & ENEMY_OUT_OF_KNIGHTS || result & ENEMY_MATED)
- Moves[undopos].GameOver = TRUE;
- else
- Moves[undopos].GameOver = FALSE;
- return result;
- }
-
- BOOL undo(void)
- {
- int Num;
- UBYTE fromx,fromy,tox,toy;
- if (undobot == undopos) return FALSE; /* konnte Undo nicht durchführen */
- --undopos;
- if (undopos < 0) undopos += MAXUNDO; /* wraparound buffer */
-
- fromx = Moves[undopos].tox; /* Undo vertauscht hin und zurück */
- fromy = Moves[undopos].toy;
- tox = Moves[undopos].fromx;
- toy = Moves[undopos].fromy;
- Num = whatsonboard[fromx][fromy];
- SetPiece(ThePieces[Num], FALSE, TRUE);/* nicht einblenden, Ausblendfarbe an */
- if (!Moves[undopos].x_first)
- {
- if (tox != fromx)
- {
- MovePiece(fromx,fromy,tox-fromx,0,TRUE);
- MovePiece(tox,fromy,0,toy-fromy,FALSE);
- }
- else
- MovePiece(fromx,fromy,0,toy-fromy,TRUE);
- }
- else /* x_first == TRUE */
- {
- if (toy != fromy)
- {
- MovePiece(fromx,fromy,0,toy-fromy,TRUE);
- MovePiece(fromx,toy,tox-fromx,0,FALSE);
- }
- else
- MovePiece(fromx,fromy,tox-fromx,0,TRUE);
- }
- ThePieces[Num].x = tox;
- ThePieces[Num].y = toy;
- ThePieces[Num].Value = fval[Num][tox][toy];
- whatsonboard[tox][toy] = Num;
- whatsonboard[fromx][fromy] = NOT_OCCUPIED;
- SetPiece(ThePieces[Num], TRUE, FALSE); /* einblenden, keine Ausblendfarbe */
- if (Moves[undopos].Beaten != NOBODY)
- {
- ThePieces[Moves[undopos].Beaten].StillAlive = TRUE; /* Revival */
- SetPiece(ThePieces[Moves[undopos].Beaten], TRUE, FALSE);
- whatsonboard[fromx][fromy] = Moves[undopos].Beaten;
- NumPieces[(Moves[undopos].Beaten > 7)]++;
- }
- return TRUE;
- }
-
- BOOL redo(void)
- {
- int Num;
- UBYTE fromx,fromy,tox,toy;
- if (redotop == undopos) return FALSE; /* konnte Redo nicht durchführen */
-
- fromx = Moves[undopos].fromx;
- fromy = Moves[undopos].fromy;
- tox = Moves[undopos].tox;
- toy = Moves[undopos].toy;
- Num = whatsonboard[fromx][fromy];
- SetPiece(ThePieces[Num], FALSE, TRUE);/* nicht einblenden, Ausblendfarbe an */
- if (Moves[undopos].x_first)
- {
- MovePiece(fromx,fromy,tox-fromx,0,TRUE);
- if (toy != fromy) MovePiece(tox,fromy,0,toy-fromy,FALSE);
- }
- else
- {
- MovePiece(fromx,fromy,0,toy-fromy,TRUE);
- if (tox != fromx) MovePiece(fromx,toy,tox-fromx,0,FALSE);
- }
- ThePieces[Num].x = tox;
- ThePieces[Num].y = toy;
- ThePieces[Num].Value = fval[Num][tox][toy];
- whatsonboard[tox][toy] = Num;
- whatsonboard[fromx][fromy] = NOT_OCCUPIED;
- SetPiece(ThePieces[Num], TRUE, FALSE); /* einblenden, keine Ausblendfarbe */
- if (Moves[undopos].Beaten != NOBODY)
- {
- ThePieces[Moves[undopos].Beaten].StillAlive = FALSE; /* Wieder tot */
- NumPieces[(Moves[undopos].Beaten>7)]--;
- }
- undopos = (undopos+1) % MAXUNDO; /* wraparound buffer */
- return TRUE;
- }
-
-