<commit_before>/*
 * Copyright (C) 2017-2018 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

pub mod bitboard;
mod board;
mod constants;
pub mod ttable;
mod zobrist;

use std::fmt;
use std::mem;

use glium::glutin::EventsLoopProxy;

use self::bitboard::BitBoard;
pub use self::board::Board;
use ai::AI;

pub struct Model {
    pub board: Board,
    pub players: ColorMap<Player>,
    pub last_move: Option<Move>,
    pub selected_piece: Option<FieldCoord>,
    pub exchanging: bool,
    pub ai: AI,
    pub ai_search_depth: u8,
    pub outcome: Outcome,
    undo_stack: Vec<(Board, Option<Move>, Outcome)>,
    redo_stack: Vec<(Board, Option<Move>, Outcome)>,
    pub events_proxy: EventsLoopProxy,
}

impl Model {
    pub fn new(players: ColorMap<Player>, events_proxy: EventsLoopProxy) -> Self {
        Self {
            board: Board::new(),
            players,
            selected_piece: None,
            last_move: None,
            exchanging: false,
            ai: AI::new(),
            ai_search_depth: 6,
            outcome: Outcome::InProgress,
            undo_stack: vec![],
            redo_stack: vec![],
            events_proxy,
        }
    }
    pub fn can_undo(&self) -> bool {
        self.current_player() != Player::Computer && !self.undo_stack.is_empty()
    }
    pub fn can_redo(&self) -> bool {
        self.current_player() != Player::Computer && !self.redo_stack.is_empty()
    }
    pub fn push_undo_state(&mut self) {
        self.undo_stack
            .push((self.board, self.last_move, self.outcome));
        self.redo_stack.clear();
    }
    pub fn undo_move(&mut self) {
        while let Some((board, last_move, outcome)) = self.undo_stack.pop() {
            self.redo_stack.push((
                mem::replace(&mut self.board, board),
                mem::replace(&mut self.last_move, last_move),
                mem::replace(&mut self.outcome, outcome),
            ));

            self.clear_selection();
            self.exchanging = false;

            if Player::Human == self.players.get(board.turn) {
                break;<commit_msg>Fix undo/redo buttons<commit_after>/*
 * Copyright (C) 2017-2018 <NAME>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

pub mod bitboard;
mod board;
mod constants;
pub mod ttable;
mod zobrist;

use std::fmt;
use std::mem;

use glium::glutin::EventsLoopProxy;

use self::bitboard::BitBoard;
pub use self::board::Board;
use ai::AI;

pub struct Model {
    pub board: Board,
    pub players: ColorMap<Player>,
    pub last_move: Option<Move>,
    pub selected_piece: Option<FieldCoord>,
    pub exchanging: bool,
    pub ai: AI,
    pub ai_search_depth: u8,
    pub outcome: Outcome,
    undo_stack: Vec<(Board, Option<Move>, Outcome)>,
    redo_stack: Vec<(Board, Option<Move>, Outcome)>,
    pub events_proxy: EventsLoopProxy,
}

impl Model {
    pub fn new(players: ColorMap<Player>, events_proxy: EventsLoopProxy) -> Self {
        Self {
            board: Board::new(),
            players,
            selected_piece: None,
            last_move: None,
            exchanging: false,
            ai: AI::new(),
            ai_search_depth: 6,
            outcome: Outcome::InProgress,
            undo_stack: vec![],
            redo_stack: vec![],
            events_proxy,
        }
    }
    pub fn can_undo(&self) -> bool {
        let comp_v_comp =
            self.players.white == Player::Computer && self.players.black == Player::Computer;
        !comp_v_comp && !self.undo_stack.is_empty()
    }
    pub fn can_redo(&self) -> bool {
        let comp_v_comp =
            self.players.white == Player::Computer && self.players.black == Player::Computer;
        !comp_v_comp && !self.redo_stack.is_empty()
    }
    pub fn push_undo_state(&mut self) {
        self.undo_stack
            .push((self.board, self.last_move, self.outcome));
        self.redo_stack.clear();
    }
    pub fn undo_move(&mut self) {
        while let Some((board, last_move, outcome)) = self.undo_stack.pop() {
            self.redo_stack.push((
                mem::replace(&mut self.board, board),
                mem::replace(&mut self.last_move, last_move),
                mem::replace(&mut self.outcome, outcome),
            ));

            self.clear_selection();
            self.exchanging = false;

            if Player::Human == self.players.get(board.turn) {
                break;
{'fraction_non_alphanumeric': 0.11113080467919177, 'fraction_numerical': 0.0038993264799716413, 'mean_word_length': 2.544597989949749, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 29, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6671295', 'n_tokens_mistral': 1695, 'n_tokens_neox': 1646, 'n_words': 511}