bug fixes, added card partitioning. already at average score: 23.91!
This commit is contained in:
parent
adf98e0e4a
commit
e0239dead0
2 changed files with 112 additions and 42 deletions
|
@ -280,6 +280,10 @@ impl CardPossibilityTable {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_determined(&self) -> bool {
|
||||||
|
self.get_possibilities().len() == 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl <'a> From<&'a CardCounts> for CardPossibilityTable {
|
impl <'a> From<&'a CardCounts> for CardPossibilityTable {
|
||||||
fn from(counts: &'a CardCounts) -> CardPossibilityTable {
|
fn from(counts: &'a CardCounts) -> CardPossibilityTable {
|
||||||
|
|
|
@ -47,11 +47,14 @@ impl ModulusInformation {
|
||||||
pub fn emit(&mut self, modulus: u32) -> Self {
|
pub fn emit(&mut self, modulus: u32) -> Self {
|
||||||
assert!(self.modulus >= modulus);
|
assert!(self.modulus >= modulus);
|
||||||
assert!(self.modulus % modulus == 0);
|
assert!(self.modulus % modulus == 0);
|
||||||
|
let original_modulus = self.modulus;
|
||||||
|
let original_value = self.value;
|
||||||
self.modulus = self.modulus / modulus;
|
self.modulus = self.modulus / modulus;
|
||||||
let value = self.value / self.modulus;
|
let value = self.value / self.modulus;
|
||||||
assert!((self.value - value) % modulus == 0);
|
self.value = self.value - value * self.modulus;
|
||||||
self.value = (self.value - value) / modulus;
|
trace!("orig value {}, orig modulus {}, self.value {}, self.modulus {}, value {}, modulus {}",
|
||||||
|
original_value, original_modulus, self.value, self.modulus, value, modulus);
|
||||||
|
assert!(original_value == value * self.modulus + self.value);
|
||||||
Self::new(modulus, value)
|
Self::new(modulus, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,32 +132,83 @@ impl Question for IsPlayable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// struct IsDead {
|
|
||||||
// index: usize,
|
struct IsDead {
|
||||||
// }
|
index: usize,
|
||||||
// impl Question for IsDead {
|
}
|
||||||
// fn info_amount(&self) -> u32 { 2 }
|
impl Question for IsDead {
|
||||||
// fn answer(&self, hand: &Cards, view: &Box<GameView>) -> u32 {
|
fn info_amount(&self) -> u32 { 2 }
|
||||||
// let ref card = hand[self.index];
|
fn answer(&self, hand: &Cards, view: Box<&GameView>) -> u32 {
|
||||||
// if view.get_board().is_dead(card) { 1 } else { 0 }
|
let ref card = hand[self.index];
|
||||||
// }
|
if view.get_board().is_dead(card) { 1 } else { 0 }
|
||||||
// fn acknowledge_answer(
|
}
|
||||||
// &self,
|
fn acknowledge_answer(
|
||||||
// answer: u32,
|
&self,
|
||||||
// hand_info: &mut Vec<CardPossibilityTable>,
|
answer: u32,
|
||||||
// view: &Box<GameView>,
|
hand_info: &mut Vec<CardPossibilityTable>,
|
||||||
// ) {
|
view: Box<&GameView>,
|
||||||
// let ref mut card_table = hand_info[self.index];
|
) {
|
||||||
// let possible = card_table.get_possibilities();
|
let ref mut card_table = hand_info[self.index];
|
||||||
// for card in &possible {
|
let possible = card_table.get_possibilities();
|
||||||
// if view.get_board().is_dead(card) {
|
for card in &possible {
|
||||||
// if answer == 0 { card_table.mark_false(card); }
|
if view.get_board().is_dead(card) {
|
||||||
// } else {
|
if answer == 0 { card_table.mark_false(card); }
|
||||||
// if answer == 1 { card_table.mark_false(card); }
|
} else {
|
||||||
// }
|
if answer == 1 { card_table.mark_false(card); }
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CardPossibilityPartition {
|
||||||
|
index: usize,
|
||||||
|
n_partitions: u32,
|
||||||
|
partition: HashMap<Card, u32>,
|
||||||
|
}
|
||||||
|
impl CardPossibilityPartition {
|
||||||
|
fn new<T>(
|
||||||
|
index: usize, n_partitions: u32, card_table: &CardPossibilityTable, view: &T
|
||||||
|
) -> CardPossibilityPartition where T: GameView {
|
||||||
|
let mut cur_block = 0;
|
||||||
|
let mut partition = HashMap::new();
|
||||||
|
for card in card_table.get_possibilities() {
|
||||||
|
let mut block = cur_block;
|
||||||
|
if view.get_board().is_dead(&card) {
|
||||||
|
block = n_partitions - 1;
|
||||||
|
} else {
|
||||||
|
cur_block = (cur_block + 1) % (n_partitions - 1);
|
||||||
|
}
|
||||||
|
partition.insert(card.clone(), block);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardPossibilityPartition {
|
||||||
|
index: index,
|
||||||
|
n_partitions: n_partitions,
|
||||||
|
partition: partition,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Question for CardPossibilityPartition {
|
||||||
|
fn info_amount(&self) -> u32 { self.n_partitions }
|
||||||
|
fn answer(&self, hand: &Cards, _: Box<&GameView>) -> u32 {
|
||||||
|
let ref card = hand[self.index];
|
||||||
|
*self.partition.get(&card).unwrap()
|
||||||
|
}
|
||||||
|
fn acknowledge_answer(
|
||||||
|
&self,
|
||||||
|
answer: u32,
|
||||||
|
hand_info: &mut Vec<CardPossibilityTable>,
|
||||||
|
_: Box<&GameView>,
|
||||||
|
) {
|
||||||
|
let ref mut card_table = hand_info[self.index];
|
||||||
|
let possible = card_table.get_possibilities();
|
||||||
|
for card in &possible {
|
||||||
|
if *self.partition.get(card).unwrap() != answer {
|
||||||
|
card_table.mark_false(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct InformationStrategyConfig;
|
pub struct InformationStrategyConfig;
|
||||||
|
@ -214,23 +268,34 @@ impl InformationPlayerStrategy {
|
||||||
let mut questions = Vec::new();
|
let mut questions = Vec::new();
|
||||||
let mut info_remaining = total_info;
|
let mut info_remaining = total_info;
|
||||||
|
|
||||||
while info_remaining > 1 {
|
fn add_question<T: 'static>(
|
||||||
let mut question = None;
|
questions: &mut Vec<Box<Question>>, info_remaining: &mut u32, question: T
|
||||||
for (i, card_table) in hand_info.iter().enumerate() {
|
) -> bool where T: Question {
|
||||||
let p = view.get_board().probability_is_playable(card_table);
|
*info_remaining = *info_remaining / question.info_amount();
|
||||||
if (p != 0.0) && (p != 1.0) {
|
questions.push(Box::new(question) as Box<Question>);
|
||||||
question = Some(Box::new(IsPlayable {index: i}) as Box<Question>);
|
|
||||||
break;
|
// if there's no more info to give, return that we should stop
|
||||||
|
*info_remaining <= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, card_table) in hand_info.iter().enumerate() {
|
||||||
|
let p = view.get_board().probability_is_playable(card_table);
|
||||||
|
if (p != 0.0) && (p != 1.0) {
|
||||||
|
if add_question(&mut questions, &mut info_remaining, IsPlayable {index: i}) {
|
||||||
|
return questions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(q) = question {
|
}
|
||||||
info_remaining = info_remaining / q.info_amount();
|
for (i, card_table) in hand_info.iter().enumerate() {
|
||||||
questions.push(q);
|
if !card_table.is_determined() {
|
||||||
} else {
|
let question = CardPossibilityPartition::new(i, info_remaining, card_table, view);
|
||||||
break;
|
if add_question(&mut questions, &mut info_remaining, question) {
|
||||||
|
return questions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
questions
|
|
||||||
|
return questions
|
||||||
}
|
}
|
||||||
|
|
||||||
fn answer_questions<T>(
|
fn answer_questions<T>(
|
||||||
|
@ -588,6 +653,7 @@ impl PlayerStrategy for InformationPlayerStrategy {
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
if playable_cards.len() > 0 {
|
if playable_cards.len() > 0 {
|
||||||
|
// TODO: try playing things that have no chance of being dead
|
||||||
// play the best playable card
|
// play the best playable card
|
||||||
// the higher the play_score, the better to play
|
// the higher the play_score, the better to play
|
||||||
let mut play_score = -1.0;
|
let mut play_score = -1.0;
|
||||||
|
|
Loading…
Reference in a new issue