scoring
This commit is contained in:
		
							parent
							
								
									b64521169b
								
							
						
					
					
						commit
						7f98ea6afe
					
				
							
								
								
									
										45
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
{
 | 
			
		||||
    // Use IntelliSense to learn about possible attributes.
 | 
			
		||||
    // Hover to view descriptions of existing attributes.
 | 
			
		||||
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 | 
			
		||||
    "version": "0.2.0",
 | 
			
		||||
    "configurations": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "lldb",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "name": "Debug executable 'mercury'",
 | 
			
		||||
            "cargo": {
 | 
			
		||||
                "args": [
 | 
			
		||||
                    "build",
 | 
			
		||||
                    "--bin=mercury",
 | 
			
		||||
                    "--package=mercury"
 | 
			
		||||
                ],
 | 
			
		||||
                "filter": {
 | 
			
		||||
                    "name": "mercury",
 | 
			
		||||
                    "kind": "bin"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "args": [],
 | 
			
		||||
            "cwd": "${workspaceFolder}"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "type": "lldb",
 | 
			
		||||
            "request": "launch",
 | 
			
		||||
            "name": "Debug unit tests in executable 'mercury'",
 | 
			
		||||
            "cargo": {
 | 
			
		||||
                "args": [
 | 
			
		||||
                    "test",
 | 
			
		||||
                    "--no-run",
 | 
			
		||||
                    "--bin=mercury",
 | 
			
		||||
                    "--package=mercury"
 | 
			
		||||
                ],
 | 
			
		||||
                "filter": {
 | 
			
		||||
                    "name": "mercury",
 | 
			
		||||
                    "kind": "bin"
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            "args": [],
 | 
			
		||||
            "cwd": "${workspaceFolder}"
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
let
 | 
			
		||||
  moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
 | 
			
		||||
  nixpkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
 | 
			
		||||
  nixpkgs = import <nixos-unstable> { overlays = [ moz_overlay ]; };
 | 
			
		||||
  rustNightlyChannel = (nixpkgs.rustChannelOf { date = "2020-03-19"; channel = "nightly"; }).rust.override {
 | 
			
		||||
    extensions = [
 | 
			
		||||
			"rust-src"
 | 
			
		||||
@ -23,5 +23,12 @@ with nixpkgs;
 | 
			
		||||
    name = "moz_overlay_shell";
 | 
			
		||||
    buildInputs = [
 | 
			
		||||
      rustStableChannel
 | 
			
		||||
      (vscode-with-extensions.override {
 | 
			
		||||
        vscodeExtensions = with vscode-extensions; [
 | 
			
		||||
          bbenoist.Nix
 | 
			
		||||
          vadimcn.vscode-lldb
 | 
			
		||||
          matklad.rust-analyzer
 | 
			
		||||
        ];
 | 
			
		||||
      })
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										312
									
								
								src/azul.rs
									
									
									
									
									
								
							
							
						
						
									
										312
									
								
								src/azul.rs
									
									
									
									
									
								
							@ -12,6 +12,7 @@ pub enum Tile {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// factory, color, pattern line
 | 
			
		||||
#[derive(Debug, Clone, Copy)]
 | 
			
		||||
pub struct GameMove (pub usize, pub Tile, pub usize);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
@ -112,6 +113,102 @@ struct Board {
 | 
			
		||||
    floor: Vec<Tile>,
 | 
			
		||||
    patterns: Patterns,
 | 
			
		||||
}
 | 
			
		||||
impl Board {
 | 
			
		||||
    fn wall_index(color: Tile, row: usize) -> Result<usize, &'static str> {
 | 
			
		||||
        match row {
 | 
			
		||||
            0 => {
 | 
			
		||||
                match color {
 | 
			
		||||
                    Tile::Blue => Ok(0),
 | 
			
		||||
                    Tile::Yellow => Ok(1),
 | 
			
		||||
                    Tile::Red => Ok(2),
 | 
			
		||||
                    Tile::Black => Ok(3),
 | 
			
		||||
                    Tile::Teal => Ok(4),
 | 
			
		||||
                    _ => return Err("Not a valid tile on the wall")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            1 => {
 | 
			
		||||
                match color {
 | 
			
		||||
                    Tile::Blue => Ok(1),
 | 
			
		||||
                    Tile::Yellow => Ok(2),
 | 
			
		||||
                    Tile::Red => Ok(3),
 | 
			
		||||
                    Tile::Black => Ok(4),
 | 
			
		||||
                    Tile::Teal => Ok(0),
 | 
			
		||||
                    _ => return Err("Not a valid tile on the wall")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            2 => {
 | 
			
		||||
                match color {
 | 
			
		||||
                    Tile::Blue => Ok(2),
 | 
			
		||||
                    Tile::Yellow => Ok(3),
 | 
			
		||||
                    Tile::Red => Ok(4),
 | 
			
		||||
                    Tile::Black => Ok(0),
 | 
			
		||||
                    Tile::Teal => Ok(1),
 | 
			
		||||
                    _ => return Err("Not a valid tile on the wall")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            3 => {
 | 
			
		||||
                match color {
 | 
			
		||||
                    Tile::Blue => Ok(3),
 | 
			
		||||
                    Tile::Yellow => Ok(4),
 | 
			
		||||
                    Tile::Red => Ok(0),
 | 
			
		||||
                    Tile::Black => Ok(1),
 | 
			
		||||
                    Tile::Teal => Ok(2),
 | 
			
		||||
                    _ => return Err("Not a valid tile on the wall")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            4 => {
 | 
			
		||||
                match color {
 | 
			
		||||
                    Tile::Blue => Ok(4),
 | 
			
		||||
                    Tile::Yellow => Ok(0),
 | 
			
		||||
                    Tile::Red => Ok(1),
 | 
			
		||||
                    Tile::Black => Ok(2),
 | 
			
		||||
                    Tile::Teal => Ok(3),
 | 
			
		||||
                    _ => return Err("Not a valid tile on the wall")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            _ => return Err("Not a valid row on the wall")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fn connected(&self, coordinate: (usize, usize)) -> u8 {
 | 
			
		||||
        let wall = self.wall;
 | 
			
		||||
 | 
			
		||||
        let mut sum = 0;
 | 
			
		||||
        let mut active = false;
 | 
			
		||||
 | 
			
		||||
        let mut count = 0;
 | 
			
		||||
        for i in 0..5 {
 | 
			
		||||
            if active == true && wall[coordinate.0][i] == false {
 | 
			
		||||
                break;
 | 
			
		||||
            } else if wall[coordinate.0][i] == false {
 | 
			
		||||
                count = 0;
 | 
			
		||||
            } else if (coordinate.0, i) == coordinate {
 | 
			
		||||
                active = true;
 | 
			
		||||
                count += 1;
 | 
			
		||||
            } else {
 | 
			
		||||
                count += 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        sum += count;
 | 
			
		||||
 | 
			
		||||
        let mut active = false;
 | 
			
		||||
        let mut count = 0;
 | 
			
		||||
        for i in 0..5 {
 | 
			
		||||
            if active == true && wall[i][coordinate.1] == false {
 | 
			
		||||
                break;
 | 
			
		||||
            } else if wall[i][coordinate.1] == false {
 | 
			
		||||
                count = 0;
 | 
			
		||||
            } else if (i, coordinate.1) == coordinate {
 | 
			
		||||
                active = true;
 | 
			
		||||
                count += 1;
 | 
			
		||||
            } else {
 | 
			
		||||
                count += 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        sum += count;
 | 
			
		||||
 | 
			
		||||
        return sum
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
impl Default for Board {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Board {
 | 
			
		||||
@ -186,8 +283,34 @@ impl Game {
 | 
			
		||||
        };
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
    pub fn do_move(&self, game_move: GameMove) -> Result<Game, &'static str> {
 | 
			
		||||
    fn score(&mut self) -> Result<(), &'static str> {
 | 
			
		||||
        for board in &mut self.boards {
 | 
			
		||||
            for row in 0..4 {
 | 
			
		||||
                if board.patterns[row].len() == (row + 1) {
 | 
			
		||||
                    let color = board.patterns[row].remove(0);
 | 
			
		||||
                    let index = Board::wall_index(color, row)?;
 | 
			
		||||
                    board.wall[row][index] = true;
 | 
			
		||||
                    board.score += board.connected((row, index));
 | 
			
		||||
 | 
			
		||||
                    self.box_top.append(&mut board.patterns[row])
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            let negative = match board.floor.len() {
 | 
			
		||||
                0 => 0,
 | 
			
		||||
                1 => 1,
 | 
			
		||||
                2 => 2,
 | 
			
		||||
                3 => 4,
 | 
			
		||||
                4 => 6,
 | 
			
		||||
                5 => 8,
 | 
			
		||||
                6 => 11,
 | 
			
		||||
                _ => 14
 | 
			
		||||
            };
 | 
			
		||||
            board.score -= negative;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
    pub fn do_move(&self, game_move: GameMove) -> Result<Game, &'static str> {
 | 
			
		||||
        
 | 
			
		||||
        if game_move.1 == Tile::Start {
 | 
			
		||||
            return Err("You can't take the start tile alone")
 | 
			
		||||
        }
 | 
			
		||||
@ -199,78 +322,121 @@ impl Game {
 | 
			
		||||
        match game_move {
 | 
			
		||||
            GameMove(_, Tile::Start, _) => return Err("You can't take the start tile specifically"),
 | 
			
		||||
            GameMove(0, _, 0) => {
 | 
			
		||||
                let mut hand = self.market.deref().clone();
 | 
			
		||||
                hand.retain(|&x| x == Tile::Start || x == game_move.1);
 | 
			
		||||
                game.market.retain(|&x| x != Tile::Start || x != game_move.1);
 | 
			
		||||
                board.floor.append(&mut hand)
 | 
			
		||||
                if self.market.contains(&game_move.1) {
 | 
			
		||||
                    let mut hand = self.market.deref().clone();
 | 
			
		||||
                    hand.retain(|&x| x == Tile::Start || x == game_move.1);
 | 
			
		||||
                    game.market.retain(|&x| x != Tile::Start || x != game_move.1);
 | 
			
		||||
                    
 | 
			
		||||
                    board.floor.append(&mut hand)
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    return Err("Market does not contain selected tile")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            GameMove(0, _, 1..=9) => {
 | 
			
		||||
                if self.market.len() == 0 {
 | 
			
		||||
                    return Err("Market is empty");
 | 
			
		||||
                }
 | 
			
		||||
                else if self.market.contains(&game_move.1) {
 | 
			
		||||
                    let target = &mut board.patterns[game_move.2 - 1];
 | 
			
		||||
                    let empty = game_move.2 - target.len();
 | 
			
		||||
 | 
			
		||||
                    if empty == 0 {
 | 
			
		||||
                        return Err("That pattern is full")
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    let mut hand = self.market.deref().clone();
 | 
			
		||||
                    hand.retain(|&x| x == Tile::Start || x == game_move.1);
 | 
			
		||||
                    game.market.retain(|&x| x != Tile::Start || x != game_move.1);
 | 
			
		||||
 | 
			
		||||
                    for tile in hand.drain(..) {
 | 
			
		||||
                        let empty = game_move.2 - &target.len();
 | 
			
		||||
                        if tile == Tile::Start {
 | 
			
		||||
                            board.floor.push(tile);
 | 
			
		||||
                        }
 | 
			
		||||
                        else {
 | 
			
		||||
                            if empty >= 1 {
 | 
			
		||||
                                target.push(tile);
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                board.floor.push(tile)
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    return Err("Market does not contain selected tile")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            GameMove(1..=9, _, _) => {
 | 
			
		||||
                let old_factory = &self.factories[game_move.0 - 1];
 | 
			
		||||
                if old_factory.contains(&game_move.1) {
 | 
			
		||||
                    
 | 
			
		||||
                    let mut new_factory = &mut game.factories[game_move.0 - 1];
 | 
			
		||||
    
 | 
			
		||||
                    let mut hand = old_factory.deref().clone();
 | 
			
		||||
    
 | 
			
		||||
                    hand.retain(|&x| x == game_move.1);
 | 
			
		||||
                    new_factory.retain(|&x| x != game_move.1);
 | 
			
		||||
 | 
			
		||||
                    game.market.append(&mut new_factory);
 | 
			
		||||
 | 
			
		||||
                    match game_move.2 {
 | 
			
		||||
                        0 => {
 | 
			
		||||
                            board.floor.append(&mut hand)
 | 
			
		||||
                        },
 | 
			
		||||
                        1..=9 => {
 | 
			
		||||
                            let target = &mut board.patterns[game_move.2 - 1];
 | 
			
		||||
                            let empty = game_move.2 - target.len();
 | 
			
		||||
                            if hand.len() <= empty {
 | 
			
		||||
                                target.append(&mut hand);
 | 
			
		||||
                            }
 | 
			
		||||
                            else if empty != 0 {
 | 
			
		||||
                                for tile in hand.drain(..) {
 | 
			
		||||
                                    let empty = game_move.2 - &target.len();
 | 
			
		||||
                                    if empty >= 1 {
 | 
			
		||||
                                        target.push(tile);
 | 
			
		||||
                                    }
 | 
			
		||||
                                    else {
 | 
			
		||||
                                        board.floor.push(tile)
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            else {
 | 
			
		||||
                                return Err("That pattern line is full")
 | 
			
		||||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                        _ => return Err("Not a valid destination")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    return Err("That tile is not in that factory")
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            GameMove(_,_,_) => return Err("Not a valid move")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let old_factory = match game_move.0 {
 | 
			
		||||
            0 => self.market.deref(),
 | 
			
		||||
            1..=9 => {
 | 
			
		||||
                if game_move.0 > self.factories.len() {
 | 
			
		||||
                    return Err("No factory with that indice")
 | 
			
		||||
                }
 | 
			
		||||
                self.factories[game_move.0 - 1].deref()
 | 
			
		||||
            },
 | 
			
		||||
            _ => return Err("Not a valid place to take tiles from")
 | 
			
		||||
        };
 | 
			
		||||
        let new_factory = match game_move.0 {
 | 
			
		||||
            0 => game.market.deref_mut(),
 | 
			
		||||
            1..=9 => game.factories[game_move.0 - 1].deref_mut(),
 | 
			
		||||
            _ => return Err("Not a valid place to take tiles from (new)")
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let sel_tile = game_move.1;
 | 
			
		||||
        let mut hand = old_factory.to_vec();
 | 
			
		||||
        hand.retain(|x| *x == sel_tile);
 | 
			
		||||
        if hand.len() == 0 {
 | 
			
		||||
            return Err("That tile is not in that factory")
 | 
			
		||||
        let mut empty = true;
 | 
			
		||||
        for factory in &game.factories {
 | 
			
		||||
            if factory.len() != 0 {
 | 
			
		||||
                empty = false;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        new_factory.retain(|x| *x != sel_tile);
 | 
			
		||||
        game.market.append(new_factory);
 | 
			
		||||
 | 
			
		||||
        if game_move.2 == 0 {
 | 
			
		||||
            board.floor.append(&mut hand);
 | 
			
		||||
            return Ok(game)
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let target: &mut Vec<Tile> = match game_move.2 {
 | 
			
		||||
            1..=5 => &mut board.patterns[game_move.2 - 1],
 | 
			
		||||
            _ => return Err("That's not a valid pattern line")
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        println!("{:#?}", target);
 | 
			
		||||
 | 
			
		||||
        if target.first() != None && target.first() != Some(&sel_tile) {
 | 
			
		||||
            return Err("You cannot place that tile on that pattern-line, because there are already other tiles with a different color there")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if target.len() == game_move.2 {
 | 
			
		||||
            return Err("That line is full!")
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let empty = game_move.2 - target.len();
 | 
			
		||||
        if hand.len() <= empty {
 | 
			
		||||
            target.append(&mut hand);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            for tile in hand.drain(..) {
 | 
			
		||||
                let empty = game_move.2 - &target.len();
 | 
			
		||||
                if empty >= 1 {
 | 
			
		||||
                    target.push(tile);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    board.floor.push(tile)
 | 
			
		||||
                }
 | 
			
		||||
        if empty == true {
 | 
			
		||||
            if game.market.len() != 0 {
 | 
			
		||||
                empty = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if empty == true {
 | 
			
		||||
            game.score()?;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            game.player = (game.player + 1) % self.boards.len();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        game.turn += 1;
 | 
			
		||||
        game.player = (game.player + 1) % self.boards.len();
 | 
			
		||||
 | 
			
		||||
        Ok(game)
 | 
			
		||||
    }
 | 
			
		||||
@ -288,4 +454,22 @@ fn bag() {
 | 
			
		||||
    let mut reds = bag.clone();
 | 
			
		||||
    reds.retain(|x| *x == Tile::Red);
 | 
			
		||||
    assert_eq!(reds.len(), 20);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn connected() -> Result<(), String> {
 | 
			
		||||
    let mut board = Board::default();
 | 
			
		||||
    board.wall[0] = [false, false, false, false, false];
 | 
			
		||||
    board.wall[1] = [true,  false, true,  false, false];
 | 
			
		||||
    board.wall[2] = [true,  false, true,  false, false];
 | 
			
		||||
    board.wall[3] = [true,  false, false, false, false];
 | 
			
		||||
    board.wall[4] = [true,  true,  true,  false, false];
 | 
			
		||||
 | 
			
		||||
    let coordinate = (4 as usize, Board::wall_index(Tile::Yellow, 4)?);
 | 
			
		||||
    assert_eq!(coordinate, (4,0));
 | 
			
		||||
 | 
			
		||||
    let score = board.connected(coordinate);
 | 
			
		||||
 | 
			
		||||
    assert_eq!(score, 7);
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
@ -6,8 +6,8 @@ fn main() -> Result<(), &'static str>{
 | 
			
		||||
    let mut game = Game::new(2)?;
 | 
			
		||||
    game.fill()?;
 | 
			
		||||
    println!("{:#?}", game);
 | 
			
		||||
    let game2 = game.do_move(GameMove(0, Tile::Red, 2))?;
 | 
			
		||||
    let game2 = game2.do_move(GameMove(1, Tile::Red, 2))?;
 | 
			
		||||
    let game2 = game.do_move(GameMove(1, Tile::Red, 1))?;
 | 
			
		||||
    let game2 = game2.do_move(GameMove(0, Tile::Blue, 1))?;
 | 
			
		||||
    println!("{:#?}", game2);
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user