/* 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; }