void CmdMove(CORE_DATA *cd) { USER_DATA *ud = UD(cd); // the game hasnt started if (ud->in_progress == false) { Reply("The game has not yet begun"); return; } // check for correct arg count if (cd->cmd_argc != 2) { ReplyFmt("Usage: !move Coord,Coord"); ReplyFmt("Example: !move e2,e4"); return; } // make sure the player is playing if (IsPlaying(ud, cd->cmd_name) == false) { Reply("You are not playing in this match"); return; } // replies to players in-game are via arena // check whos turn it is if (GetColor(ud, cd->cmd_name) != ud->to_move) { ArenaMessage("It is not your move"); return; } // parse argument char xstr[3]; char ystr[3]; DelimArgs(xstr, 3, cd->cmd_argv[1], 0, ',', false); DelimArgs(ystr, 3, cd->cmd_argv[1], 1, ',', false); int x1, y1, x2, y2; if (ParseCoords(xstr, &x1, &y1) == true && ParseCoords(ystr, &x2, &y2) == true) { char *err = TryMove(ud, ud->to_move, x1, y1, x2, y2); if (err == NULL && ud->in_progress == true) { // successful moves are announced in TryMove() ud->to_move = GetOppositeColor(ud->to_move); LvzToMove(ud->to_move, NULL); ArenaMessageFmt("%s (%s) to Move", GetPlayerName(ud, ud->to_move), GetColorText(ud->to_move)); } else if (ud->in_progress == true) { ArenaMessageFmt("Couldn't move: %s", err); } } else { ArenaMessageFmt("Invalid coordinates"); } }
void ParseImage( const char* nameFile ) { int width, height; const char syms[][2] = { { 'a', 'z' }, { 'A', 'Z' }, { 'а', 'я' }, { 'А', 'Я' }, { '0', '9' }, { '+', '+' }, { '-', '-' }, { 0, 0 } }; Font* font = InitFont( "Arial", 15, syms ); uchar* img = LoadImage( nameFile, width, height ); //DbgMsg( "%d %d", width, height ); //for( int i = 0; i < 256; i++ ) // DbgMsg( "%d - %d", i, colors[i] ); int colors[2]; int c_color = GetColorText( img, width, height, colors ); //оставляем только нужные цвета int sz = width * height; for( int i = 0; i < sz; i++ ) { int c = 0; for( int j = 0; j < c_color; j++ ) if( img[i] == colors[j] ) { c = 255; break; } img[i] = c; } const int maxRects = 1000; RECT* rects = (RECT*)u_alloc( sizeof(RECT) * maxRects ); int c_rects = GetRectSymbols( img, width, height, rects, maxRects ); /* for( int i = 0; i < c_rects; i++ ) { //DbgMsg( "%d %d %d %d", rects[i].left, rects[i].top, rects[i].right, rects[i].bottom ); int p1 = rects[i].top * width + rects[i].left; int p2 = rects[i].bottom * width + rects[i].left; for( int x = rects[i].left; x <= rects[i].right; x++, p1++, p2++ ) { img[p1] = 128; img[p2] = 128; } p1 = rects[i].top * width + rects[i].left; p2 = rects[i].top * width + rects[i].right; for( int y = rects[i].top; y <= rects[i].bottom; y++, p1 += width, p2 += width ) { img[p1] = 128; img[p2] = 128; } } SaveToBmp( "1_1.bmp", img, width, height ); */ char* chars = u_alloc(c_rects); for( int i = 0; i < c_rects; i++ ) { uint bits[MaxHeightSymbol]; RectToBits( img, width, height, rects[i], bits ); chars[i] = OCRChar( font, bits ); //DbgMsg( "[%c] %d,%d %d,%d", s, rects[i].left, rects[i].top, rects[i].right, rects[i].bottom ); } //объединяем символы в слова Word* words = (Word*)u_alloc( sizeof(Word) * c_rects ); int c_words = UnionChars( rects, chars, c_rects, words ); for( int i = 0; i < c_words; i++ ) DbgMsg( "[%s] %d,%d %d,%d", words[i].w, words[i].r.left, words[i].r.top, words[i].r.right, words[i].r.bottom ); u_free(words); u_free(chars); u_free(rects); u_free(img); ReleaseFont(font); }
/* * TODO: rewrite this to remove duplicated code */ static char* TryCastle(USER_DATA *ud, COLOR c, int x, int y, int dx, int dy) { BOARD b = ud->board; // coordinates were already verified by IsCastleMove() COLOR opp = GetOppositeColor(c); if (IsCoordAttackedBy(b, opp, x, y) == true) { return "Can't castle out of check"; } if (c == COLOR_WHITE) { if (dx == 6) { if (IsCoordAttackedBy(b, opp, 5, 0) || IsCoordAttackedBy(b, opp, 6, 0)) { return "Can't castle through or into check"; } if (GetPieceAt(b, 5, 0)->type != TYPE_NONE || GetPieceAt(b, 6, 0)->type != TYPE_NONE) { return "Can't castle through pieces"; } if (GetPieceAt(b, 7, 0)->type != TYPE_ROOK || GetPieceAt(b, 7, 0)->color != COLOR_WHITE) { return "No rook"; } MoveAndReplaceTarget(ud, b, x, y, dx, dy); MoveAndReplaceTarget(ud, b, 7, 0, 5, 0); ArenaMessageFmt("%s (%s) Moves: Castle kingside", GetPlayerName(ud, c), GetColorText(c)); return NULL; } else if (dx == 2) { // castle queenside if (IsCoordAttackedBy(b, opp, 2, 0) || IsCoordAttackedBy(b, opp, 3, 0)) { return "Can't castle through or into check"; } if (GetPieceAt(b, 1, 0)->type != TYPE_NONE || GetPieceAt(b, 2, 0)->type != TYPE_NONE || GetPieceAt(b, 3, 0)->type != TYPE_NONE) { return "Can't castle through pieces"; } if (GetPieceAt(b, 0, 0)->type != TYPE_ROOK || GetPieceAt(b, 0, 0)->color != COLOR_WHITE) { return "No rook"; } MoveAndReplaceTarget(ud, b, x, y, dx, dy); MoveAndReplaceTarget(ud, b, 0, 0, 3, 0); ArenaMessageFmt("%s (%s) Moves: Castle queenside", GetPlayerName(ud, c), GetColorText(c)); return NULL; } } else if (c == COLOR_BLACK) { if (dx == 6) { // castle kingside if (IsCoordAttackedBy(b, opp, 5, 7) || IsCoordAttackedBy(b, opp, 6, 7)) { return "Can't castle through or into check"; } if (GetPieceAt(b, 5, 7)->type != TYPE_NONE || GetPieceAt(b, 6, 7)->type != TYPE_NONE) { return "Can't castle through pieces"; } if (GetPieceAt(b, 7, 7)->type != TYPE_ROOK || GetPieceAt(b, 7, 7)->color != COLOR_BLACK) { return "No rook"; } MoveAndReplaceTarget(ud, b, x, y, dx, dy); MoveAndReplaceTarget(ud, b, 7, 7, 5, 7); ArenaMessageFmt("%s (%s) Moves: Castle kingside", GetPlayerName(ud, c), GetColorText(c)); return NULL; } else if (dx == 2) { // castle queenside if (IsCoordAttackedBy(b, opp, 2, 7) || IsCoordAttackedBy(b, opp, 3, 7)) { return "Can't castle through or into check"; } if (GetPieceAt(b, 1, 7)->type != TYPE_NONE || GetPieceAt(b, 2, 7)->type != TYPE_NONE || GetPieceAt(b, 3, 7)->type != TYPE_NONE) { return "Can't castle through pieces"; } if (GetPieceAt(b, 0, 7)->type != TYPE_ROOK || GetPieceAt(b, 0, 7)->color != COLOR_BLACK) { return "No rook"; } MoveAndReplaceTarget(ud, b, x, y, dx, dy); MoveAndReplaceTarget(ud, b, 0, 7, 3, 7); ArenaMessageFmt("%s (%s) Moves: Castle queenside", GetPlayerName(ud, c), GetColorText(c)); return NULL; } } else { return "Error castling"; } return "Could not castle"; }
// TODO: Handle en passant static char* TryMove(USER_DATA *ud, COLOR c, int x, int y, int dx, int dy) { BOARD b = ud->board; PIECE *p = GetPieceAt(ud->board, x, y); if (p->type == TYPE_NONE) { return "No piece at that position!"; } else if (p->color != c) { return "That piece is not yours!"; } // check if this move is a castle attempt // TODO: check for rook movements if (p->type == TYPE_KING && IsCastleMove(c, x, y, dx, dy)) { if (ColorCanCastle(ud, c) == false) { return "You can no longer castle"; } return TryCastle(ud, c, x, y, dx, dy); } // check that the piece can make this movement if (PieceCanAttack(ud->board, c, p->type, x, y, dx, dy) == false) { return "Piece can't make that movement"; } // target piece PIECE *t = GetPieceAt(ud->board, dx, dy); if (t->type != TYPE_NONE && t->color == c) { return "You already have a piece in the destination position!"; } // make the movements to check for check, but store the data // in case the board needs to be reverted PIECE old_p = *p; PIECE old_t = *t; SetPieceAt(b, dx, dy, p->color, p->type); SetPieceAt(b, x, y, COLOR_NONE, TYPE_NONE); // find the king and test for check int kingx, kingy; FindKing(b, c, &kingx, &kingy); if (IsCoordAttackedBy(b, GetOppositeColor(c), kingx, kingy) == true) { // restore saved positions SetPieceAt(b, x, y, old_p.color, old_p.type); SetPieceAt(b, dx, dy, old_t.color, old_t.type); return "That move would place your King in check!"; } // // At this point, the move was successful // // make the pieces blink // TODO: this will erroneously leave pieces on if 2 moves // are made quickly uint32_t objid = LvzGetObjId(old_p.color, old_p.type, dx, dy); SetTimer(500, (void*)objid, (void*)0); SetTimer(1000, (void*)objid, (void*)1); SetTimer(1500, (void*)objid, (void*)0); SetTimer(2000, (void*)objid, (void*)1); SetTimer(2500, (void*)objid, (void*)0); SetTimer(3000, (void*)objid, (void*)1); if (old_t.type != TYPE_NONE) { // flash the captured piece objid = LvzGetObjId(old_t.color, old_t.type, dx, dy); SetTimer(500, (void*)objid, (void*)1); SetTimer(1000, (void*)objid, (void*)0); SetTimer(1500, (void*)objid, (void*)1); SetTimer(2000, (void*)objid, (void*)0); SetTimer(2500, (void*)objid, (void*)1); SetTimer(3000, (void*)objid, (void*)0); } if (old_p.type == TYPE_KING) { // kings cant castle once theyve moved if (old_p.color == COLOR_WHITE) { ud->white_can_castle = false; } else if (old_p.color == COLOR_BLACK) { ud->black_can_castle = false; } } // set if a piece has been captured bool capture = old_t.type != TYPE_NONE; // remove drawing of the old pieces LvzActivate(ud, NULL, old_p.color, old_p.type, x, y, false); if (capture) { LvzActivate(ud, NULL, old_t.color, old_t.type, dx, dy, false); } // check for pawn promotions // TODO: handle underpromotions bool promoted = false; p = GetPieceAt(b, dx, dy); if (p->type == TYPE_PAWN) { if (p->color == COLOR_WHITE && dy == 7) { p->type = TYPE_QUEEN; promoted = true; } else if (p->color == COLOR_BLACK && dy == 0) { p->type = TYPE_QUEEN; promoted = true; } } // draw the new piece LvzActivate(ud, NULL, old_p.color, old_p.type, dx, dy, true); objid = LvzGetObjId(old_p.color, old_p.type, dx, dy); // create move notation char move[6]; move[0] = x + 'a'; move[1] = y + '1'; move[2] = ','; move[3] = dx + 'a'; move[4] = dy + '1'; move[5] = '\0'; // announce the move char line[256]; snprintf(line, 256, "%s (%s) Moves: %s", GetPlayerName(ud, c), GetColorText(ud->to_move), move); if (capture) { // add capture line char capture[64]; snprintf(capture, 64, ", capturing a %s!", GetTypeName(old_t.type)); strlcat(line, capture, 256); } if (promoted == true) { // add promition line strlcat(line, " Pawn promoted to Queen!", 256); } FindKing(b, GetOppositeColor(c), &kingx, &kingy); if (IsCoordAttackedBy(b, c, kingx, kingy) == true) { if (IsCheckmatedBy(b, c, kingx, kingy) == true) { strlcat(line, " Checkmate!", 256); ArenaMessage(line); char gametime[32]; TicksToText(gametime, 32, GetTicksMs() - ud->start_tick); StopGame(ud, "%s Wins in %s!", GetPlayerName(ud, c), gametime); } else { strlcat(line, " Check!", 256); ArenaMessage(line); } } else { ArenaMessage(line); } return NULL; }