From 75e946d9eea79f76cc1332f3e3bcb5d14cb6c398 Mon Sep 17 00:00:00 2001 From: LinlyBoi Date: Fri, 5 May 2023 15:56:43 +0300 Subject: [PATCH] Cleaned up commented code, get_wins and get_streaks are now separate :D --- src/gamedata/heuristic.rs | 129 +++++++++++++++++++++++++++++--------- 1 file changed, 100 insertions(+), 29 deletions(-) diff --git a/src/gamedata/heuristic.rs b/src/gamedata/heuristic.rs index 45f7946..a16b44c 100644 --- a/src/gamedata/heuristic.rs +++ b/src/gamedata/heuristic.rs @@ -2,7 +2,7 @@ use array2d::Array2D; use super::{ dec_both, dec_col, dec_inc, dec_row, inc_both, inc_col, inc_dec, inc_row, - score_checkers::{get_legal_moves, variant_eq, Direction}, + score_checkers::{flip_direction, get_legal_moves, variant_eq, Direction}, Board, Disk, }; //multipliers @@ -15,7 +15,7 @@ const MAX_WINS: i32 = 17; pub fn get_score(board: &Board, disk: Disk) -> i32 { //this should be summing up a bunch of functions defined below this one - let sequences = get_dups(&board.columns, &disk); + let sequences = get_streaks(&board.columns, &disk); let score: i32 = match disk { Disk::RED => board.red_score - board.blu_score, Disk::BLU => board.blu_score - board.red_score, @@ -24,18 +24,18 @@ pub fn get_score(board: &Board, disk: Disk) -> i32 { potential_streaks(&sequences, &disk) + potential_wins(&sequences, &disk) + score * SCORE_DIFF } fn potential_wins(sequences: &Vec>, _disk: &Disk) -> i32 { - let mut count: i32 = 0; - for win in sequences { - if win - .iter() - .filter(|&_disk| variant_eq(_disk, &Disk::EMPTY)) - .count() - == 1 - && win.len() == 4 - { - count += 1; - } - } + let count: i32 = sequences.iter().count() as i32; + // for win in sequences { + // if win + // .iter() + // .filter(|&_disk| variant_eq(_disk, &Disk::EMPTY)) + // .count() + // == 1 + // && win.len() == 4 + // { + // count += 1; + // } + // } match count { 1 => POT_WIN, _ => POT_WINS * count, @@ -60,28 +60,77 @@ fn potential_streaks(sequences: &Vec>, _disk: &Disk) -> i32 { _ => POT_STREAKS * streaks as i32, } } -fn get_dups(board: &Array2D, player_disk: &Disk) -> Vec> { - let mid_indices: Vec<(usize, usize)> = board +fn get_streaks(board: &Array2D, player_disk: &Disk) -> Vec> { + let empty_indices: Vec<(usize, usize)> = board .indices_row_major() .filter(|&index| variant_eq(board.get(index.0, index.1).expect(""), &Disk::EMPTY)) .collect(); - let mut dups: Vec> = vec![]; - for index in mid_indices { + //TODO rename this variable + let mut streaks: Vec> = vec![]; + for index in empty_indices { let moves = get_legal_moves(&index, (board.num_rows(), board.num_columns())); for direction in moves { - let poopy = heur_scan(&board, &index, direction.clone(), 4, *player_disk); + let mut sequence = heur_scan(&board, &index, direction.clone(), 4, *player_disk); //dbg!(&index, &direction, &poopy); - match poopy + match sequence .iter() .filter(|&disk| variant_eq(disk, player_disk)) .count() { - 3 | 2 => dups.push(poopy), + 2 => streaks.push(sequence), _ => {} } } } - dups + streaks +} +fn get_wins(board: &Array2D, player_disk: &Disk) -> Vec> { + let empty_indices: Vec<(usize, usize)> = board + .indices_row_major() + .filter(|&index| variant_eq(board.get(index.0, index.1).expect(""), &Disk::EMPTY)) + .collect(); + let mut wins: Vec> = vec![]; + for index in empty_indices { + let moves = get_legal_moves(&index, (board.num_rows(), board.num_columns())); + for direction in moves { + let mut win: Vec = Vec::with_capacity(4); + win.append(&mut heur_scan( + &board, + &index, + direction.clone(), + 4, + *player_disk, + )); + match win + .iter() + .filter(|&disk| variant_eq(disk, player_disk)) + .count() + { + 3 => wins.push(win), + 2 => { + for i in 1..win.len() - 1 { + if !variant_eq(player_disk, &win[i]) { + win.remove(i); + } + } + let opp_direction = flip_direction(direction.clone()); + let mut opp_sequence = heur_scan( + &board, + &index, + opp_direction, + (4 - win.len() + 1) as i32, + *player_disk, + ); + opp_sequence.remove(0); + win.append(&mut opp_sequence); + dbg!(&win); + wins.push(win); + } + _ => {} + } + } + } + wins } fn heur_scan( @@ -174,24 +223,46 @@ fn heur_scan( //Tests because I am making everything public //TODO separate module here #[test] -fn heuristic_test_1() { +fn streak_test_1() { let mut board = Board::default(); board.play(Disk::BLU, 3); board.play(Disk::BLU, 3); board.play(Disk::BLU, 3); board.play(Disk::BLU, 2); board.play(Disk::BLU, 1); - let sequences = get_dups(&board.columns, &Disk::BLU); - assert_eq!(16, potential_wins(&sequences, &Disk::BLU)); + let sequences = get_streaks(&board.columns, &Disk::BLU); assert_eq!(18, potential_streaks(&sequences, &Disk::BLU)); board.play(Disk::BLU, 0); - let sequences = get_dups(&board.columns, &Disk::BLU); - assert_eq!(5, potential_wins(&sequences, &Disk::BLU)); + let sequences = get_streaks(&board.columns, &Disk::BLU); board.play(Disk::BLU, 3); board.play(Disk::BLU, 3); board.play(Disk::BLU, 3); board.play(Disk::BLU, 3); - let sequences = get_dups(&board.columns, &Disk::BLU); - assert_eq!(0, potential_wins(&sequences, &Disk::BLU)); + let sequences = get_streaks(&board.columns, &Disk::BLU); assert_eq!(12, potential_streaks(&sequences, &Disk::BLU)); } +#[test] +fn win_test_flipping() { + let mut board = Board::default(); + board.play(Disk::BLU, 3); + board.play(Disk::RED, 4); + board.play(Disk::BLU, 4); + board.play(Disk::RED, 5); + board.play(Disk::RED, 5); + board.play(Disk::RED, 6); + board.play(Disk::RED, 6); + board.play(Disk::RED, 6); + board.play(Disk::BLU, 6); + let sequences = get_wins(&board.columns, &Disk::BLU); + dbg!(&sequences); + assert_eq!(POT_WIN, potential_wins(&sequences, &Disk::BLU)); +} +#[test] +fn win_test_flipping_hard() { + let mut board = Board::default(); + board.play(Disk::BLU, 1); + board.play(Disk::BLU, 2); + board.play(Disk::BLU, 4); + let sequences = get_wins(&board.columns, &Disk::BLU); + assert_eq!(POT_WIN, potential_wins(&sequences, &Disk::BLU)); +}