src/main.rs
changeset 1 5f81068a8a88
parent 0 a95b84125269
child 2 950660fddec0
--- a/src/main.rs	Sun Jan 29 21:41:10 2023 +0100
+++ b/src/main.rs	Sun Jan 29 23:59:45 2023 +0100
@@ -1,13 +1,13 @@
 // vigyazz6! autplayer
 //
 
-use core::fmt;
+use core::{fmt, panic};
 use std::collections::VecDeque;
 use rand::Rng;
 use std::mem;
 
 fn main() {
-    println!("Hello, world!");
+    game();
 }
 
 #[derive(Debug)]
@@ -61,6 +61,25 @@
     }
 }
 
+impl Eq for Card {} 
+
+impl PartialOrd for Card {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        match self.value.partial_cmp(&other.value) {
+            Some(core::cmp::Ordering::Equal) => {None}
+            ord => return ord,
+        }
+    }
+}
+
+impl Ord for Card {
+    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+        self.value.cmp(&other.value)
+    }
+}
+
+
+#[derive(Debug)]
 struct Deck {
     content: VecDeque<Card>,
 }
@@ -88,9 +107,9 @@
         // * grin: take 1..6 from front and put at bottom
 
         // naive shuffle: exchange random cards
-        for _i in 1..500 {
-            let c1 = rng.gen_range(1 .. self.content.len());
-            let c2 = rng.gen_range(1 .. self.content.len());
+        for _i in 1..=500 {
+            let c1 = rng.gen_range(0 .. self.content.len());
+            let c2 = rng.gen_range(0 .. self.content.len());
             if c1 != c2 {
                 self.content.swap(c1, c2);
             }
@@ -120,6 +139,7 @@
     }
 }
 
+#[derive(Debug)]
 struct Player {
     name: String,
     hand: Deck,
@@ -156,7 +176,7 @@
     }
 
     // get a busted row of cards
-    fn get_pile( &mut self, cards: Vec<Card> ) {
+    fn get_pile( &mut self, cards: VecDeque<Card> ) {
         for c in cards.into_iter() {
             self.game_point += c.points as i32;
             self.pile.push(c);
@@ -208,6 +228,7 @@
 }
 
 // a row of cards on the table (max 5)
+#[derive(Debug)]
 struct Row {
     cards: VecDeque<Card>,
 }
@@ -243,32 +264,166 @@
     }
 }
 
+#[derive(Debug)]
 struct PlayerCard {
-    player_id: u32,
+    player_id: i32,
     card: Card,
 }
 
+impl PlayerCard {
+    fn get_player(&self) -> i32 {
+        self.player_id
+    }
+}
+
+impl PartialEq for PlayerCard {
+    fn eq(&self, other: &Self) -> bool {
+        self.card == other.card
+    }
+}
+
+impl PartialOrd for PlayerCard {
+    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+        match self.card.partial_cmp(&other.card) {
+            Some(core::cmp::Ordering::Equal) => {None}
+            ord => return ord,
+        }
+    }
+}
+
+#[derive(Debug)]
 struct Table {
     rows: Vec<Row>,
     player_cards: Vec<PlayerCard>, // owned by a player
 }
 
+impl Table {
+    fn new(row_cards: Vec<Card>) -> Self {
+        let mut rows = Vec::new();
+        for card in row_cards {
+            // create a new row then put a card into it
+            let mut row = Row::new();
+            if let Some(c) = row.push_or_collect(card) {
+                panic!("Freshly created row overflowed");
+            }
+            rows.push( row );
+        }
 
+        Table {
+            rows,
+            player_cards: Vec::new(),
+        }
+    }
+
+    fn lay_player_card( &mut self, card: Card, player_id: i32 ) {
+        self.player_cards.push( PlayerCard { player_id, card } );
+    }
+
+    fn sort_cards( &mut self ) {
+        self.player_cards.sort_by( |a,b| b.card.cmp(&a.card) );
+    }
+
+    fn get_smallest_player_card( &mut self ) -> PlayerCard {
+        self.player_cards.pop().expect("out of player cards on table")
+    }
+
+    fn get_closest_row( &self, pcard: &PlayerCard ) -> Option<i8> {
+        // get the row id with last card closest smaller to players'
+        todo!()
+    }
+
+    fn put_card_into_row( &mut self, pcard: PlayerCard, row_id: i8 ) -> Option<VecDeque<Card>> {
+        self.rows[row_id as usize].push_or_collect(pcard.card)
+    }
+}
 
 
 fn game() {
-/*
-    let mut deck = deck_init();
-    let mut players = Vec::new();
+    let mut cnt_shuffle = 0;
+
+    let mut deck = Deck::new();
+
+    let player_names = vec![ "grin", "moni", "icbalint", "orsi", "topi", "kgb", "zsu", "csilla" ];
+    let mut players: Vec<Player> = player_names.iter().map( |n| Player::new(n.to_string()) ).collect();
+
+    let player_count = players.len(); // pc - 1
+
+    for _cnt_game in 1..=2 {
+        deck.shuffle();
+        cnt_shuffle += 1;
+
+        // dealing
+        for i in 1..=10 {
+            for player in 0 .. player_count {
+                players[player].get_card( deck.pop().expect("Deck is empty while dealing to players") );
+            }
+        }
+
+        // we need 5 crds from deck
+        let mut cards = Vec::new();
+        for i in 1..=5 {
+            cards.push( deck.pop().expect("deck empty before starting the game") );
+        }
+        println!("We push 5 cards to rows: {:?}\n", cards);
+        let mut table = Table::new(cards);
+
+        // DEBUG
+        println!("Table: {:?}\n", table);
+        println!("PLayers: {:?}\n", players);
+        println!("Deck: {:?}\n", deck);
+        
+
+        // playing
+        for turn in 1..=10 {
 
-    for cnt_game in (1..100) {
+            // everyone puts a card face down
+            for player in 0 .. player_count {
+                let player_id: i32 = player.try_into().unwrap();
+                // get a card from the player
+                let topcard = players[player].throw_card();
+                // put it on the table ("turned face down")
+                table.lay_player_card( topcard, player_id );
+            }
+
+            // process cards
+            table.sort_cards();
+
+            let smallest = table.get_smallest_player_card();
 
+            let closest_row = table.get_closest_row(&smallest);
+            match closest_row {
+                Some(rowid) => {
+                    let player_id: usize = smallest.player_id.try_into().unwrap();
+                    let overflow = table.put_card_into_row(smallest, rowid);
+                    if let Some(cards) = overflow {
+                        // row is full, got pile
+                        // player gets pile, card gets into row head
+                        players[ player_id ].get_pile( cards );
+                    }
+                },
+                None => {
+                    // card too small, need to pick row!
+                    todo!();
+                }
+            }
+
+        }
+
+        // end of round
+
+        // recollect deck
+
+        panic!("FInish now.");
     }
-     */
 }
 
 #[cfg(test)]
 mod tests {
+    use core::panic;
+    use std::collections::VecDeque;
+
+    use rand::Rng;
+
     use crate::{Card, Player, Row};
 
     #[test]
@@ -287,11 +442,11 @@
         // create a player
         let mut p = Player::new("bob".to_string());
         // create a pile
-        let mut pile = Vec::new();
+        let mut pile = VecDeque::new();
         let mut refpile = Vec::new();
         for i in 5..10 {
             let c = Card::new(i);
-            pile.push(c);
+            pile.push_back(c);
             let c = Card::new(i);
             refpile.push(c);
         }
@@ -307,10 +462,10 @@
         // this check is O(n^2), doesn't matter for less than 100 items
         assert!( pile.iter().all( |item| refpile.contains(item)) );
 
-        let mut pile = Vec::new();
-        for i in 4..9 {
+        let mut pile = VecDeque::new();
+        for i in 4..=9 {
             let c = Card::new(i);
-            pile.push(c);
+            pile.push_back(c);
         }
         p.get_pile(pile);
         assert!( p.rows_busted == 2 );
@@ -342,6 +497,22 @@
         }
         assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() );
     }
+
+    #[test]
+    fn sort_cards() {
+        let mut cards: Vec<Card> = Vec::new();
+        let mut rng = rand::thread_rng();
+        for i in 1..50 {
+            let n = rng.gen_range(1..104);
+            cards.push( Card::new(n) );
+        }
+        cards.sort();
+
+        for i in 1..cards.len() {
+            assert!( cards[i-1].value <= cards[i].value, "Bad ordering: {} > {}", cards[i-1].value,cards[i].value );
+        }
+    }
+
 }
 
 /*