scoring
This commit is contained in:
parent
b64521169b
commit
7f98ea6afe
|
@ -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
|
let
|
||||||
moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
|
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 {
|
rustNightlyChannel = (nixpkgs.rustChannelOf { date = "2020-03-19"; channel = "nightly"; }).rust.override {
|
||||||
extensions = [
|
extensions = [
|
||||||
"rust-src"
|
"rust-src"
|
||||||
|
@ -23,5 +23,12 @@ with nixpkgs;
|
||||||
name = "moz_overlay_shell";
|
name = "moz_overlay_shell";
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
rustStableChannel
|
rustStableChannel
|
||||||
|
(vscode-with-extensions.override {
|
||||||
|
vscodeExtensions = with vscode-extensions; [
|
||||||
|
bbenoist.Nix
|
||||||
|
vadimcn.vscode-lldb
|
||||||
|
matklad.rust-analyzer
|
||||||
|
];
|
||||||
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
284
src/azul.rs
284
src/azul.rs
|
@ -12,6 +12,7 @@ pub enum Tile {
|
||||||
}
|
}
|
||||||
|
|
||||||
// factory, color, pattern line
|
// factory, color, pattern line
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct GameMove (pub usize, pub Tile, pub usize);
|
pub struct GameMove (pub usize, pub Tile, pub usize);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -112,6 +113,102 @@ struct Board {
|
||||||
floor: Vec<Tile>,
|
floor: Vec<Tile>,
|
||||||
patterns: Patterns,
|
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 {
|
impl Default for Board {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Board {
|
Board {
|
||||||
|
@ -186,6 +283,32 @@ impl Game {
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
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> {
|
pub fn do_move(&self, game_move: GameMove) -> Result<Game, &'static str> {
|
||||||
|
|
||||||
if game_move.1 == Tile::Start {
|
if game_move.1 == Tile::Start {
|
||||||
|
@ -199,65 +322,76 @@ impl Game {
|
||||||
match game_move {
|
match game_move {
|
||||||
GameMove(_, Tile::Start, _) => return Err("You can't take the start tile specifically"),
|
GameMove(_, Tile::Start, _) => return Err("You can't take the start tile specifically"),
|
||||||
GameMove(0, _, 0) => {
|
GameMove(0, _, 0) => {
|
||||||
|
if self.market.contains(&game_move.1) {
|
||||||
let mut hand = self.market.deref().clone();
|
let mut hand = self.market.deref().clone();
|
||||||
hand.retain(|&x| x == Tile::Start || x == game_move.1);
|
hand.retain(|&x| x == Tile::Start || x == game_move.1);
|
||||||
game.market.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)
|
board.floor.append(&mut hand)
|
||||||
},
|
},
|
||||||
GameMove(_,_,_) => return Err("Not a valid move")
|
|
||||||
}
|
|
||||||
|
|
||||||
let old_factory = match game_move.0 {
|
|
||||||
0 => self.market.deref(),
|
|
||||||
1..=9 => {
|
1..=9 => {
|
||||||
if game_move.0 > self.factories.len() {
|
let target = &mut board.patterns[game_move.2 - 1];
|
||||||
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")
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
let empty = game_move.2 - target.len();
|
||||||
if hand.len() <= empty {
|
if hand.len() <= empty {
|
||||||
target.append(&mut hand);
|
target.append(&mut hand);
|
||||||
}
|
}
|
||||||
else {
|
else if empty != 0 {
|
||||||
for tile in hand.drain(..) {
|
for tile in hand.drain(..) {
|
||||||
let empty = game_move.2 - &target.len();
|
let empty = game_move.2 - &target.len();
|
||||||
if empty >= 1 {
|
if empty >= 1 {
|
||||||
|
@ -268,9 +402,41 @@ impl Game {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 mut empty = true;
|
||||||
|
for factory in &game.factories {
|
||||||
|
if factory.len() != 0 {
|
||||||
|
empty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.turn += 1;
|
||||||
game.player = (game.player + 1) % self.boards.len();
|
|
||||||
|
|
||||||
Ok(game)
|
Ok(game)
|
||||||
}
|
}
|
||||||
|
@ -289,3 +455,21 @@ fn bag() {
|
||||||
reds.retain(|x| *x == Tile::Red);
|
reds.retain(|x| *x == Tile::Red);
|
||||||
assert_eq!(reds.len(), 20);
|
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)?;
|
let mut game = Game::new(2)?;
|
||||||
game.fill()?;
|
game.fill()?;
|
||||||
println!("{:#?}", game);
|
println!("{:#?}", game);
|
||||||
let game2 = game.do_move(GameMove(0, Tile::Red, 2))?;
|
let game2 = game.do_move(GameMove(1, Tile::Red, 1))?;
|
||||||
let game2 = game2.do_move(GameMove(1, Tile::Red, 2))?;
|
let game2 = game2.do_move(GameMove(0, Tile::Blue, 1))?;
|
||||||
println!("{:#?}", game2);
|
println!("{:#?}", game2);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue