Compare commits

..

1 Commits

Author SHA1 Message Date
Daniel Olsen 9dd402d493 start cache work 2021-03-06 16:44:11 +01:00
8 changed files with 365 additions and 1283 deletions

3
.gitignore vendored
View File

@ -1,4 +1 @@
/target /target
/flamegraph.svg
/perf.data
/perf.data.old

View File

@ -1,52 +0,0 @@
image: "rustlang/rust:nightly-buster"
# Optional: Install a C compiler, cmake and git into the container.
# You will often need this when you (or any of your dependencies) depends on C code.
before_script:
- apt-get update -yqq
- apt-get install -yqq mingw-w64 coz-profiler
variables:
CARGO_HOME: $CI_PROJECT_DIR/cargo
APT_CACHE_DIR: $CI_PROJECT_DIR/apt
cache:
key: all
paths:
- apt/
- cargo/
- target/
stages:
- build
build:linux-glibc:
stage: build
script:
- cargo build --release
artifacts:
paths:
- target/release/mercury
build:windows:
stage: build
script:
- mkdir .cargo && echo -e "[target.x86_64-pc-windows-gnu]\nlinker = \"x86_64-w64-mingw32-gcc\"\nar = \"x86_64-w64-mingw32-gcc-ar\"" > .cargo/config
- apt-get update -yqq
- apt-get install -yqq mingw-w64
- rustup target add x86_64-pc-windows-gnu
- cargo build --release --target=x86_64-pc-windows-gnu
artifacts:
paths:
- target/x86_64-pc-windows-gnu/release/mercury.exe
build:linux-musl:
stage: build
script:
- rustup target add x86_64-unknown-linux-musl
- cargo build --release --target x86_64-unknown-linux-musl
artifacts:
paths:
- target/x86_64-unknown-linux-musl/release/mercury

383
Cargo.lock generated
View File

@ -1,96 +1,10 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "async-mutex"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
dependencies = [
"event-listener",
]
[[package]]
name = "async-trait"
version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "byte-strings"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963ceed6e0041e1f4cdd9e2fae3b384f5613a22119b5bb04ccc14fc815e87ae3"
dependencies = [
"byte-strings-proc_macros",
]
[[package]]
name = "byte-strings-proc_macros"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e78e8673d97234c7a07636474b02c92fad06a0f26f70581aa46aee124c508e5"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cached"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e2afe73808fbaac302e39c9754bfc3c4b4d0f99c9c240b9f4e4efc841ad1b74"
dependencies = [
"async-mutex",
"async-trait",
"cached_proc_macro",
"cached_proc_macro_types",
"futures",
"hashbrown",
"once_cell",
]
[[package]]
name = "cached_proc_macro"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4230b8d9f5db741004bfaef172c5b2dbf0eb94f105204cc6147a220080daaa85"
dependencies = [
"cached_proc_macro_types",
"darling",
"quote",
"syn",
]
[[package]]
name = "cached_proc_macro_types"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "coz" name = "coz"
@ -102,270 +16,61 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "darling"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "event-listener"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "futures"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
[[package]]
name = "futures-executor"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-macro"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
[[package]]
name = "futures-task"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
[[package]]
name = "futures-util"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.4" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"wasi", "wasi",
] ]
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.118" version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]] [[package]]
name = "mercury" name = "mercury"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ahash",
"byte-strings",
"cached",
"coz", "coz",
"modular-bitfield",
"rand", "rand",
"thousands",
"tinyvec", "tinyvec",
] ]
[[package]]
name = "modular-bitfield"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
dependencies = [
"modular-bitfield-impl",
"static_assertions",
]
[[package]]
name = "modular-bitfield-impl"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.9.0" version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "pin-project-lite"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.16" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" checksum = "a76330fb486679b4ace3670f117bbc9e16204005c4bde9c4bd372f45bed34f12"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha", "rand_chacha",
"rand_core", "rand_core",
"rand_hc",
] ]
[[package]] [[package]]
name = "rand_chacha" name = "rand_chacha"
version = "0.3.1" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core", "rand_core",
@ -373,68 +78,30 @@ dependencies = [
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.6.3" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" checksum = "a8b34ba8cfb21243bd8df91854c830ff0d785fff2e82ebd4434c2644cb9ada18"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]
[[package]] [[package]]
name = "slab" name = "rand_hc"
version = "0.4.5" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [ dependencies = [
"proc-macro2", "rand_core",
"quote",
"unicode-xid",
] ]
[[package]]
name = "thousands"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.5.1" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"

View File

@ -7,26 +7,17 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
rand = "0.8.1" rand = "0.8.0"
coz = "0.1" coz = "0.1"
tinyvec = "1.1.0" tinyvec = "1.1.0"
cached = "0.23.0"
ahash = "0.7.2"
thousands = "0.2.0"
modular-bitfield = "0.11.2"
byte-strings = "0.2.2"
#jemallocator = "0.3.2" #jemallocator = "0.3.2"
#mimalloc = { version = "0.1.22", default-features = false } #mimalloc = { version = "0.1.22", default-features = false }
#alloc_counter = "0.0.4" #alloc_counter = "0.0.4"
[profile.release] [profile.release]
debug = 0 debug = 1
lto = "fat" lto = "fat"
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"

View File

@ -1,38 +1,39 @@
let let
pkgs = import <nixos-unstable> { }; moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
fenix = import (fetchTarball "https://github.com/nix-community/fenix/archive/main.tar.gz") { }; nixpkgs = import <nixos-unstable> { overlays = [ moz_overlay ]; };
in rustNightlyChannel = (nixpkgs.rustChannelOf { date = "2020-03-19"; channel = "nightly"; }).rust.override {
with pkgs; extensions = [
{ windows-cross ? false }: "rust-src"
stdenv.mkDerivation { "rls-preview"
name = "rust_shell"; "clippy-preview"
"rustfmt-preview"
nativeBuildInputs = []
++ lib.optionals windows-cross [
pkgsCross.mingwW64.stdenv.cc
]; ];
};
rustStableChannel = nixpkgs.latest.rustChannels.stable.rust.override {
extensions = [
"rust-src"
"rls-preview"
"clippy-preview"
"rustfmt-preview"
];
};
in
with nixpkgs;
stdenv.mkDerivation {
name = "moz_overlay_shell";
buildInputs = [ buildInputs = [
(fenix.combine ([ rustStableChannel
fenix.complete.toolchain
] ++ lib.optionals windows-cross [
fenix.targets.x86_64-pc-windows-gnu.latest.rust-std
]))
(vscode-with-extensions.override { (vscode-with-extensions.override {
vscodeExtensions = with vscode-extensions; [ vscodeExtensions = with vscode-extensions; [
bbenoist.nix bbenoist.Nix
vadimcn.vscode-lldb vadimcn.vscode-lldb
fenix.rust-analyzer-vscode-extension matklad.rust-analyzer
]; ];
}) })
coz
# cargo-flamegraph cargo-flamegraph
cmake
# cmake gcc
# gcc llvm_11
# llvm_11
] ++ lib.optionals windows-cross [
pkgsCross.mingwW64.windows.mingw_w64_pthreads
]; ];
} }

View File

@ -1,15 +1,11 @@
use std::{hash::Hash, ops::{Deref, DerefMut}}; use std::ops::{Deref, DerefMut};
use rand::prelude::*; use rand::prelude::*;
use rand::distributions::WeightedIndex;
//use smallvec::{SmallVec, smallvec}; //use smallvec::{SmallVec, smallvec};
//use alloc_counter::{AllocCounterSystem, no_alloc}; //use alloc_counter::{AllocCounterSystem, no_alloc};
//#[global_allocator] //#[global_allocator]
//static A: AllocCounterSystem = AllocCounterSystem; //static A: AllocCounterSystem = AllocCounterSystem;
extern crate byte_strings;
use ::byte_strings::concat_bytes;
pub fn size_of_stuff() { pub fn size_of_stuff() {
println!("size of azul game: {}", std::mem::size_of::<Game>()); println!("size of azul game: {}", std::mem::size_of::<Game>());
println!("size of azul tile: {}", std::mem::size_of::<Tile>()); println!("size of azul tile: {}", std::mem::size_of::<Tile>());
@ -26,9 +22,8 @@ pub fn size_of_stuff() {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum Tile { pub enum Tile {
// None,
Start, Start,
Blue, Blue,
Yellow, Yellow,
@ -39,7 +34,6 @@ pub enum Tile {
impl Default for Tile { impl Default for Tile {
fn default() -> Self { fn default() -> Self {
// Tile::None
Tile::Blue Tile::Blue
} }
} }
@ -55,15 +49,6 @@ impl IntoIterator for Tile {
} }
} }
/*impl From<Option<Tile>> for Tile {
fn from(option: Option<Tile>) -> Tile {
match option {
Option::None => Tile::None,
Some(tile) => tile
}
}
}*/
pub struct TileIter { pub struct TileIter {
current: Tile current: Tile
} }
@ -175,46 +160,7 @@ impl Iterator for GameMoveIter {
} }
} }
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Copy)]
struct Bag {
blue: u8,
yellow: u8,
red: u8,
black: u8,
teal: u8,
}
impl Default for Bag {
fn default() -> Self {
Bag {
blue: 20,
yellow: 20,
red: 20,
black: 20,
teal: 20,
}
}
}
impl Bag {
fn len(&self) -> u8 {
self.blue + self.yellow + self.red + self.black + self.teal
}
fn is_empty(&self) -> bool {
self.len() == 0
}
fn hash(&self) -> [u8; 5] {
[
self.blue,
self.yellow,
self.red,
self.black,
self.teal
]
}
}
/*#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)]
struct Bag (tinyvec::ArrayVec::<[Tile; 128]>); struct Bag (tinyvec::ArrayVec::<[Tile; 128]>);
impl Default for Bag { impl Default for Bag {
@ -257,11 +203,32 @@ impl From<tinyvec::ArrayVec<[Tile; 128]>> for Bag {
fn from(vector: tinyvec::ArrayVec<[Tile; 128]>) -> Bag { fn from(vector: tinyvec::ArrayVec<[Tile; 128]>) -> Bag {
Bag(vector) Bag(vector)
} }
}*/ }
trait Compress {
fn compress(&self) -> usize;
}
#[derive(Default, Debug, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] impl Compress for Bag {
struct Factory (tinyvec::ArrayVec<[Tile; 4]>); fn compress(&self) -> usize {
let blue = self.iter().filter(|&&t| t == Tile::Blue).count();
let yellow = self.iter().filter(|&&t| t == Tile::Yellow).count();
let red = self.iter().filter(|&&t| t == Tile::Red).count();
let black = self.iter().filter(|&&t| t == Tile::Black).count();
let teal = self.iter().filter(|&&t| t == Tile::Teal).count();
let compressed = blue*21_usize.pow(0)
+ yellow*21_usize.pow(1)
+ red*21_usize.pow(2)
+ black*21_usize.pow(3)
+ teal*21_usize.pow(4);
compressed
}
}
#[derive(Default, Debug, Copy)]
struct Factory (tinyvec::ArrayVec<[Option<Tile>; 4]>);
impl Clone for Factory { impl Clone for Factory {
//#[no_alloc] //#[no_alloc]
fn clone(&self) -> Self { fn clone(&self) -> Self {
@ -269,20 +236,235 @@ impl Clone for Factory {
} }
} }
impl Deref for Factory { impl Deref for Factory {
type Target = tinyvec::ArrayVec<[Tile; 4]>; type Target = tinyvec::ArrayVec<[Option<Tile>; 4]>;
fn deref(&self) -> &tinyvec::ArrayVec<[Tile; 4]> { fn deref(&self) -> &tinyvec::ArrayVec<[Option<Tile>; 4]> {
&self.0 &self.0
} }
} }
impl DerefMut for Factory { impl DerefMut for Factory {
fn deref_mut(&mut self) -> &mut tinyvec::ArrayVec<[Tile; 4]> { fn deref_mut(&mut self) -> &mut tinyvec::ArrayVec<[Option<Tile>; 4]> {
&mut self.0 &mut self.0
} }
} }
impl Compress for Factory {
// Assumes factory is sorted!
fn compress(&self) -> usize {
match self[..] {
[Option::None, Option::None, Option::None, Option::None] => 0,
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] [Option::None, Option::None, Option::None, Some(Tile::Blue)] => 1,
[Option::None, Option::None, Option::None, Some(Tile::Yellow)] => 2,
[Option::None, Option::None, Option::None, Some(Tile::Red)] => 3,
[Option::None, Option::None, Option::None, Some(Tile::Black)] => 4,
[Option::None, Option::None, Option::None, Some(Tile::Teal)] => 5,
[Option::None, Option::None, Some(Tile::Blue), Some(Tile::Blue)] => 6,
[Option::None, Option::None, Some(Tile::Blue), Some(Tile::Yellow)] => 7,
[Option::None, Option::None, Some(Tile::Blue), Some(Tile::Red)] => 8,
[Option::None, Option::None, Some(Tile::Blue), Some(Tile::Black)] => 9,
[Option::None, Option::None, Some(Tile::Blue), Some(Tile::Teal)] => 10,
[Option::None, Option::None, Some(Tile::Yellow), Some(Tile::Yellow)] => 11,
[Option::None, Option::None, Some(Tile::Yellow), Some(Tile::Red)] => 12,
[Option::None, Option::None, Some(Tile::Yellow), Some(Tile::Black)] => 13,
[Option::None, Option::None, Some(Tile::Yellow), Some(Tile::Teal)] => 14,
[Option::None, Option::None, Some(Tile::Red), Some(Tile::Red)] => 15,
[Option::None, Option::None, Some(Tile::Red), Some(Tile::Black)] => 16,
[Option::None, Option::None, Some(Tile::Red), Some(Tile::Teal)] => 17,
[Option::None, Option::None, Some(Tile::Black), Some(Tile::Black)] => 18,
[Option::None, Option::None, Some(Tile::Black), Some(Tile::Teal)] => 19,
[Option::None, Option::None, Some(Tile::Teal), Some(Tile::Teal)] => 20,
[Option::None, Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue)] => 21,
[Option::None, Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Yellow)] => 22,
[Option::None, Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Red)] => 23,
[Option::None, Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Black)] => 24,
[Option::None, Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Teal)] => 25,
[Option::None, Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Yellow)] => 26,
[Option::None, Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Red)] => 27,
[Option::None, Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Black)] => 28,
[Option::None, Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Teal)] => 29,
[Option::None, Some(Tile::Blue), Some(Tile::Red), Some(Tile::Red)] => 30,
[Option::None, Some(Tile::Blue), Some(Tile::Red), Some(Tile::Black)] => 31,
[Option::None, Some(Tile::Blue), Some(Tile::Red), Some(Tile::Teal)] => 32,
[Option::None, Some(Tile::Blue), Some(Tile::Black), Some(Tile::Black)] => 33,
[Option::None, Some(Tile::Blue), Some(Tile::Black), Some(Tile::Teal)] => 34,
[Option::None, Some(Tile::Blue), Some(Tile::Teal), Some(Tile::Teal)] => 35,
[Option::None, Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow)] => 36,
[Option::None, Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Red)] => 37,
[Option::None, Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Black)] => 38,
[Option::None, Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Teal)] => 39,
[Option::None, Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Red)] => 40,
[Option::None, Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Black)] => 41,
[Option::None, Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Teal)] => 42,
[Option::None, Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Black)] => 43,
[Option::None, Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Teal)] => 44,
[Option::None, Some(Tile::Yellow), Some(Tile::Teal), Some(Tile::Teal)] => 45,
[Option::None, Some(Tile::Red), Some(Tile::Red), Some(Tile::Red)] => 46,
[Option::None, Some(Tile::Red), Some(Tile::Red), Some(Tile::Black)] => 47,
[Option::None, Some(Tile::Red), Some(Tile::Red), Some(Tile::Teal)] => 48,
[Option::None, Some(Tile::Red), Some(Tile::Black), Some(Tile::Black)] => 49,
[Option::None, Some(Tile::Red), Some(Tile::Black), Some(Tile::Teal)] => 50,
[Option::None, Some(Tile::Red), Some(Tile::Teal), Some(Tile::Teal)] => 51,
[Option::None, Some(Tile::Black), Some(Tile::Black), Some(Tile::Black)] => 52,
[Option::None, Some(Tile::Black), Some(Tile::Black), Some(Tile::Teal)] => 53,
[Option::None, Some(Tile::Black), Some(Tile::Teal), Some(Tile::Teal)] => 54,
[Option::None, Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal)] => 55,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue)] => 56,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Yellow)] => 57,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Red)] => 58,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Black)] => 59,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Teal)] => 60,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Yellow)] => 61,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Red)] => 62,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Black)] => 63,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Teal)] => 64,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Red), Some(Tile::Red)] => 65,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Red), Some(Tile::Black)] => 66,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Red), Some(Tile::Teal)] => 67,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Black), Some(Tile::Black)] => 68,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Black), Some(Tile::Teal)] => 69,
[Some(Tile::Blue), Some(Tile::Blue), Some(Tile::Teal), Some(Tile::Teal)] => 70,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow)] => 71,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Red)] => 72,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Black)] => 73,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Teal)] => 74,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Red)] => 75,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Black)] => 76,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Teal)] => 77,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Black)] => 78,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Teal)] => 79,
[Some(Tile::Blue), Some(Tile::Yellow), Some(Tile::Teal), Some(Tile::Teal)] => 80,
[Some(Tile::Blue), Some(Tile::Red), Some(Tile::Red), Some(Tile::Red)] => 81,
[Some(Tile::Blue), Some(Tile::Red), Some(Tile::Red), Some(Tile::Black)] => 82,
[Some(Tile::Blue), Some(Tile::Red), Some(Tile::Red), Some(Tile::Teal)] => 83,
[Some(Tile::Blue), Some(Tile::Red), Some(Tile::Black), Some(Tile::Black)] => 84,
[Some(Tile::Blue), Some(Tile::Red), Some(Tile::Black), Some(Tile::Teal)] => 85,
[Some(Tile::Blue), Some(Tile::Red), Some(Tile::Teal), Some(Tile::Teal)] => 86,
[Some(Tile::Blue), Some(Tile::Black), Some(Tile::Black), Some(Tile::Black)] => 87,
[Some(Tile::Blue), Some(Tile::Black), Some(Tile::Black), Some(Tile::Teal)] => 88,
[Some(Tile::Blue), Some(Tile::Black), Some(Tile::Teal), Some(Tile::Teal)] => 89,
[Some(Tile::Blue), Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal)] => 90,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow)] => 91,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Red)] => 92,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Black)] => 93,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Teal)] => 94,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Red)] => 95,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Black)] => 96,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Teal)] => 97,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Black)] => 98,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Teal)] => 99,
[Some(Tile::Yellow), Some(Tile::Yellow), Some(Tile::Teal), Some(Tile::Teal)] => 100,
[Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Red), Some(Tile::Red)] => 101,
[Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Red), Some(Tile::Black)] => 102,
[Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Red), Some(Tile::Teal)] => 103,
[Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Black), Some(Tile::Black)] => 104,
[Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Black), Some(Tile::Teal)] => 105,
[Some(Tile::Yellow), Some(Tile::Red), Some(Tile::Teal), Some(Tile::Teal)] => 106,
[Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Black), Some(Tile::Black)] => 107,
[Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Black), Some(Tile::Teal)] => 108,
[Some(Tile::Yellow), Some(Tile::Black), Some(Tile::Teal), Some(Tile::Teal)] => 109,
[Some(Tile::Yellow), Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal)] => 110,
[Some(Tile::Red), Some(Tile::Red), Some(Tile::Red), Some(Tile::Red)] => 111,
[Some(Tile::Red), Some(Tile::Red), Some(Tile::Red), Some(Tile::Black)] => 112,
[Some(Tile::Red), Some(Tile::Red), Some(Tile::Red), Some(Tile::Teal)] => 113,
[Some(Tile::Red), Some(Tile::Red), Some(Tile::Black), Some(Tile::Black)] => 114,
[Some(Tile::Red), Some(Tile::Red), Some(Tile::Black), Some(Tile::Teal)] => 115,
[Some(Tile::Red), Some(Tile::Red), Some(Tile::Teal), Some(Tile::Teal)] => 116,
[Some(Tile::Red), Some(Tile::Black), Some(Tile::Black), Some(Tile::Black)] => 117,
[Some(Tile::Red), Some(Tile::Black), Some(Tile::Black), Some(Tile::Teal)] => 118,
[Some(Tile::Red), Some(Tile::Black), Some(Tile::Teal), Some(Tile::Teal)] => 119,
[Some(Tile::Red), Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal)] => 120,
[Some(Tile::Black), Some(Tile::Black), Some(Tile::Black), Some(Tile::Black)] => 121,
[Some(Tile::Black), Some(Tile::Black), Some(Tile::Black), Some(Tile::Teal)] => 122,
[Some(Tile::Black), Some(Tile::Black), Some(Tile::Teal), Some(Tile::Teal)] => 123,
[Some(Tile::Black), Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal)] => 124,
[Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal), Some(Tile::Teal)] => 125,
}
}
}
#[derive(Debug, Clone, Copy)]
struct Market (tinyvec::ArrayVec<[Tile; 28]>); struct Market (tinyvec::ArrayVec<[Tile; 28]>);
impl Default for Market { impl Default for Market {
fn default() -> Self { fn default() -> Self {
@ -310,7 +492,7 @@ type Patterns = [tinyvec::ArrayVec<[Tile; 5]>; 5];
type Row = [bool; 5]; type Row = [bool; 5];
type Wall = [Row; 5]; type Wall = [Row; 5];
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Default, Copy)]
struct Board { struct Board {
score: u8, score: u8,
wall: Wall, wall: Wall,
@ -414,37 +596,34 @@ impl Board {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] //#[repr(align(16))]
pub struct State { #[derive(Debug, Clone, Copy)]
player: u8, pub struct Game {
turn: u32,
player: usize,
box_top: Bag, box_top: Bag,
bag: Bag, bag: Bag,
market: Market, market: Market,
factories: tinyvec::ArrayVec<[Factory; 5]>, // TODO set to 9? factories: tinyvec::ArrayVec<[Factory; 9]>, // TODO set to 9?
boards: tinyvec::ArrayVec<[Board; 2]> // TODO set to 4? boards: tinyvec::ArrayVec<[Board; 4]> // TODO set to 4?
} }
impl State { impl Game {
pub fn new(players: u8) -> Result<State, &'static str> { pub fn new(players: u8) -> Result<Game, &'static str> {
let n_factories = get_n_factories(players)?; let n_factories = get_n_factories(players)?;
let mut factories = tinyvec::ArrayVec::<[Factory; 5]>::new(); let mut factories = tinyvec::ArrayVec::<[Factory; 9]>::new();
for _ in 0..n_factories { for _ in 0..n_factories {
factories.push(Factory::default()) factories.push(Factory::default())
} }
let mut boards = tinyvec::ArrayVec::<[Board; 2]>::new(); let mut boards = tinyvec::ArrayVec::<[Board; 4]>::new();
for _ in 0..players { for _ in 0..players {
boards.push(Board::default()); boards.push(Board::default());
} }
let game = State { let game = Game {
turn: 0,
player: 0, player: 0,
box_top: Bag { box_top: Bag(tinyvec::ArrayVec::<[Tile; 128]>::new()),
blue: 0,
yellow: 0,
red: 0,
black: 0,
teal: 0,
},
bag: Bag::default(), bag: Bag::default(),
market: Market::default(), market: Market::default(),
factories: factories, factories: factories,
@ -461,33 +640,22 @@ impl State {
}; };
for factory in &mut self.factories { for factory in &mut self.factories {
for _ in 0..4 { for _ in 0..4 {
if self.bag.is_empty() && !self.box_top.is_empty() { if self.bag.len() == 0 && self.box_top.len() > 0 {
self.bag = self.box_top; self.bag.append(&mut self.box_top);
self.box_top = Bag { blue: 0, yellow: 0, red: 0, black: 0, teal: 0};
} }
else if self.bag.is_empty() { else if self.bag.len() == 0 {
factory.sort_unstable();
return Ok(()) return Ok(())
} }
else { else {
let choices = [Tile::Blue, Tile::Yellow, Tile::Red, Tile::Black, Tile::Teal]; let tile_i:usize = rng.gen_range(0..self.bag.len());
let weights = [self.bag.blue, self.bag.yellow, self.bag.red, self.bag.black, self.bag.teal]; let tile = self.bag.remove(tile_i);
let dist = WeightedIndex::new(&weights).unwrap(); factory.push(tile);
let tile = choices[dist.sample(&mut rng)];
match tile {
Tile::Start => {return Err("This should never happen")}
Tile::Blue => {self.bag.blue -= 1}
Tile::Yellow => {self.bag.yellow -= 1}
Tile::Red => {self.bag.red -= 1}
Tile::Black => {self.bag.black -= 1}
Tile::Teal => {self.bag.teal -= 1}
}
factory.push(tile)
} }
} }
factory.sort_unstable(); factory.sort_unstable();
println!("{}", factory.compress());
}; };
self.factories.sort_unstable();
Ok(()) Ok(())
} }
fn score(&mut self) -> Result<(), &'static str> { fn score(&mut self) -> Result<(), &'static str> {
@ -499,15 +667,7 @@ impl State {
board.wall[row][index] = true; board.wall[row][index] = true;
board.score += board.connected((row, index)); board.score += board.connected((row, index));
match color { self.box_top.extend_from_slice(board.patterns[row].as_slice());
Tile::Start => {return Err("This should never happen")}
Tile::Blue => {self.box_top.blue += (row as u8 + 1)}
Tile::Yellow => {self.box_top.yellow += (row as u8 + 1)}
Tile::Red => {self.box_top.red += (row as u8 + 1)}
Tile::Black => {self.box_top.black += (row as u8 + 1)}
Tile::Teal => {self.box_top.teal += (row as u8 + 1)}
}
//self.box_top.extend_from_slice(board.patterns[row].as_slice());
board.patterns[row].clear(); board.patterns[row].clear();
} }
} }
@ -525,8 +685,9 @@ impl State {
} }
Ok(()) Ok(())
} }
// #[no_alloc(forbid)]
pub fn do_move(&mut self, game_move: GameMove) -> Result<(), &'static str> { pub fn do_move(&mut self, game_move: GameMove) -> Result<(), &'static str> {
let board = &mut self.boards[self.player as usize]; let board = &mut self.boards[self.player];
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) => {
@ -581,7 +742,7 @@ impl State {
} }
}, },
GameMove(1..=9, _, _) => { GameMove(1..=9, _, _) => {
let board = &mut self.boards[self.player as usize]; let board = &mut self.boards[self.player];
if game_move.0 > self.factories.len() { if game_move.0 > self.factories.len() {
return Err("That factory is out of bounds"); return Err("That factory is out of bounds");
} }
@ -655,127 +816,9 @@ impl State {
self.player = (self.player + 1) % self.boards.len(); self.player = (self.player + 1) % self.boards.len();
} }
*/ */
self.player = (self.player + 1) % self.boards.len();
self.factories.sort_unstable();
self.market.sort();
for board in &mut self.boards {
board.floor.sort_unstable();
}
self.player = (self.player + 1) % self.boards.len() as u8;
Ok(())
}
pub fn is_legal(&self, game_move: GameMove) -> Result<(), &'static str> {
let board = &self.boards[self.player as usize];
match game_move {
GameMove(_, Tile::Start, _) => return Err("You can't take the start tile specifically"),
GameMove(0, _, 0) => {
if !&self.market.contains(&game_move.1) {
return Err("Market does not contain selected tile")
}
else {
Ok(())
}
},
GameMove(0, _, 1..=5) => {
if self.market.len() == 0 {
return Err("Market is empty");
}
else if self.market.contains(&game_move.1) {
let target = &board.patterns[game_move.2 - 1];
if target.first().is_some() && target[0] != game_move.1 {
return Err("That pattern line already contains a different color")
}
let empty = game_move.2 - target.len();
if empty == 0 {
return Err("That pattern is full")
}
Ok(())
}
else {
return Err("Market does not contain selected tile")
}
},
GameMove(1..=9, _, _) => {
let board = &self.boards[self.player as usize];
if game_move.0 > self.factories.len() {
return Err("That factory is out of bounds");
}
let factory = self.factories[game_move.0 - 1].deref();
if factory.contains(&game_move.1) {
let mut hand = factory.clone();
hand.retain(|x| *x == game_move.1);
match game_move.2 {
0 => Ok(()),
1..=9 => {
let target = &board.patterns[game_move.2 - 1];
if target.first().is_some() && target[0] != game_move.1 {
return Err("That pattern line already contains a different color")
}
let empty = game_move.2 - target.len();
if hand.len() <= empty {
return Ok(())
}
else if empty != 0 {
return Ok(())
}
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")
}
}
/*pub fn hash(&self) -> [u8; 256]{
[
[self.player],
self.box_top.hash(),
self.bag.hash()
].concat()
}*/
}
//#[repr(align(16))]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Game {
pub state: State,
pub turn: u32,
}
impl Game {
pub fn new(players: u8) -> Result<Game, &'static str> {
let game = Game {
state: State::new(players)?,
turn: 0
};
Ok(game)
}
pub fn do_move(&mut self, game_move: GameMove) -> Result<(), &'static str> {
let result = self.state.do_move(game_move);
self.turn += 1; self.turn += 1;
result Ok(())
}
}
impl Deref for Game {
type Target = State;
fn deref(&self) -> &Self::Target {
&self.state
}
}
impl DerefMut for Game {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.state
} }
} }
@ -797,44 +840,15 @@ pub fn complicated() -> Result<Game, &'static str> {
Ok(game) Ok(game)
} }
pub fn some_game() -> Result<Game, &'static str> { #[test]
let mut game = Game::new(2)?; fn bag() {
let game = Game::new(2).unwrap();
let bag = game.bag;
assert_eq!(bag.len(), 100);
let factories = &mut game.factories; let mut reds = bag.clone();
reds.retain(|x| *x == Tile::Red);
factories[0].push(Tile::Blue); assert_eq!(reds.len(), 20);
factories[0].push(Tile::Blue);
factories[0].push(Tile::Yellow);
factories[0].push(Tile::Black);
factories[1].push(Tile::Blue);
factories[1].push(Tile::Red);
factories[1].push(Tile::Red);
factories[1].push(Tile::Red);
factories[2].push(Tile::Blue);
factories[2].push(Tile::Red);
factories[2].push(Tile::Black);
factories[2].push(Tile::Teal);
factories[3].push(Tile::Blue);
factories[3].push(Tile::Red);
factories[3].push(Tile::Black);
factories[3].push(Tile::Teal);
factories[4].push(Tile::Yellow);
factories[4].push(Tile::Yellow);
factories[4].push(Tile::Black);
factories[4].push(Tile::Teal);
let bag = &mut game.bag;
bag.blue -= 5;
bag.yellow -= 3;
bag.black -= 4;
bag.red -= 5;
bag.teal -= 3;
Ok(game)
} }
#[test] #[test]
@ -861,7 +875,7 @@ fn game_move_iter() {
println!("Original: {:?}", i); println!("Original: {:?}", i);
assert_eq!(i.into_iter().next().unwrap(), GameMove(1, Tile::Blue, 1)); assert_eq!(i.into_iter().next().unwrap(), GameMove(1, Tile::Blue, 1));
//assert_eq!(i.into_iter().count(), 5) assert_eq!(i.into_iter().count(), 5)
} }
#[test] #[test]

View File

@ -1,518 +0,0 @@
#![feature(bench_black_box)]
use rand::prelude::*;
use rand::distributions::WeightedIndex;
use modular_bitfield::prelude::*;
#[derive(BitfieldSpecifier)]
#[bits = 3]
#[derive(Debug, Clone, Copy, PartialEq)]
enum Tile2 {
Blue,
Yellow,
Red,
Black,
Teal,
Start,
None
}
impl Tile2 {
fn is_none(&self) -> bool {
*self == Tile2::None
}
fn is_some(&self) -> bool {
!self.is_none()
}
}
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
enum Player2 {
One,
Two
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Bag2 {
blue: B5,
yellow: B5,
red: B5,
black: B5,
teal: B5,
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Factory2 {
one: Tile2,
two: Tile2,
three: Tile2,
four: Tile2
}
impl Factory2 {
fn is_empty(&self) -> bool {
self.one().is_none()
&& self.two().is_none()
&& self.three().is_none()
&& self.four().is_none()
}
fn is_full(&self) -> bool {
self.one().is_some()
&& self.two().is_some()
&& self.three().is_some()
&& self.four().is_some()
}
fn add_to_first(&mut self, tile: Tile2) -> Result<(), Tile2> {
if self.one().is_none() {
self.set_one(tile);
return Ok(());
}
else if self.two().is_none() {
self.set_two(tile);
return Ok(());
}
else if self.three().is_none() {
self.set_three(tile);
return Ok(());
}
else if self.four().is_none() {
self.set_four(tile);
return Ok(());
}
Err(tile)
}
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Factories2 {
one: Factory2,
two: Factory2,
three: Factory2,
four: Factory2,
five: Factory2,
}
impl Factories2 {
fn is_empty(&self) -> bool {
self.one().is_empty()
&& self.two().is_empty()
&& self.three().is_empty()
&& self.four().is_empty()
&& self.five().is_empty()
}
fn add_to_firsts(&mut self, tile: Tile2) -> Result<(), Tile2>{
if !self.one().is_full() {
self.one().add_to_first(tile);
return Ok(())
}
else if !self.two().is_full() {
self.two().add_to_first(tile);
return Ok(())
}
else if !self.three().is_full() {
self.three().add_to_first(tile);
return Ok(())
}
else if !self.four().is_full() {
self.four().add_to_first(tile);
return Ok(())
}
else if !self.five().is_full() {
self.five().add_to_first(tile);
return Ok(())
}
Err(tile)
}
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Row2 {
one: bool,
two: bool,
three: bool,
four: bool,
five: bool
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Wall2 {
one: Row2,
two: Row2,
three: Row2,
four: Row2,
five: Row2
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Market2 {
blue: B5,
yellow: B5,
red: B5,
black: B5,
teal: B5,
start: bool
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Pattern2_1 (Tile2, B1);
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Pattern2_2 (Tile2, B2);
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Pattern2_3 (Tile2, B2);
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Pattern2_4 (Tile2, B3);
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Pattern2_5 (Tile2, B3);
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Patterns2 {
one: Pattern2_1,
two: Pattern2_2,
three: Pattern2_3,
four: Pattern2_4,
five: Pattern2_5,
}
#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
#[derive(Debug)]
struct Board2 {
score: B7,
wall: Wall2,
patterns: Patterns2,
floor: Market2
}
/*#[bitfield(filled = false)]
#[derive(BitfieldSpecifier)]
struct Boards2 {
one: Board2,
two: Board2
}*/
#[bitfield]
#[derive(Debug, Copy, Clone)]
pub struct Game2 {
player: Player2,
box_top: Bag2,
bag: Bag2,
market: Market2,
factories: Factories2,
board_1: Board2,
board_2: Board2,
#[skip]
unused: B7
}
impl Game2 {
pub fn create() -> Self {
let game = Game2::new()
.with_player(Player2::One)
.with_box_top(Bag2::new()
.with_blue(0)
.with_yellow(0)
.with_red(0)
.with_black(0)
.with_teal(0)
)
.with_bag(Bag2::new()
.with_blue(20)
.with_yellow(20)
.with_red(20)
.with_black(20)
.with_teal(20)
)
.with_market(Market2::new()
.with_start(true)
.with_blue(0)
.with_yellow(0)
.with_red(0)
.with_black(0)
.with_teal(0)
)
.with_factories(Factories2::new()
.with_one(Factory2::new()
.with_one(Tile2::None)
.with_two(Tile2::None)
.with_three(Tile2::None)
.with_four(Tile2::None)
)
.with_two(Factory2::new()
.with_one(Tile2::None)
.with_two(Tile2::None)
.with_three(Tile2::None)
.with_four(Tile2::None)
)
.with_three(Factory2::new()
.with_one(Tile2::None)
.with_two(Tile2::None)
.with_three(Tile2::None)
.with_four(Tile2::None)
)
.with_four(Factory2::new()
.with_one(Tile2::None)
.with_two(Tile2::None)
.with_three(Tile2::None)
.with_four(Tile2::None)
)
.with_five(Factory2::new()
.with_one(Tile2::None)
.with_two(Tile2::None)
.with_three(Tile2::None)
.with_four(Tile2::None)
)
)
.with_board_1(Board2::new()
.with_score(0)
.with_wall(Wall2::new()
.with_one(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_two(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_three(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_four(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_five(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
)
.with_patterns(Patterns2::new()
.with_one(Pattern2_1::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_two(Pattern2_2::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_three(Pattern2_3::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_four(Pattern2_4::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_five(Pattern2_5::new()
.with_0(Tile2::None)
.with_1(0)
)
)
.with_floor(Market2::new()
.with_start(false)
.with_blue(0)
.with_yellow(0)
.with_red(0)
.with_black(0)
.with_teal(0)
)
)
.with_board_2(Board2::new()
.with_score(0)
.with_wall(Wall2::new()
.with_one(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_two(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_three(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_four(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
.with_five(Row2::new()
.with_one(false)
.with_two(false)
.with_three(false)
.with_four(false)
.with_five(false)
)
)
.with_patterns(Patterns2::new()
.with_one(Pattern2_1::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_two(Pattern2_2::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_three(Pattern2_3::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_four(Pattern2_4::new()
.with_0(Tile2::None)
.with_1(0)
)
.with_five(Pattern2_5::new()
.with_0(Tile2::None)
.with_1(0)
)
)
.with_floor(Market2::new()
.with_start(false)
.with_blue(0)
.with_yellow(0)
.with_red(0)
.with_black(0)
.with_teal(0)
)
);
game
}
pub fn fill(&mut self, mut rng: StdRng) -> Result<(), &'static str> {
if !self.factories().is_empty() {
return Err("Factories are not empty");
}
for _ in 0..(4*5) {
let choices = [Tile2::Blue, Tile2::Yellow, Tile2::Red, Tile2::Black, Tile2::Teal];
let weights = [self.bag().blue(), self.bag().yellow(), self.bag().red(), self.bag().black(), self.bag().teal()];
let dist = WeightedIndex::new(&weights).unwrap();
let tile = choices[dist.sample(&mut rng)];
/* match self.set_factories(self.factories().add_to_firsts(tile)) {
Err(e) => return Err("Couldn't add tile to factory"),
Ok(_) => {
if tile == Tile2::Blue {
self.set_bag(self.bag().with_blue(self.bag().blue() - 1));
}
else if tile == Tile2::Yellow {
self.set_bag(self.bag().with_yellow(self.bag().yellow() - 1));
}
}
}; */
println!("{:?}", tile);
println!("{:#?}", self.bag());
//println!("{:#?}", self.factories());
}
Ok(())
/* for factory in &mut self.factories {
for _ in 0..4 {
if self.bag.len() == 0 && self.box_top.len() > 0 {
self.bag.append(&mut self.box_top);
}
else if self.bag.len() == 0 {
return Ok(())
}
else {
let tile_i:usize = rng.gen_range(0..self.bag.len());
let tile = self.bag.remove(tile_i);
factory.push(tile);
}
}
};
*/
}
/*pub fn do_move(&mut self, game_move: GameMove) -> Result<(), &'static str> {
match game_move {
() =>
}
}*/
}
use std::time::{Instant, Duration};
pub fn size_of_bitfields() -> Result<(), &'static str> {
println!("size of bitfield game: {}", std::mem::size_of::<Game2>());
println!("size of state: {}", std::mem::size_of::<super::azul::State>());
/* let game2 = Game2::create();
//println!("debug: {:#?}", game2);
//println!("{:?}", game2.into_bytes());
let now = Instant::now();
for _ in 0..1_000_000_000 {
let mut game2_2 = game2.clone();
game2_2.set_player(Player2::Two);
/*std::hint::black_box(game2_2);*/
}
let game_2_time = now.elapsed().as_nanos();
// let game1 = Game::new(2)?;
let now = Instant::now();
for _ in 0..1_000_000_000 {
// let mut game1_2 = game1.clone();
// game1_2.turn = 1;
// std::hint::black_box(game1_2);
}
let game_1_time = now.elapsed().as_nanos();
println!("{} | {}", game_1_time, game_2_time);
*/
Ok(())
}

View File

@ -1,14 +1,7 @@
#![feature(test)]
use cached::proc_macro::cached;
mod azul; mod azul;
use azul::*; use azul::*;
mod azul2;
use azul2::*;
use rand::prelude::*; use rand::prelude::*;
use thousands::Separable;
//#[global_allocator] //#[global_allocator]
//static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; //static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
@ -20,31 +13,31 @@ fn main() -> Result<(), &'static str> {
let program = std::env::args().nth(1).expect("no program given") let program = std::env::args().nth(1).expect("no program given")
.parse().unwrap_or(1); .parse().unwrap_or(1);
// size_of_stuff(); size_of_stuff();
return match program { return match program {
1 => { 1 => {
let mut game = some_game()?; let mut rng = StdRng::seed_from_u64(42);
let mut game = Game::new(2)?;
game.fill(StdRng::from_rng(&mut rng).expect("rng error"))?;
println!("{:#?}", game);
game.do_move(GameMove(2, Tile::Red, 3))?; game.do_move(GameMove(3, Tile::Red, 3))?;
game.do_move(GameMove(5, Tile::Yellow, 2))?; game.do_move(GameMove(1, Tile::Yellow, 2))?;
game.do_move(GameMove(3, Tile::Blue, 2))?; game.do_move(GameMove(4, Tile::Blue, 2))?;
//game.do_move(GameMove(0, Tile::Black, 4))?; game.do_move(GameMove(0, Tile::Black, 4))?;
//game.do_move(GameMove(5, Tile::Black, 1))?; game.do_move(GameMove(5, Tile::Black, 1))?;
// game.do_move(GameMove(0, Tile::Blue, 3))?; // game.do_move(GameMove(0, Tile::Blue, 3))?;
println!("{:#?}", game);
println!("{}", count_options(game, 1, 2)); println!("{}", count_options(game, 1, 2));
Ok(()) Ok(())
}, },
2 => calculate_options(), 2 => calculate_options(),
3 => size_of_bitfields(),
4 => {
let mut game = Game2::create();
game.fill(StdRng::seed_from_u64(42));
Ok(())
},
_ => Err("Not a valid program") _ => Err("Not a valid program")
} }
} }
@ -91,16 +84,12 @@ fn calculate_options() -> Result<(), &'static str> {
Ok(()) Ok(())
} }
#[cached(size=45_000_000, key = "State", convert = r#"{ _game.state }"#)]
fn count_options(_game: Game, depth: u8, treshold: u8) -> u128 { fn count_options(_game: Game, depth: u8, treshold: u8) -> u128 {
let before = std::time::Instant::now();
let mut sum = 0; let mut sum = 0;
let mut all_failed = true; let mut all_failed = true;
let mut multiplier = 1; let mut multiplier = 1;
// Upper bound calculation by skipping first depth and assuming most complicated possible game as multiplier
let game = match depth { let game = match depth {
0 => { 0 => {
let mut new_game = _game.clone(); let mut new_game = _game.clone();
@ -122,13 +111,10 @@ fn count_options(_game: Game, depth: u8, treshold: u8) -> u128 {
for game_move in i { for game_move in i {
//println!("{:?}", game_move); //println!("{:?}", game_move);
if game.is_legal(game_move).is_err() {
continue;
};
let mut new_game = game.clone(); let mut new_game = game.clone();
let r = new_game.do_move(game_move); let r = new_game.do_move(game_move);
match r { match r {
Ok(_) => sum += {/*println!("{}", depth);*/ all_failed = false; /*coz::progress!("OK");*/ multiplier * count_options(new_game, depth + 1, treshold)}, Ok(_) => sum += {/*println!("{}", depth);*/ all_failed = false; coz::progress!("OK"); multiplier * count_options(new_game, depth + 1, treshold)},
Err(_) => continue Err(_) => continue
}; };
}; };
@ -141,11 +127,7 @@ fn count_options(_game: Game, depth: u8, treshold: u8) -> u128 {
} }
if depth <= treshold { if depth <= treshold {
let elapsed = before.elapsed(); println!("{}: sum: {}", depth, sum);
let hashrate = sum / std::cmp::max(elapsed.as_millis() as u128, 1u128) * 1000u128;
println!("{}: sum: {}, took +{:?}: {}/s",
depth, sum, elapsed, hashrate.separate_with_spaces()
);
} }
return sum; return sum;