make use of dead card discard info
This commit is contained in:
parent
9494d549ae
commit
ea2857a9cd
2 changed files with 46 additions and 25 deletions
|
@ -53,5 +53,5 @@ Currently, on seeds 0-9999, we have:
|
||||||
| 2p | 3p | 4p | 5p |
|
| 2p | 3p | 4p | 5p |
|
||||||
----------|---------|---------|---------|---------|
|
----------|---------|---------|---------|---------|
|
||||||
cheating | 24.8600 | 24.9781 | 24.9715 | 24.9583 |
|
cheating | 24.8600 | 24.9781 | 24.9715 | 24.9583 |
|
||||||
info | 14.981 | 22.526 | 24.516 | 24.742 |
|
info | 15.15 | 22.79 | 24.604 | 24.778 |
|
||||||
|
|
||||||
|
|
|
@ -343,7 +343,7 @@ impl InformationPlayerStrategy {
|
||||||
answer
|
answer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_hint_sum<T>(&self, total_info: u32, view: &T) -> ModulusInformation
|
fn get_hint_sum_info<T>(&self, total_info: u32, view: &T) -> ModulusInformation
|
||||||
where T: GameView
|
where T: GameView
|
||||||
{
|
{
|
||||||
let mut sum = ModulusInformation::new(total_info, 0);
|
let mut sum = ModulusInformation::new(total_info, 0);
|
||||||
|
@ -442,29 +442,33 @@ impl InformationPlayerStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if view.board.is_playable(card) {
|
|
||||||
5 + (5 - (card.value as i32))
|
5 + (5 - (card.value as i32))
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_useless_card(&self, view: &BorrowedGameView, hand: &Vec<CardPossibilityTable>) -> Option<usize> {
|
fn find_useless_cards<T>(&self, view: &T, hand: &Vec<CardPossibilityTable>) -> Vec<usize>
|
||||||
let mut set: HashSet<Card> = HashSet::new();
|
where T: GameView
|
||||||
|
{
|
||||||
|
let mut useless: HashSet<usize> = HashSet::new();
|
||||||
|
let mut seen: HashMap<Card, usize> = HashMap::new();
|
||||||
|
|
||||||
for (i, card_table) in hand.iter().enumerate() {
|
for (i, card_table) in hand.iter().enumerate() {
|
||||||
if card_table.probability_is_dead(view.board) == 1.0 {
|
if card_table.probability_is_dead(view.get_board()) == 1.0 {
|
||||||
return Some(i);
|
useless.insert(i);
|
||||||
}
|
} else {
|
||||||
if let Some(card) = card_table.get_card() {
|
if let Some(card) = card_table.get_card() {
|
||||||
if set.contains(&card) {
|
if seen.contains_key(&card) {
|
||||||
// found a duplicate card
|
// found a duplicate card
|
||||||
return Some(i);
|
useless.insert(i);
|
||||||
}
|
useless.insert(*seen.get(&card).unwrap());
|
||||||
set.insert(card);
|
} else {
|
||||||
|
seen.insert(card, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None
|
}
|
||||||
|
}
|
||||||
|
let mut useless_vec : Vec<usize> = useless.into_iter().collect();
|
||||||
|
useless_vec.sort();
|
||||||
|
return useless_vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn someone_else_can_play(&self, view: &BorrowedGameView) -> bool {
|
fn someone_else_can_play(&self, view: &BorrowedGameView) -> bool {
|
||||||
|
@ -564,7 +568,7 @@ impl InformationPlayerStrategy {
|
||||||
fn get_hint(&self, view: &BorrowedGameView) -> TurnChoice {
|
fn get_hint(&self, view: &BorrowedGameView) -> TurnChoice {
|
||||||
let total_info = 3 * (view.board.num_players - 1);
|
let total_info = 3 * (view.board.num_players - 1);
|
||||||
|
|
||||||
let hint_info = self.get_hint_sum(total_info, view);
|
let hint_info = self.get_hint_sum_info(total_info, view);
|
||||||
|
|
||||||
let hint_type = hint_info.value % 3;
|
let hint_type = hint_info.value % 3;
|
||||||
let player_amt = (hint_info.value - hint_type) / 3;
|
let player_amt = (hint_info.value - hint_type) / 3;
|
||||||
|
@ -699,12 +703,16 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
- (COLORS.len() * VALUES.len()) as u32
|
- (COLORS.len() * VALUES.len()) as u32
|
||||||
- (view.board.num_players * view.board.hand_size);
|
- (view.board.num_players * view.board.hand_size);
|
||||||
|
|
||||||
// TODO: use the useless card discard as information!
|
let public_useless_indices = self.find_useless_cards(view, &self.get_my_public_info());
|
||||||
|
let useless_indices = self.find_useless_cards(view, &private_info);
|
||||||
|
|
||||||
if view.board.discard_size() <= discard_threshold {
|
if view.board.discard_size() <= discard_threshold {
|
||||||
// if anything is totally useless, discard it
|
// if anything is totally useless, discard it
|
||||||
if let Some(i) = self.find_useless_card(view, &private_info) {
|
if public_useless_indices.len() > 1 {
|
||||||
return TurnChoice::Discard(i);
|
let info = self.get_hint_sum_info(public_useless_indices.len() as u32, view);
|
||||||
|
return TurnChoice::Discard(public_useless_indices[info.value as usize]);
|
||||||
|
} else if useless_indices.len() > 0 {
|
||||||
|
return TurnChoice::Discard(useless_indices[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,7 +722,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
if self.someone_else_can_play(view) {
|
if self.someone_else_can_play(view) {
|
||||||
return self.get_hint(view);
|
return self.get_hint(view);
|
||||||
} else {
|
} else {
|
||||||
print!("This actually happened");
|
// print!("This actually happens");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,8 +730,11 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
// infer that we have no playable cards
|
// infer that we have no playable cards
|
||||||
|
|
||||||
// if anything is totally useless, discard it
|
// if anything is totally useless, discard it
|
||||||
if let Some(i) = self.find_useless_card(view, &private_info) {
|
if public_useless_indices.len() > 1 {
|
||||||
return TurnChoice::Discard(i);
|
let info = self.get_hint_sum_info(public_useless_indices.len() as u32, view);
|
||||||
|
return TurnChoice::Discard(public_useless_indices[info.value as usize]);
|
||||||
|
} else if useless_indices.len() > 0 {
|
||||||
|
return TurnChoice::Discard(useless_indices[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play the best discardable card
|
// Play the best discardable card
|
||||||
|
@ -759,6 +770,16 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
}
|
}
|
||||||
TurnChoice::Discard(index) => {
|
TurnChoice::Discard(index) => {
|
||||||
if let &TurnResult::Discard(ref card) = &turn.result {
|
if let &TurnResult::Discard(ref card) = &turn.result {
|
||||||
|
let public_useless_indices = self.find_useless_cards(
|
||||||
|
&self.last_view, &self.get_player_public_info(&turn.player));
|
||||||
|
if public_useless_indices.len() > 1 {
|
||||||
|
// unwrap is safe because *if* a discard happened, and there were known
|
||||||
|
// dead cards, it must be a dead card
|
||||||
|
let value = public_useless_indices.iter().position(|&i| i == index).unwrap();
|
||||||
|
self.update_from_hint_sum(ModulusInformation::new(
|
||||||
|
public_useless_indices.len() as u32, value as u32
|
||||||
|
));
|
||||||
|
}
|
||||||
self.update_public_info_for_discard_or_play(view, &turn.player, index, card);
|
self.update_public_info_for_discard_or_play(view, &turn.player, index, card);
|
||||||
} else {
|
} else {
|
||||||
panic!("Got turn choice {:?}, but turn result {:?}",
|
panic!("Got turn choice {:?}, but turn result {:?}",
|
||||||
|
|
Loading…
Reference in a new issue