Example #1
0
int main(int argc, const char *argv[])
{
    int rc = 1;
    try 
    {
        LoadIniFile("ttychess.ini");
        TheTerminal.printline();
        TheTerminal.printline(std::string("Teletype chess program (") + ConvertDateToVersion(__DATE__) + ") by Don Cross.");
        TheTerminal.printline("http://cosinekitty.com/chenard");
        while (true)
        {
            ChessBoard board;
            ChessUI_TTY ui;
            ChessGame game(board, ui);
            ui.SetGame(&game);
            game.Play();
            ui.SetGame(NULL);
        }
        rc = 0;
    }
    catch (const char *message)
    {
        TheTerminal.print(message);
        TheTerminal.printline();
    }
    TheTerminal.close();
    return rc;
}
Example #2
0
    virtual ChessPlayer *CreatePlayer(ChessSide side)
    {
        while (humanSide == SIDE_NEITHER)
        {
            TheTerminal.print("Which side do you want to play (w, b, quit)? ");
            std::string choice = TheTerminal.readline();
            if (choice == "w")
            {
                humanSide = SIDE_WHITE;
            }
            else if (choice == "b")
            {
                humanSide = SIDE_BLACK;
            }
            else if (choice == "quit")
            {
                throw "Chess program exited.";
            }
        }

        if (side == humanSide)
        {
            human = new HumanChessPlayer(*this);
            return human;
        }
        else
        {
            computer = new ComputerChessPlayer(*this);
            computer->SetTimeLimit(ComputerThinkTime);
            computer->SetSearchBias(1);
            computer->setResignFlag(false);
            return computer;
        }
    }
Example #3
0
 //--------------------------------------------------------------
 //  Called whenever a player needs to be asked which
 //  piece a pawn should be promoted to.
 //  Must return one of the following values:
 //      Q_INDEX, R_INDEX, B_INDEX, N_INDEX
 //--------------------------------------------------------------
 virtual SQUARE PromotePawn(int pawnDest, ChessSide side)
 {
     while (true)
     {
         TheTerminal.print("Promote pawn to Q, R, N, B? ");
         std::string answer = TheTerminal.readline();
         if (answer == "q")
         {
             return Q_INDEX;
         }
         else if (answer == "r")
         {
             return R_INDEX;
         }
         else if (answer == "n")
         {
             return N_INDEX;
         }
         else if (answer == "b")
         {
             return B_INDEX;
         }
     }
 }
Example #4
0
 //----------------------------------------------------------------
 //  The following member function displays a prompt and waits
 //  for acknowledgement from the user.
 //----------------------------------------------------------------
 virtual void NotifyUser ( const char *message )
 {
     TheTerminal.print(message);
 }
Example #5
0
    void ReallyDrawBoard(const ChessBoard &board)
    {
        // Show the board from the human player's point of view.
        char startFile, startRank;
        int deltaFile, deltaRank;
        if (humanSide == SIDE_WHITE)
        {
            // We draw the board with White (rank 1) at the bottom, so we start with rank 8.
            startFile = 'a';
            startRank = '8';
            deltaFile = +1;
            deltaRank = -1;
        }
        else
        {
            // We draw the board with Black (rank 8) at the bottom, so we start with rank 1.
            startFile = 'h';
            startRank = '1';
            deltaFile = -1;
            deltaRank = +1;
        }

        for (int y=0, rank=startRank; y < 8; ++y, rank += deltaRank)
        {
            TheTerminal.print(static_cast<char>(rank));
            TheTerminal.print("   ");
            for (int x=0, file=startFile; x < 8; ++x, file += deltaFile)
            {
                const SQUARE square = board.GetSquareContents(file - 'a', rank - '1');
                const char *text;
                switch (square)
                {
                case EMPTY:     text = ". ";    break;

                case WPAWN:     text = "WP";    break;
                case WKNIGHT:   text = "WN";    break;
                case WBISHOP:   text = "WB";    break;
                case WROOK:     text = "WR";    break;
                case WQUEEN:    text = "WQ";    break;
                case WKING:     text = "WK";    break;

                case BPAWN:     text = "BP";    break;
                case BKNIGHT:   text = "BN";    break;
                case BBISHOP:   text = "BB";    break;
                case BROOK:     text = "BR";    break;
                case BQUEEN:    text = "BQ";    break;
                case BKING:     text = "BK";    break;

                default:        text = "??";    break;
                }

                TheTerminal.print(text);

                if (x < 7)      // no need for white space at end of line
                {
                    TheTerminal.print("   ");
                }
            }
            TheTerminal.printline();
            TheTerminal.printline();
        }

        // Print file letters at the bottom.
        TheTerminal.print("    ");
        for (int x=0, file=startFile; x < 8; ++x, file += deltaFile)
        {
            TheTerminal.print(static_cast<char>(file));
            if (x < 7)      // no need for white space at end of line
            {
                TheTerminal.print("    ");
            }
        }
        TheTerminal.printline();
        TheTerminal.printline();
    }
Example #6
0
    //----------------------------------------------------------------
    //  The following function is called by the ChessGame after
    //  each player moves, so that the move can be displayed
    //  in standard chess notation, if the UI desires.
    //  It is helpful to use the ::FormatChessMove() function
    //  for this purpose.
    //  The parameter 'thinkTime' is how long the player thought
    //  about the move, expressed in hundredths of seconds.
    //
    //  NOTE:  This function is called BEFORE the move
    //  has been made on the given ChessBoard.
    //  This is necessary for ::FormatChessMove() to work.
    //----------------------------------------------------------------
    virtual void RecordMove(ChessBoard &board, Move move, INT32 thinkTime)
    {
        TheTerminal.print(BoolSideName(board.WhiteToMove()));
        TheTerminal.print(" move #");
        TheTerminal.printInteger((board.GetCurrentPlyNumber()/2) + 1);
        TheTerminal.print(": ");

        int source, dest;
        SQUARE prom = move.actualOffsets(board, source, dest);
        char sourceFile = XPART(source) - 2 + 'a';
        char sourceRank = YPART(source) - 2 + '1';
        char destFile   = XPART(dest)   - 2 + 'a';
        char destRank   = YPART(dest)   - 2 + '1';
        TheTerminal.print(sourceFile);
        TheTerminal.print(sourceRank);
        TheTerminal.print(destFile);
        TheTerminal.print(destRank);
        if (prom)
        {
            char pchar = '?';
            int pindex = UPIECE_INDEX(prom);
            switch (pindex)
            {
                case Q_INDEX:   pchar = 'Q';    break;
                case R_INDEX:   pchar = 'R';    break;
                case B_INDEX:   pchar = 'B';    break;
                case N_INDEX:   pchar = 'N';    break;
            }
            TheTerminal.print(pchar);
        }

        // Temporarily make the move, so we can display what the board
        // looks like after the move has been made.
        // We also use this to determine if the move causes check,
        // checkmate, stalemate, etc.
        UnmoveInfo unmove;
        board.MakeMove(move, unmove);

        // Report check, checkmate, draws.
        bool inCheck = board.CurrentPlayerInCheck();
        bool canMove = board.CurrentPlayerCanMove();
        if (canMove)
        {
            if (inCheck)
            {
                TheTerminal.print('+');
            }
        }
        else
        {
            // The game is over!
            if (inCheck)
            {
                if (board.WhiteToMove())
                {
                    // White just got checkmated.
                    TheTerminal.print("# 0-1");
                }
                else
                {
                    // Black just got checkmated.
                    TheTerminal.print("# 1-0");
                }
            }
            else
            {
                // The game is a draw (could be stalemate, could be by repetition, insufficient material, ...)
                TheTerminal.print(" 1/2-1/2");
            }
        }

        TheTerminal.printline();

        // Unmake the move, because the caller will make the move itself.
        board.UnmakeMove(move, unmove);
    }
Example #7
0
    //--------------------------------------------------------------
    //  The following function should return true if the Move
    //  was read successfully, or false to abort the game.
    //  The move does not have to be legal; if an illegal move
    //  is returned, the caller will repeatedly call until a
    //  legal move is obtained.
    //--------------------------------------------------------------
    virtual bool ReadMove ( 
        ChessBoard  &board, 
        int         &source, 
        int         &dest, 
        SQUARE      &promPieceIndex )   // set to 0 (P_INDEX) if no promotion, or call to PromotePawn is needed; set to N_INDEX..Q_INDEX to specify promotion.
    {
        promPieceIndex = P_INDEX;

        bool boardWasAlreadyPrinted = AutoPrintBoard;

        // accept either of the following two formats: e2e4, g7g8q
        while (true)
        {
            if (IsFirstPrompt)
            {
                IsFirstPrompt = false;
                TheTerminal.printline("Enter 'help' for info and more options.");
            }
            TheTerminal.print("Your move? ");
            std::string line = TheTerminal.readline();

            // =================================================================
            // REMEMBER:  Update "PrintHelp()" every time you add a command!
            // =================================================================

            if (line == "board")
            {
                ReallyDrawBoard(board);
                boardWasAlreadyPrinted = true;
            }
            else if (line == "help")
            {
                PrintHelp();
            }
            else if (line == "new")
            {                
                if (human)
                {
                    human->SetQuitReason(qgr_startNewGame);     // suppress saying that the player resigned
                }
                return false;   // Start a new game.
            }
            else if (line == "quit")
            {
                throw "Chess program exited.";
            }
            else if (line == "show")
            {
                AutoPrintBoard = true;
                if (!boardWasAlreadyPrinted)
                {
                    ReallyDrawBoard(board);
                    boardWasAlreadyPrinted = true;
                }
            }
            else if (line == "swap")
            {
                if (game)
                {
                    humanSide = OppositeSide(humanSide);
                    if (humanSide == SIDE_WHITE)
                    {
                        game->SetPlayers(human, computer);
                    }
                    else
                    {
                        game->SetPlayers(computer, human);
                    }
                    TheTerminal.print("You are now playing as ");
                    TheTerminal.print(SideName(humanSide));
                    TheTerminal.printline(".");

                    source = 0;
                    dest = SPECIAL_MOVE_NULL;
                    return true;
                }
            }
            else if (line == "time")
            {
                // Adjust computer's think time.
                TheTerminal.print("The computer's max think time is now ");
                TheTerminal.printChessTime(ComputerThinkTime);
                TheTerminal.printline(".");
                TheTerminal.print("Enter new think time (0.1 .. 600): ");
                std::string line = TheTerminal.readline();
                double thinkTime = atof(line.c_str());
                if ((thinkTime >= 0.1) && (thinkTime < 600.0))
                {
                    ComputerThinkTime = static_cast<int>(100.0*thinkTime + 0.5);    // round seconds to integer centiseconds
                    if (computer)
                    {
                        computer->SetTimeLimit(ComputerThinkTime);
                    }
                }
                else
                {
                    TheTerminal.printline("Invalid think time - ignoring.");
                }
            }
            else
            {
                if (ParseFancyMove(line.c_str(), board, source, dest, promPieceIndex))
                {
                    return true;
                }
            }
        }
    }
Example #8
0
int main() {
        Terminal term;
        term.enterAltScreen().enableMouse().placeCursor(50, 50);
        term.setWrapAround(true);
        term
                //.setForeground(Color::BLACK)
                //.setBackground(Color::GREEN)
                .clear();
        term.fillRectangle(50, 8, 60, 10, 'X');
        term.placeCursor(term.columns() / 2, term.rows() - 1).print("[HELLO WORLD TOP]");
        term.placeCursor(term.columns() / 2, 0).print("[HELLO WORLD BOTTOM]");
        term.placeCursor(5, 5);
        term.print("Hello %d, %d", term.rows(), term.columns());
        bool run = true;
        while (run) {
                switch (term.await()) {
                        case EventType::KEY:
                                switch (term.lastKey()) {
                                        case Key::UP: term.moveCursor(0, 1); break;
                                        case Key::DOWN: term.moveCursor(0, -1); break;
                                        case Key::LEFT: term.moveCursor(-1, 0); break;
                                        case Key::RIGHT: term.moveCursor(1, 0); break;
                                        case Key::F1: term.setForeground(Color::RED).print("F1"); break;
                                        case Key::F2: term.setForeground(Color::GREEN).print("F2"); break;
                                        case Key::F3: term.setForeground(Color::YELLOW).print("F3"); break;
                                        case Key::F4: term.setForeground(Color::BLUE).print("F4"); break;
                                        case Key::F5: term.setForeground(Color::MAGENTA).print("F5"); break;
                                        case Key::F6: term.setForeground(Color::CYAN).print("F6"); break;
                                        case Key::F7: term.setForeground(Color::WHITE).print("F7"); break;
                                        case Key::F8: term.setForeground(Color::RED).print("F8"); break;
                                        case Key::F9: term.setForeground(Color::GREEN).print("F9"); break;
                                        case Key::F10: term.setForeground(Color::YELLOW).print("F10"); break;
                                        case Key::F11: term.setForeground(Color::BLUE).print("F11"); break;
                                        case Key::F12: term.setForeground(Color::MAGENTA).print("F12"); break;
                                        default: break;
                                }
                                break;
                       case EventType::CHAR:
                               {
                                       uint32_t c = term.lastCharacter();
                                       if (c == 3 || c == 4) run = false;
                                       if (c == 'A') term.placeCursorAtColumn(term.columns() - 1);
                                       else if (c == '|') term.setCursorStyleBar();
                                       else if (c == 'B') term.setCursorStyleBlock();
                                       else if (c == 'C') term.clear().placeCursor(40, 5).setTitle("CLEARED");
                                       else if (c == 'D') term.deleteLines(2);
                                       else if (c == 'E') term.deleteCells(1);
                                       else if (c == 'U') term.clear()
                                                          .placeCursor(5, 5).print("Just one combining:  \u0302")
                                                          .placeCursor(5, 6).print("'o' followed by combining: o\u0302")
                                                          .placeCursor(5, 7).print("'o' followed by combining, then go back and replace: o\u0302").moveCursor(-1,0).print("U")
                                                          .placeCursor(5, 8).print("'o' last column followed by combining:").placeCursor(term.columns() - 1, 8).print("o\u0302")
                                                          .placeCursor(5,  9).print("'ou', then back and combining: ou").moveCursor(-1, 0).print("\u0302")
                                                          .placeCursor(5, 10).print("Double-width and combining: 枝").print("\u0302")
                                                          .placeCursor(5, 11).print("Double, back 1 and combining: 枝").moveCursor(-1, 0).print("\u0302")
                                                          .placeCursor(5, 12).print("Double, back 2 and combining: 枝").moveCursor(-2, 0).print("\u0302")
                                                          .placeCursor(5, 13).print("枝").placeCursorAtColumn(45).placeCursorAtColumn(41).print("\u0302")
                                                          .placeCursor(5, 14).print("Double-width, back 2 and a: '枝'").moveCursor(-3, 0).print("a")
                                                          .placeCursor(5, 15).print("Double-width, back 1 and a: '枝'").moveCursor(-2, 0).print("a")
                                                          .placeCursor(5, 16).print("Double-width in last col:").placeCursorAtColumn(term.columns()-1).print("枝")
                                                          .placeCursor(5, 17).print("Single-width in last col:").placeCursorAtColumn(term.columns()-1).print("a")
                                                          .placeCursor(5, 18).print("Combining in first col <=").placeCursorAtColumn(0).print("\u0302")
                                                          .placeCursor(5, 19).print("a to last column and combining:").placeCursorAtColumn(term.columns()-1).print("a\u0302")
                                                          .placeCursor(5, 20);
                                       else if (c == 'R') term.resetColorsAndStyle();
                                       else if (c >= '0' && c <= '9') term.setBackground(Color(int(Color::BLACK) + (c - '0')));
                                       else if (c == 'F') term.print("枝");
                                       else if (c == 'I') term.placeCursorAtColumn(0);
                                       else if (c == 'L') term.insertLines(2);
                                       else if (c == 'W') term.setWrapAround(false);
                                       else if (c == 'X') term.erase(2);
                                       else if (c == 'Z') term.print("\u0302");
                                       else if (c == '_') term.setCursorStyleUnderline();
                                       else term.print("%c",(char) c);
                               }
                               break;
                       case EventType::RESIZE:
                               term.setTitle("RESIZE %d,%d", term.columns(), term.rows()).clear().placeCursor(term.columns()/2, 0);
                               break;
                       case EventType::TIMEOUT:
                               term.print("TIMEOUT ");
                               break;
                       case EventType::MOUSE_DOWN:
                       case EventType::MOUSE_UP:
                               term.placeCursor(term.lastMouseColumn(), term.lastMouseRow());
                               //term.fillRectangle(term.lastMouseColumn(), term.lastMouseRow(), term.lastMouseColumn()+10, term.lastMouseRow()+3, 'X');
                               break;
                       default:
                               break;
               }
        }
        return 0;
}