Explorar el Código

Implemented game mechanics
Heaps of winned cards for defence and attack, dealing with the fool

Denis Merigoux hace 9 años
padre
commit
2f2739b624
Se han modificado 4 ficheros con 293 adiciones y 25 borrados
  1. 82 0
      src/ai.rs
  2. 38 0
      src/card.rs
  3. 169 22
      src/game.rs
  4. 4 3
      src/main.rs

+ 82 - 0
src/ai.rs

@@ -0,0 +1,82 @@
1
+use game;
2
+use deck;
3
+use card;
4
+
5
+// Each player looks at his game and termines if he takes or not, returns the taker's id
6
+pub fn auctions(players: &Vec<game::Player>) -> i32 {
7
+    let potentials: Vec<(i32, i32)> = players.iter()
8
+        .map(|ref player| (player.id, evaluate_hand_potential(&player.hand)))
9
+        .collect();
10
+    let &(taker_id, _) = match potentials.iter().max_by_key(|&&(id, _)| id) {
11
+        None => panic!("no players"),
12
+        Some(x) => x,
13
+    };
14
+    taker_id
15
+}
16
+
17
+pub fn evaluate_hand_potential(hand: &deck::Hand) -> i32 {
18
+    hand.iter().fold(0, |acc, card| acc + card::potential_value(card))
19
+}
20
+
21
+pub fn exchange_dog(mut players: &mut Vec<game::Player>,
22
+                    dog: &mut deck::Hand,
23
+                    game: &mut game::Game) {
24
+    let ref mut taker = match players.iter_mut().find(|player| player.id == game.taker_id) {
25
+        None => panic!("cannot find the taker"),
26
+        Some(player) => player,
27
+    };
28
+    // Now we proceed to exchange the cards in the dog
29
+    // We adopt a simple and naïve strategy
30
+    // We let the low cards in the dog and exchange useful for random low others
31
+    let mut new_dog: Vec<(card::Card, i32)> = Vec::new();
32
+    dog.clone()
33
+        .iter()
34
+        .fold((), |_, &card| {
35
+            let to_exchange = match card {
36
+                card::Card::Trump(_) => true,
37
+                card::Card::Face(card::Face { suit: _, symbol }) => {
38
+                    match symbol {
39
+                        card::Symbol::Jack | card::Symbol::Knight | card::Symbol::Queen |
40
+                        card::Symbol::King => true,
41
+                        _ => false,
42
+                    }
43
+                }
44
+                card::Card::Fool => true,
45
+            };
46
+            if to_exchange {
47
+                // Performs the exchange
48
+                dog.remove(&card);
49
+                new_dog.push((card, taker.id));
50
+            }
51
+        });
52
+    // We exchange the remaining cards with cards in the hand of the taker
53
+    dog.clone().iter().fold((), |_, &dog_card| {
54
+        let taker_hand = taker.hand.clone();
55
+        let exchange_card = taker_hand.iter().filter(|&&card| dog_card > card).next();
56
+        match exchange_card {
57
+            None => (),
58
+            Some(&exchange_card) => {
59
+                dog.remove(&dog_card);
60
+                taker.hand.insert(dog_card);
61
+                taker.hand.remove(&exchange_card);
62
+                new_dog.push((exchange_card, taker.id));
63
+            }
64
+        };
65
+    });
66
+    //Then for the remaining cards in the dog we simply transfer them to the new dog
67
+    dog.clone().iter().fold((), |_, &card| {
68
+        dog.remove(&card);
69
+        new_dog.push((card, taker.id));
70
+    });
71
+
72
+    // Finaly the new dog goes into the attack's heap
73
+    game.attack_heap.append(&mut new_dog);
74
+}
75
+
76
+// Select a card to play among the valid cards
77
+pub fn select_card(_: &game::Player, valid_cards: &deck::Hand, _: &game::Heap) -> card::Card {
78
+    match valid_cards.iter().next() {
79
+        None => panic!("no valid card to play"),
80
+        Some(card) => card.clone(),
81
+    }
82
+}

+ 38 - 0
src/card.rs

@@ -210,3 +210,41 @@ impl Ord for Card {
210 210
         }
211 211
     }
212 212
 }
213
+
214
+pub fn potential_value(&card: &Card) -> i32 {
215
+    match card {
216
+        Card::Fool => 100,
217
+        Card::Trump(Trump::One) => 100,
218
+        Card::Trump(Trump::TwentyOne) => 100,
219
+        Card::Face(Face { suit: _, symbol: Symbol::Jack }) => 10,
220
+        Card::Face(Face { suit: _, symbol: Symbol::Knight }) => 20,
221
+        Card::Face(Face { suit: _, symbol: Symbol::Queen }) => 30,
222
+        Card::Face(Face { suit: _, symbol: Symbol::King }) => 40,
223
+        Card::Trump(trump) => {
224
+            10 +
225
+            match trump {
226
+                Trump::Two => 2,
227
+                Trump::Three => 3,
228
+                Trump::Four => 4,
229
+                Trump::Five => 5,
230
+                Trump::Six => 6,
231
+                Trump::Seven => 7,
232
+                Trump::Eight => 8,
233
+                Trump::Nine => 9,
234
+                Trump::Ten => 10,
235
+                Trump::Eleven => 11,
236
+                Trump::Twelve => 12,
237
+                Trump::Thirteen => 13,
238
+                Trump::Fourteen => 14,
239
+                Trump::Fifteen => 15,
240
+                Trump::Sixteen => 16,
241
+                Trump::Seventeen => 17,
242
+                Trump::Eighteen => 18,
243
+                Trump::Nineteen => 19,
244
+                Trump::Twenty => 20,
245
+                _ => 100,
246
+            }
247
+        }
248
+        _ => 0,
249
+    }
250
+}

+ 169 - 22
src/game.rs

@@ -1,8 +1,9 @@
1 1
 use params;
2 2
 use deck;
3 3
 use card;
4
+use ai;
4 5
 
5
-type Heap = Vec<(card::Card, i32)>;
6
+pub type Heap = Vec<(card::Card, i32)>;
6 7
 
7 8
 #[derive(Clone)]
8 9
 pub struct Player {
@@ -11,6 +12,12 @@ pub struct Player {
11 12
     pub hand: deck::Hand,
12 13
 }
13 14
 
15
+pub struct Game {
16
+    pub taker_id: i32,
17
+    pub attack_heap: Heap,
18
+    pub defense_heap: Heap,
19
+}
20
+
14 21
 // Empty the hands and names vector and creates a player vector instead
15 22
 pub fn initialize_players(hands: &mut Vec<deck::Hand>, names: &mut Vec<String>) -> Vec<Player> {
16 23
     if hands.len() != names.len() {}
@@ -35,33 +42,105 @@ pub fn initialize_players(hands: &mut Vec<deck::Hand>, names: &mut Vec<String>)
35 42
     players
36 43
 }
37 44
 
38
-pub fn start_game(_: &deck::Hand, mut players: &mut Vec<Player>) {
45
+pub fn start_game(mut dog: &mut deck::Hand, mut players: &mut Vec<Player>) {
39 46
     let cards_per_player = players[0].hand.len();
40
-    //Check if all players have same number of cards
47
+    // Check if all players have same number of cards
41 48
     for i in 1..params::NUMBER_OF_PLAYERS {
42 49
         if cards_per_player != players[i].hand.len() {
43 50
             panic!("the players don't have the same number of cards")
44 51
         }
45 52
     }
53
+
54
+    // Determine the attack and defense
55
+    let taker_id = ai::auctions(&players);
56
+    let mut game = Game {
57
+        taker_id: taker_id,
58
+        attack_heap: Vec::new(),
59
+        defense_heap: Vec::new(),
60
+    };
61
+    println!(">>>> {} prend le chien <<<<<",
62
+             match players.iter().find(|player| player.id == taker_id) {
63
+                 None => panic!("cannot find the player who won the round"),
64
+                 Some(player) => &player.name,
65
+             });
66
+
67
+    ai::exchange_dog(&mut players, &mut dog, &mut game);
68
+
46 69
     let mut starting_player_id = 0;
70
+    let mut fool_on_standby: Option<(card::Card, i32)> = None;
47 71
     println!("===== Début de la partie ! =====");
48 72
     for _ in 0..cards_per_player {
49 73
         // For each round of the game
50 74
         let mut cards_played: Heap = Vec::new();
51 75
         sort_by_playing_order(&mut players, starting_player_id);
52 76
         for player in players.iter_mut() {
53
-            // For each player
77
+            // Each player plays a card
54 78
             play_card(player, &mut cards_played)
55 79
         }
56 80
         // Decide who has won
57 81
         starting_player_id = winning_player(&mut cards_played);
58
-        let last_card_played = match cards_played.first() {
59
-            None => panic!("no card played this round"),
60
-            Some(card) => card,
61
-        };
62
-        println!(">>>>> Le joueur {} remporte le pli avec la carte {} ! <<<<<",
63
-                 last_card_played.1,
64
-                 last_card_played.0);
82
+        {
83
+            // Printing winner
84
+            let last_card_played = match cards_played.first() {
85
+                None => panic!("no card played this round"),
86
+                Some(card) => card,
87
+            };
88
+            println!(">>>>> {} remporte le pli avec la carte {} ! <<<<<",
89
+                     match players.iter().find(|player| player.id == last_card_played.1) {
90
+                         None => panic!("cannot find the player who won the round"),
91
+                         Some(player) => &player.name,
92
+                     },
93
+                     last_card_played.0);
94
+        }
95
+
96
+        // Before giving cards to the winner's heap, must first apply special rule for the fool
97
+        match fool_on_standby {
98
+            None => (),
99
+            Some(fool) => {
100
+                // The player who played the fool couldn't exchange cards in a prior tour,
101
+                // trying now to do so
102
+                cards_played.push(fool)
103
+            }
104
+        }
105
+        fool_on_standby = deal_with_fool(&mut cards_played, &mut game, starting_player_id);
106
+
107
+        // Giving cards to the winner's heap
108
+        if starting_player_id == game.taker_id {
109
+            game.attack_heap.append(&mut cards_played);
110
+        } else {
111
+            game.defense_heap.append(&mut cards_played);
112
+        }
113
+    }
114
+    // End of game
115
+    match fool_on_standby {
116
+        None => (),
117
+        Some((fool, id)) => {
118
+            // The player never could exchange his fool, we return it to him
119
+            if id == game.taker_id {
120
+                game.attack_heap.push((fool, id));
121
+            } else {
122
+                game.defense_heap.push((fool, id));
123
+            }
124
+        }
125
+    }
126
+
127
+    println!("-> Cartes gagnées par l'attaque");
128
+    for &(card, id) in game.attack_heap.iter() {
129
+        println!("{} ({})",
130
+                 card,
131
+                 match players.iter().find(|player| player.id == id) {
132
+                     None => panic!("cannot find the player who won the round"),
133
+                     Some(player) => &player.name,
134
+                 });
135
+    }
136
+    println!("-> Cartes gagnées par la défense");
137
+    for &(card, id) in game.defense_heap.iter() {
138
+        println!("{} ({})",
139
+                 card,
140
+                 match players.iter().find(|player| player.id == id) {
141
+                     None => panic!("cannot find the player who won the round"),
142
+                     Some(player) => &player.name,
143
+                 });
65 144
     }
66 145
 }
67 146
 
@@ -79,10 +158,10 @@ fn sort_by_playing_order(mut players: &mut Vec<Player>, starting_player_id: i32)
79 158
 
80 159
 fn play_card(player: &mut Player, cards_played: &mut Heap) {
81 160
     let valid_cards = valid_cards(&player, cards_played);
82
-    let card = select_card(player, &valid_cards, cards_played);
161
+    let card = ai::select_card(player, &valid_cards, cards_played);
83 162
     player.hand.remove(&card);
84 163
     cards_played.push((card, player.id));
85
-    println!("Le joueur {} joue {}.", player.id, card);
164
+    println!("{} joue {}.", player.name, card);
86 165
 }
87 166
 
88 167
 fn valid_cards(player: &Player, cards_played: &Heap) -> deck::Hand {
@@ -186,7 +265,7 @@ fn valid_cards(player: &Player, cards_played: &Heap) -> deck::Hand {
186 265
     }
187 266
 }
188 267
 
189
-// Returns the max trump in a heap of played cards, panics if no trump
268
+// Returns the max trump in a heap of played cards
190 269
 fn max_trump(cards_played: &Heap) -> Option<card::Trump> {
191 270
     let mut max_trump: Option<card::Trump> = None;
192 271
     for &(card, _) in cards_played.iter() {
@@ -207,14 +286,6 @@ fn max_trump(cards_played: &Heap) -> Option<card::Trump> {
207 286
     max_trump
208 287
 }
209 288
 
210
-// Select a card to play among the valid cards
211
-fn select_card(_: &Player, valid_cards: &deck::Hand, _: &Heap) -> card::Card {
212
-    match valid_cards.iter().next() {
213
-        None => panic!("no valid card to play"),
214
-        Some(card) => card.clone(),
215
-    }
216
-}
217
-
218 289
 // Determine who won the round
219 290
 fn winning_player(cards: &mut Heap) -> i32 {
220 291
     cards.sort_by(|&(card1, _), &(card2, _)| card2.cmp(&card1));
@@ -223,3 +294,79 @@ fn winning_player(cards: &mut Heap) -> i32 {
223 294
         None => panic!("no cards have been played"),
224 295
     }
225 296
 }
297
+
298
+// Proceeds to exchange the fool against a lower card of the opponent's heap if necessary
299
+fn deal_with_fool(mut cards_played: &mut Heap,
300
+                  mut game: &mut Game,
301
+                  winning_player_id: i32)
302
+                  -> Option<(card::Card, i32)> {
303
+    let mut fool_index: Option<usize> = None;
304
+    let mut fool_on_standby: Option<(card::Card, i32)> = None;
305
+    for (index, &(card_played, _)) in cards_played.iter().enumerate() {
306
+        if card_played == card::Card::Fool {
307
+            fool_index = Some(index);
308
+            break;
309
+        }
310
+    }
311
+    match fool_index {
312
+        None => (),
313
+        Some(index) => {
314
+            let fool = cards_played.remove(index);
315
+            if fool.1 == game.taker_id && winning_player_id != game.taker_id {
316
+                // The attack played the fool and lost => exchange
317
+                let attack_copy = game.attack_heap.clone();
318
+                let card_to_exchange = attack_copy.iter()
319
+                    .enumerate()
320
+                    .filter(|&(_, &(card, _))| match card {
321
+                        card::Card::Trump(_) => false,
322
+                        card::Card::Face(card::Face { suit: _, symbol }) => {
323
+                            match symbol {
324
+                                card::Symbol::Jack | card::Symbol::Knight |
325
+                                card::Symbol::Queen | card::Symbol::King => false,
326
+                                _ => true,
327
+                            }
328
+                        }
329
+                        card::Card::Fool => false,
330
+                    })
331
+                    .next();
332
+                match card_to_exchange {
333
+                    Some((index, &card_to_exchange)) => {
334
+                        game.attack_heap.remove(index);
335
+                        game.defense_heap.push(card_to_exchange);
336
+                        game.attack_heap.push(fool);
337
+                    }
338
+                    None => fool_on_standby = Some(fool),
339
+                };
340
+            } else if fool.1 != game.taker_id && winning_player_id == game.taker_id {
341
+                // The defense played the fool and lost => exchange
342
+                let defense_copy = game.defense_heap.clone();
343
+                let card_to_exchange = defense_copy.iter()
344
+                    .enumerate()
345
+                    .filter(|&(_, &(card, _))| match card {
346
+                        card::Card::Trump(_) => false,
347
+                        card::Card::Face(card::Face { suit: _, symbol }) => {
348
+                            match symbol {
349
+                                card::Symbol::Jack | card::Symbol::Knight |
350
+                                card::Symbol::Queen | card::Symbol::King => false,
351
+                                _ => true,
352
+                            }
353
+                        }
354
+                        card::Card::Fool => false,
355
+                    })
356
+                    .next();
357
+                match card_to_exchange {
358
+                    Some((index, &card_to_exchange)) => {
359
+                        game.defense_heap.remove(index);
360
+                        game.attack_heap.push(card_to_exchange);
361
+                        game.defense_heap.push(fool);
362
+                    }
363
+                    None => fool_on_standby = Some(fool),
364
+                };
365
+            } else {
366
+                // Normal case, the fool shouldn't be exchanged
367
+                cards_played.insert(index, fool);
368
+            }
369
+        }
370
+    };
371
+    fool_on_standby
372
+}

+ 4 - 3
src/main.rs

@@ -2,6 +2,7 @@ mod card;
2 2
 mod deck;
3 3
 mod params;
4 4
 mod game;
5
+mod ai;
5 6
 
6 7
 extern crate rand;
7 8
 
@@ -13,17 +14,17 @@ fn main() {
13 14
     let mut names: Vec<String> =
14 15
         vec!["A".to_string(), "B".to_string(), "C".to_string(), "D".to_string()];
15 16
     let deck = deck::new_deck();
16
-    let (dog, mut hands) = deck::distribute_cards(&deck);
17
+    let (mut dog, mut hands) = deck::distribute_cards(&deck);
17 18
     let mut players = game::initialize_players(&mut hands, &mut names);
18 19
     println!("-> Cartes du chien :");
19 20
     for card in dog.iter() {
20 21
         println!("{}", card);
21 22
     }
22 23
     for player in players.iter() {
23
-        println!("-> Cartes du joueur {}:", player.id);
24
+        println!("-> Cartes du joueur {}:", player.name);
24 25
         for card in player.hand.iter() {
25 26
             println!("{}", card);
26 27
         }
27 28
     }
28
-    game::start_game(&dog, &mut players);
29
+    game::start_game(&mut dog, &mut players);
29 30
 }