mirror of
https://github.com/Noratrieb/minmax.git
synced 2026-01-16 08:15:04 +01:00
wrap
This commit is contained in:
parent
5bfabd3cec
commit
6b5347b196
5 changed files with 89 additions and 20 deletions
|
|
@ -27,6 +27,10 @@ impl Connect4 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_pos(&mut self, position: usize, value: Position) {
|
||||||
|
self.positions[position] = value;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn result(&self) -> State {
|
pub fn result(&self) -> State {
|
||||||
match self.check_board() {
|
match self.check_board() {
|
||||||
State::Winner(winner) => State::Winner(winner),
|
State::Winner(winner) => State::Winner(winner),
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ impl Score {
|
||||||
Self(int)
|
Self(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
fn randomize(self) -> Self {
|
fn randomize(self) -> Self {
|
||||||
let score = self.0 as f32;
|
let score = self.0 as f32;
|
||||||
let rand = rand::thread_rng();
|
let rand = rand::thread_rng();
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ impl<G: Game> PerfectPlayer<G> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn best_move(&self) -> G::Move {
|
||||||
|
self.best_move.expect("no move made yet")
|
||||||
|
}
|
||||||
|
|
||||||
fn minmax(&mut self, board: &mut G, player: Player, depth: usize) -> Score {
|
fn minmax(&mut self, board: &mut G, player: Player, depth: usize) -> Score {
|
||||||
if let Some(max_depth) = self.max_depth && depth >= max_depth {
|
if let Some(max_depth) = self.max_depth && depth >= max_depth {
|
||||||
return board.rate(player);
|
return board.rate(player);
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ extern "C" {
|
||||||
/*
|
/*
|
||||||
* Class: ch_bbw_m411_connect4_RustPlayer
|
* Class: ch_bbw_m411_connect4_RustPlayer
|
||||||
* Method: rustPlay
|
* Method: rustPlay
|
||||||
* Signature: (B[Lch/bbw/m411/connect4/Connect4ArenaMain/Stone;)I
|
* Signature: (B[B)I
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jint JNICALL Java_ch_bbw_m411_connect4_RustPlayer_rustPlay
|
JNIEXPORT jint JNICALL Java_ch_bbw_m411_connect4_RustPlayer_rustPlay
|
||||||
(JNIEnv *, jobject, jbyte, jobjectArray);
|
(JNIEnv *, jclass, jbyte, jbyteArray);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,81 @@
|
||||||
// This is the interface to the JVM that we'll call the majority of our
|
use jni::objects::{JClass, JObject, ReleaseMode};
|
||||||
// methods on.
|
|
||||||
use jni::JNIEnv;
|
|
||||||
|
|
||||||
// These objects are what you should use as arguments to your native
|
|
||||||
// function. They carry extra lifetime information to prevent them escaping
|
|
||||||
// this context and getting used after being GC'd.
|
|
||||||
use jni::objects::{JClass, JObject};
|
|
||||||
|
|
||||||
// This is just a pointer. We'll be returning it from our function. We
|
|
||||||
// can't return one of the objects with lifetime information because the
|
|
||||||
// lifetime checker won't let us.
|
|
||||||
use jni::sys::{jbyte, jint};
|
use jni::sys::{jbyte, jint};
|
||||||
|
use jni::JNIEnv;
|
||||||
use minmax::{connect4::board::Connect4, GamePlayer};
|
use minmax::{connect4::board::Connect4, GamePlayer};
|
||||||
|
use minmax::{PerfectPlayer, Player};
|
||||||
|
|
||||||
// 0 -> X
|
/// We need to map the board.
|
||||||
// 1 -> O
|
/// Rust:
|
||||||
pub fn wrap_player<P: GamePlayer<Connect4>>(current_player: i8, board: ()) -> i32 {
|
/// ```text
|
||||||
0
|
/// 0 1 2 3 4 5 6
|
||||||
|
/// 7 8 9 10 11 12 13
|
||||||
|
/// 14 15 16 17 18 19 20
|
||||||
|
/// 21 22 23 24 25 26 27
|
||||||
|
/// ```
|
||||||
|
/// Java:
|
||||||
|
/// ```text
|
||||||
|
/// 21 22 23 24 25 26 27
|
||||||
|
/// 14 15 16 17 18 19 20
|
||||||
|
/// 7 8 9 10 11 12 13
|
||||||
|
/// 0 1 2 3 4 5 6
|
||||||
|
/// ```
|
||||||
|
fn map_idx(i: usize) -> usize {
|
||||||
|
match () {
|
||||||
|
() if i < 7 => i + 21,
|
||||||
|
() if i < 15 => i + 7,
|
||||||
|
() if i < 21 => i - 7,
|
||||||
|
() => i - 21,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn crate_board(java_board: &[i8]) -> Connect4 {
|
||||||
|
let mut board = Connect4::new();
|
||||||
|
|
||||||
|
for i in 0..28 {
|
||||||
|
let java_int = java_board[i];
|
||||||
|
let rust_value = match java_int {
|
||||||
|
0 => Some(Player::X),
|
||||||
|
1 => Some(Player::O),
|
||||||
|
2 => None,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let rust_index = map_idx(i);
|
||||||
|
|
||||||
|
board.set_pos(rust_index, rust_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
board
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0 -> BLUE -> X
|
||||||
|
// 1 -> RED -> O
|
||||||
|
// 2 -> empty
|
||||||
|
pub fn wrap_player(env: JNIEnv<'_>, current_player: i8, board: JObject<'_>) -> i32 {
|
||||||
|
let board_size = env.get_array_length(board.into_raw()).unwrap();
|
||||||
|
assert_eq!(board_size, 28);
|
||||||
|
|
||||||
|
let byte_array = env
|
||||||
|
.get_byte_array_elements(board.into_raw(), ReleaseMode::NoCopyBack)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let slice = unsafe { std::slice::from_raw_parts(byte_array.as_ptr() as *const _, 28) };
|
||||||
|
|
||||||
|
let mut board = crate_board(slice);
|
||||||
|
|
||||||
|
let mut player = PerfectPlayer::new(false);
|
||||||
|
|
||||||
|
let current_player_rust = match current_player {
|
||||||
|
0 => Player::X,
|
||||||
|
1 => Player::O,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
player.next_move(&mut board, current_player_rust);
|
||||||
|
|
||||||
|
let result_move = player.best_move();
|
||||||
|
|
||||||
|
map_idx(result_move) as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
// This keeps Rust from "mangling" the name and making it unique for this
|
// This keeps Rust from "mangling" the name and making it unique for this
|
||||||
|
|
@ -27,9 +86,10 @@ pub extern "system" fn Java_ch_bbw_m411_connect4_RustPlayer_rustPlay(
|
||||||
// This is the class that owns our static method. It's not going to be used,
|
// This is the class that owns our static method. It's not going to be used,
|
||||||
// but still must be present to match the expected signature of a static
|
// but still must be present to match the expected signature of a static
|
||||||
// native method.
|
// native method.
|
||||||
class: JClass<'_>,
|
_: JClass<'_>,
|
||||||
player: jbyte,
|
player: jbyte,
|
||||||
board: JObject<'_>,
|
board: JObject<'_>,
|
||||||
) -> jint {
|
) -> jint {
|
||||||
0
|
std::panic::catch_unwind(|| wrap_player(env, player, board))
|
||||||
|
.unwrap_or_else(|_| std::process::abort())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue