--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.rs Sun Jan 29 21:41:10 2023 +0100
@@ -0,0 +1,371 @@
+// vigyazz6! autplayer
+//
+
+use core::fmt;
+use std::collections::VecDeque;
+use rand::Rng;
+use std::mem;
+
+fn main() {
+ println!("Hello, world!");
+}
+
+#[derive(Debug)]
+struct Card {
+ value: i8,
+ points: i8,
+}
+
+impl Card {
+ fn new(value: i8)->Self {
+
+ let mut points = 0;
+ if value % 10 == 5 {
+ // ends with 5 = 2 point
+ points = 2;
+ // println!("*5 add 1, val={}, pt={}", value, points);
+ }
+
+ if value % 10 == 0 {
+ // ends with 0 = 3 point
+ points = 3;
+ // println!("*0 add 2, val={}, pt={}", value, points);
+ }
+
+ if value % 10 == value / 10 {
+ // same numbers = 5 points (55=7)
+ points += 5;
+ // println!("NN add 5, val={}, pt={}", value, points);
+ }
+
+ if points == 0 {
+ points = 1;
+ }
+
+ Card {
+ value,
+ points,
+ }
+ }
+}
+
+impl fmt::Display for Card {
+ fn fmt( &self, f: &mut fmt::Formatter ) -> fmt::Result {
+ write!(f, "(Card {}, points {})", self.value, self.points)
+ }
+}
+
+impl PartialEq for Card {
+ fn eq(&self, other: &Self) -> bool {
+ self.value == other.value
+ }
+}
+
+struct Deck {
+ content: VecDeque<Card>,
+}
+
+impl Deck {
+ fn new_empty() -> Self {
+ Deck {
+ content: VecDeque::new(),
+ }
+ }
+
+ fn new() -> Self {
+ let content = (1..104).into_iter().map( |n| Card::new(n) ).collect();
+ Deck {
+ content,
+ }
+ }
+
+ fn shuffle( &mut self ) {
+ let mut rng = rand::thread_rng();
+
+ // shufflers:
+ // * naive: swap cards n times
+ // * kgb: half the deck, take 1..4 cards sequentially from each
+ // * 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());
+ if c1 != c2 {
+ self.content.swap(c1, c2);
+ }
+ }
+ }
+
+ // get top card from deck
+ fn pop( &mut self ) -> Option<Card> {
+ self.content.pop_front()
+ }
+
+ // put a card into the bottom of the deck
+ fn push( &mut self, c: Card ) {
+ self.content.push_back(c);
+ }
+
+ fn len( &self ) -> usize {
+ self.content.len()
+ }
+
+ fn get_nth( &mut self, n: usize ) -> Card {
+ if let Some(c) = self.content.remove(n) {
+ c
+ } else {
+ panic!("get_nth: index {} out of bounds ({})!", n, self.content.len());
+ }
+ }
+}
+
+struct Player {
+ name: String,
+ hand: Deck,
+ pile: Vec<Card>,
+ game_point: i32,
+ total_point: i32,
+ rows_busted: i32,
+}
+
+impl Player {
+ fn new(name: String)->Self {
+ Player {
+ name,
+ hand: Deck::new_empty(),
+ pile: Vec::new(),
+ game_point: 0,
+ total_point: 0,
+ rows_busted: 0,
+ }
+ }
+
+ // get one card from th dealer
+ fn get_card( &mut self, card: Card ) {
+ self.hand.push(card);
+ }
+
+ // throw a card from hand to the table
+ fn throw_card( &mut self )->Card {
+ if let Some(c) = self.hand.pop() {
+ c
+ } else {
+ panic!("throw_card: Player {} has no card in hand!", self.name);
+ }
+ }
+
+ // get a busted row of cards
+ fn get_pile( &mut self, cards: Vec<Card> ) {
+ for c in cards.into_iter() {
+ self.game_point += c.points as i32;
+ self.pile.push(c);
+ }
+ self.rows_busted += 1;
+ }
+
+ // ask the player their score
+ fn tell_points( self ) -> i32 {
+ self.game_point
+ }
+
+ // give back cards from the pile
+ fn give_pile( &mut self ) -> Vec<Card> {
+ mem::take( &mut self.pile )
+ // same effect:
+ // self.pile.drain(..).collect()
+
+ // very cumbersome manual fiddling (also reverted...)
+/* let mut throw: Vec<Card> = Vec::new();
+ for _i in 0 .. self.pile.len() {
+ throw.push( self.pile.pop().unwrap() );
+ }
+ throw
+ */
+ }
+
+ // I can do this just because I *throw away* c!
+ // doesn't work if I want to use it.
+/* fn _gimme_pile(self)->Self {
+ for c in &self.pile {
+ println!("Throw {} ", c);
+ }
+ self
+ }
+ */
+ fn close_round( &mut self ) {
+ if self.hand.len() > 0 {
+ panic!("Closing round when {} has {} cards in hand", self.name, self.hand.len());
+ }
+
+ if self.pile.len() > 0 {
+ panic!("Closing round when {} stil have pile with {} cards", self.name, self.pile.len());
+ }
+
+ self.total_point += self.game_point;
+ self.game_point = 0;
+ }
+}
+
+// a row of cards on the table (max 5)
+struct Row {
+ cards: VecDeque<Card>,
+}
+
+impl Row {
+ const MAX_LEN: usize = 5;
+
+ fn new() -> Self {
+ Row {
+ cards: VecDeque::new(),
+ }
+ }
+
+ fn push_or_collect( &mut self, card: Card ) -> Option<VecDeque<Card>> {
+ if self.cards.len() < Self::MAX_LEN {
+ self.cards.push_back(card);
+ None
+
+ } else {
+ // row overflow
+ let row_cards = mem::take( &mut self.cards );
+ self.cards.push_back(card);
+ if self.cards.len() != 1 {
+ panic!("New row must have one card, not {}", self.cards.len());
+ }
+ Some(row_cards)
+ }
+ }
+
+ fn last_card_value(&self) -> i8 {
+ println!("last_card_value: cards {:?}, len {}", self.cards, self.cards.len());
+ self.cards.get( self.cards.len()-1 ).unwrap().value
+ }
+}
+
+struct PlayerCard {
+ player_id: u32,
+ card: Card,
+}
+
+struct Table {
+ rows: Vec<Row>,
+ player_cards: Vec<PlayerCard>, // owned by a player
+}
+
+
+
+
+fn game() {
+/*
+ let mut deck = deck_init();
+ let mut players = Vec::new();
+
+ for cnt_game in (1..100) {
+
+ }
+ */
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{Card, Player, Row};
+
+ #[test]
+ fn card_values() {
+ let card_values = vec![1,2,5,10,33,55,77];
+ let card_points = vec![1,1,2,3, 5, 7, 5];
+ for i in 1 .. card_values.len() {
+ let c = Card::new( card_values[i] );
+ let p = c.points;
+ assert!(p == card_points[i], "card={} card points={} i={} expected point={}", card_values[i], p, i, card_points[i]);
+ }
+ }
+
+ #[test]
+ fn player_take_pile() {
+ // create a player
+ let mut p = Player::new("bob".to_string());
+ // create a pile
+ let mut pile = Vec::new();
+ let mut refpile = Vec::new();
+ for i in 5..10 {
+ let c = Card::new(i);
+ pile.push(c);
+ let c = Card::new(i);
+ refpile.push(c);
+ }
+ // add the pile to player
+ p.get_pile(pile);
+ assert!( p.rows_busted == 1 );
+
+ // get back the pile from player
+ // p = p.gimme_pile();
+ let pile = p.give_pile();
+
+ // the pile we got shall be same as the pile we gave
+ // 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 c = Card::new(i);
+ pile.push(c);
+ }
+ p.get_pile(pile);
+ assert!( p.rows_busted == 2 );
+ }
+
+ #[test]
+ fn row_push() {
+ let mut row = Row::new();
+ let mut refcard = Vec::new(); // reference vec to check
+ for i in 1..=7 {
+ let cval = i+5;
+ let card = Card::new(cval);
+ // push a card into the row
+ if let Some(cards) = row.push_or_collect(card) {
+ // got the overflow
+ println!("Got overflow row at {}!", i);
+ assert!( i == 6, "Overflow at wrong position: {} != 6", i );
+ // we need to get the proper vec
+ assert!( cards.iter().all( |item| refcard.contains(item) ), "Got cards {:?}", cards );
+ } else {
+ println!("push success {}", i);
+ }
+ // remember the correct vec for checking
+ let card = Card::new(cval);
+ refcard.push(card);
+
+ // check card value
+ assert!( row.last_card_value() == cval, "Last card value mismatch: got {} vs expected {}", row.last_card_value(), cval );
+ }
+ assert!( row.cards.len() == 2, "Row contains wrong amount of cards: {}", row.cards.len() );
+ }
+}
+
+/*
+
+- 1-104 lap,
+ - *5 - 2
+ - *0 - 3
+ - NN - 5
+ - 55 - 7
+- deck
+- jatekosok; kezben tartott lapok; elvitt lapok; pontszamok; counter: elvitt sorok, okrok, total pont
+-- keveres (keveresek szama)
+-- osztas: mindenki 10 lap
+-- start sorok: 5 kartya
+- jatek (jatekok szama)
+-- mindenki a felso lapot kiteszi
+-- szamsorrendben felkerulnek, aki viszi, viszi
+--- ha kisebb, akkor dontes
+---- ha van legkevesebb, viszi
+---- ha tobb min van, random valaszt
+- osszesites
+-- okrok, elvitt sorok
+-- keveresek szama, jatekok szama, eltelt ido
+- deck osszegyujtes
+
+
+*/
\ No newline at end of file