Ethan du Toit 1 year ago
parent
commit
de2c0557d1
  1. 287
      src/main.rs

287
src/main.rs

@ -1,8 +1,12 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
use bitvec::prelude::*; use bitvec::prelude::*;
use core::fmt;
use rand::prelude::*; use rand::prelude::*;
use rand::seq::SliceRandom;
use std::cmp::max; use std::cmp::max;
use std::collections::HashMap;
use std::convert::TryInto;
use std::io; use std::io;
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
@ -19,6 +23,23 @@ struct Card {
rank: u8, // 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A <- 2 is 0, ... A is 12 rank: u8, // 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A <- 2 is 0, ... A is 12
} }
impl fmt::Display for Card {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let rank: String = if self.rank == 12 {
"A".to_string()
} else if self.rank == 11 {
"K".to_string()
} else if self.rank == 10 {
"Q".to_string()
} else if self.rank == 9 {
"J".to_string()
} else {
(self.rank + 2).to_string()
};
write!(f, "{} {:?}", rank, self.suit)
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct GameState { struct GameState {
player: u8, player: u8,
@ -39,6 +60,133 @@ struct Node {
state: GameState, state: GameState,
outcomes: [Option<Box<Node>>; 52], outcomes: [Option<Box<Node>>; 52],
} }
fn printHand(state: &GameState) {
let mut hand_clone = state.hand.clone();
hand_clone.sort_by_key(|x| match (x) {
Some(card) => cardToNum(*card),
None => 255,
});
for card in hand_clone {
match card {
Some(real_card) => println!("{}", real_card),
None => {}
}
}
}
fn deal(human: usize, trump: Option<Suit>) {
match trump {
Some(x) => println!("The trump is {:?}", x),
None => println!("There is no trump"),
}
let mut deck: [Card; 52] = (0..52)
.map(numToCard)
.collect::<Vec<Card>>()
.try_into()
.unwrap();
deck.shuffle(&mut thread_rng());
let (half1, half2) = deck.split_at(26);
let (hand0, hand1) = half1.split_at(13);
let (hand2, hand3) = half2.split_at(13);
let the_hands: [&[Card]; 4] = [hand0, hand1, hand2, hand3];
let mut states: [GameState; 4] = the_hands
.iter()
.enumerate()
.map(|(i, hand)| {
let mut opt_hand: [Option<Card>; 13] = [None; 13];
for (card_i, card) in hand.iter().enumerate() {
opt_hand[card_i] = Some(*card);
}
GameState {
player: 0,
handPlayer: i.try_into().unwrap(),
trump,
hand: opt_hand,
ruffs: bitarr!(0; 16),
played: bitarr!(0; 52),
trick: [None, None, None],
tricksWonBy0: 0,
sizes: [13, 13, 13, 13],
}
})
.collect::<Vec<GameState>>()
.try_into()
.unwrap();
let mut player: usize = 0;
let mut ais: [Option<Node>; 4] = [None, None, None, None];
for _turn in 0..52 {
let card_played: Card = if player == human {
// we'll do the other stuff later
printHand(&states[player as usize]);
println!("What do you play? ");
readCard()
} else {
let mut node: Node = match &ais[player] {
None => new_node(states[player].clone()),
Some(nnode) => nnode.clone(),
};
for _ in 1..10000 {
let mut hands = hands(&node.state);
let pathcur: (Vec<usize>, &mut Node) = search(&mut node, &mut hands); //search!
let path = pathcur.0;
let cur = pathcur.1;
let n: i8;
if cur.state.played.count_ones() == 52 {
let tricks0: u8 = cur.state.tricksWonBy0;
n = if cur.state.handPlayer == 0 || cur.state.handPlayer == 2 {
max(tricks0 as i8 - 6, 0) - max(7 - tricks0 as i8, 0)
} else {
max(7 - tricks0 as i8, 0) - max(tricks0 as i8 - 6, 0)
}
} else {
cur.outcomes[path[path.len() - 1]] = Some(Box::new(new_node(state_transit(
&cur.state,
numToCard(path[path.len() - 1] as u8),
)))); //expand!
n = simulate(
&(*cur.outcomes[path[path.len() - 1]].as_ref().unwrap()).state,
&mut hands,
);
//simulate!
}
propagate(&mut node, path, n);
}
let mut highest_value = -4000.0;
let mut best_move = 100;
for i in 0..52 {
match &node.outcomes[i] {
None => (),
Some(x) => {
if x.value as f64 / x.visited as f64 > highest_value {
highest_value = x.value as f64 / x.visited as f64;
best_move = i;
}
}
}
}
ais[player] = Some(node);
println!("{} played {}!", player, numToCard(best_move as u8));
numToCard(best_move as u8)
};
for i in 0..4 {
match &ais[i] {
Some(node) => match &node.outcomes[cardToNum(card_played) as usize] {
None => {
ais[i] = Some(new_node(state_transit(&node.state, card_played)));
}
Some(x) => {
ais[i] = Some((**x).clone());
}
},
None => {}
}
states[i] = state_transit(&states[i], card_played);
}
player = states[0].player as usize;
}
}
fn rankOf(c: Card) -> u8 { fn rankOf(c: Card) -> u8 {
c.rank c.rank
} }
@ -238,7 +386,7 @@ fn hands(state: &GameState) -> [Vec<u8>; 4] {
let mut running = 0; let mut running = 0;
while n_to_assign > 0 { while n_to_assign > 0 {
let mut any_done = false; let mut any_done = false;
/* for i in 0..52 { /* for i in 0..52 {
if seen[i] { if seen[i] {
continue; continue;
} }
@ -260,8 +408,8 @@ fn hands(state: &GameState) -> [Vec<u8>; 4] {
any_done = true; any_done = true;
} }
} */ } */
any_done = false; any_done = false;
for i in 0..4 { for i in 0..4 {
if sizes[i] > 0 && n_assignable_to[i] == sizes[i] { if sizes[i] > 0 && n_assignable_to[i] == sizes[i] {
for j in 0..52 { for j in 0..52 {
@ -326,7 +474,7 @@ fn search<'a>(node: &'a mut Node, hands: &mut [Vec<u8>; 4]) -> (Vec<usize>, &'a
cur.visited += 1; cur.visited += 1;
if cur.state.played.count_ones() == 52 { if cur.state.played.count_ones() == 52 {
// abort // abort
// no need to do anything with hands // no need to do anything with hands
return (seen, cur); return (seen, cur);
} }
let mut score: f64 = -10000.0; let mut score: f64 = -10000.0;
@ -349,13 +497,13 @@ fn search<'a>(node: &'a mut Node, hands: &mut [Vec<u8>; 4]) -> (Vec<usize>, &'a
match &cur.outcomes[usize::from(*i)] { match &cur.outcomes[usize::from(*i)] {
None => { None => {
seen.push((*i).into()); seen.push((*i).into());
let mut new : Vec<u8> = vec![]; let mut new: Vec<u8> = vec![];
for k in &hands[usize::from(cur.state.player)] { for k in &hands[usize::from(cur.state.player)] {
if *k != (*i) { if *k != (*i) {
new.push(*k) new.push(*k)
} }
} }
hands[usize::from(cur.state.player)] = new; hands[usize::from(cur.state.player)] = new;
return (seen, cur); return (seen, cur);
} }
Some(x) => { Some(x) => {
@ -372,16 +520,16 @@ fn search<'a>(node: &'a mut Node, hands: &mut [Vec<u8>; 4]) -> (Vec<usize>, &'a
None => panic!("This will not happen. SEARCH PANIC KW!#"), None => panic!("This will not happen. SEARCH PANIC KW!#"),
Some(x) => { Some(x) => {
seen.push(idx); seen.push(idx);
let mut new : Vec<u8> = vec![]; let mut new: Vec<u8> = vec![];
for i in &hands[usize::from(cur.state.player)] { for i in &hands[usize::from(cur.state.player)] {
if usize::from(*i) != idx { if usize::from(*i) != idx {
new.push(*i) new.push(*i)
} }
} }
hands[usize::from(cur.state.player)] = new; hands[usize::from(cur.state.player)] = new;
cur = x; //lol cur = x; //lol
} }
} }
//cur.outcomes[idx].clone().unwrap(); //cur.outcomes[idx].clone().unwrap();
@ -403,6 +551,37 @@ fn propagate(node: &mut Node, path: Vec<usize>, value: i8) {
} }
} }
} }
fn readCard() -> Card {
let mut n = String::new();
io::stdin().read_line(&mut n).expect("Input!");
let v: Vec<&str> = n.trim().split(" ").collect();
let suits: HashMap<&str, Suit> = [
("H", Suit::Hearts),
("D", Suit::Diamonds),
("C", Suit::Clubs),
("S", Suit::Spades),
]
.iter()
.cloned()
.collect();
let suit: Suit = suits[v[1]];
let rank: u8;
if v[0] == "A" {
rank = 12;
} else if v[0] == "K" {
rank = 11;
} else if v[0] == "Q" {
rank = 10;
} else if v[0] == "J" {
rank = 9;
} else {
rank = v[0].trim().parse::<u8>().expect("RIGHT") - 2;
}
Card { suit, rank }
}
fn simulate(state: &GameState, hands: &mut [Vec<u8>; 4]) -> i8 { fn simulate(state: &GameState, hands: &mut [Vec<u8>; 4]) -> i8 {
let mut cur: GameState = state.clone(); let mut cur: GameState = state.clone();
loop { loop {
@ -445,15 +624,14 @@ fn simulate(state: &GameState, hands: &mut [Vec<u8>; 4]) -> i8 {
continue; continue;
} }
if random::<u8>() % n == 0 { if random::<u8>() % n == 0 {
p = numToCard(*i); p = numToCard(*i);
let mut new : Vec<u8> = vec![]; let mut new: Vec<u8> = vec![];
for k in &hands[usize::from(cur.player)] { for k in &hands[usize::from(cur.player)] {
if *k != *i { if *k != *i {
new.push(*k) new.push(*k)
} }
} }
hands[usize::from(cur.player)] = new; hands[usize::from(cur.player)] = new;
break; break;
} else { } else {
@ -467,45 +645,43 @@ fn simulate(state: &GameState, hands: &mut [Vec<u8>; 4]) -> i8 {
} }
fn main() { fn main() {
deal(0, Some(Suit::Hearts));
let mut played = bitarr!(0; 52); let mut played = bitarr!(0; 52);
played.set(12, true);
played.set(1, true);
played.set(0, true);
let mut node = new_node(GameState { let mut node = new_node(GameState {
player: 0, player: 0,
handPlayer: 0, handPlayer: 0,
trump: Some(Suit::Hearts), trump: Some(Suit::Hearts),
hand: [ hand: [
Some(card(Suit::Hearts, 0)), Some(card(Suit::Hearts, 5)),
Some(card(Suit::Hearts, 2)), Some(card(Suit::Hearts, 6)),
Some(card(Suit::Hearts, 7)), Some(card(Suit::Hearts, 12)),
Some(card(Suit::Hearts, 8)), Some(card(Suit::Spades, 1)),
Some(card(Suit::Hearts, 9)), Some(card(Suit::Spades, 5)),
Some(card(Suit::Hearts, 10)), Some(card(Suit::Spades, 8)),
Some(card(Suit::Spades, 2)), Some(card(Suit::Spades, 11)),
Some(card(Suit::Spades, 7)), Some(card(Suit::Diamonds, 1)),
Some(card(Suit::Spades, 10)),
Some(card(Suit::Diamonds, 2)), Some(card(Suit::Diamonds, 2)),
Some(card(Suit::Clubs, 1)), Some(card(Suit::Diamonds, 7)),
Some(card(Suit::Clubs, 3)), Some(card(Suit::Clubs, 0)),
Some(card(Suit::Clubs, 7)), Some(card(Suit::Clubs, 7)),
Some(card(Suit::Clubs, 11)),
], ],
ruffs: bitarr!(0; 16), ruffs: bitarr!(0; 16),
played, played,
trick: [ trick: [None, None, None],
Some(card(Suit::Spades, 12)),
Some(card(Suit::Spades, 1)),
Some(card(Suit::Spades, 0)),
],
tricksWonBy0: 0, tricksWonBy0: 0,
sizes: [13, 12, 12, 12], sizes: [13, 13, 13, 13],
}); });
for i in 0..13 {
println!("Give me {i} from your hand");
node.state.hand[i] = Some(readCard());
}
loop { loop {
if node.state.player != node.state.handPlayer { if node.state.player != node.state.handPlayer {
println!("Input the card played by player {}", node.state.player); println!("Input the card played by player {}", node.state.player);
let mut n = String::new(); let card: usize = cardToNum(readCard()).into();
io::stdin().read_line(&mut n).expect("Input!");
let card: usize = n.trim().parse().expect("RIGHT!");
match &node.outcomes[card] { match &node.outcomes[card] {
None => { None => {
node = new_node(state_transit(&node.state, numToCard(card as u8))); node = new_node(state_transit(&node.state, numToCard(card as u8)));
@ -517,7 +693,7 @@ fn main() {
continue; continue;
} }
for _ in 1..10000 { for _ in 1..10000 {
let mut hands = hands(&node.state); let mut hands = hands(&node.state);
let pathcur: (Vec<usize>, &mut Node) = search(&mut node, &mut hands); //search! let pathcur: (Vec<usize>, &mut Node) = search(&mut node, &mut hands); //search!
let path = pathcur.0; let path = pathcur.0;
let cur = pathcur.1; let cur = pathcur.1;
@ -534,7 +710,10 @@ fn main() {
&cur.state, &cur.state,
numToCard(path[path.len() - 1] as u8), numToCard(path[path.len() - 1] as u8),
)))); //expand! )))); //expand!
n = simulate(&(*cur.outcomes[path[path.len() - 1]].as_ref().unwrap()).state, &mut hands); n = simulate(
&(*cur.outcomes[path[path.len() - 1]].as_ref().unwrap()).state,
&mut hands,
);
//simulate! //simulate!
} }
propagate(&mut node, path, n); propagate(&mut node, path, n);

Loading…
Cancel
Save