|
|
@@ -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
|
+}
|