diff --git a/game/src/config/mod.rs b/game/src/config/mod.rs index 905ab7e..9274570 100644 --- a/game/src/config/mod.rs +++ b/game/src/config/mod.rs @@ -1,4 +1,42 @@ +use crate::{Piece, PieceClass}; + +#[derive(Clone)] +pub struct TimingConfig { + game_limit:Option, + // Time available to each player + play_limit:Option, + // Time available per move + timeout_mode:u8, + // +} +impl TimingConfig { + pub fn new() -> Self + { + Self { + game_limit:None, + play_limit:None, + timeout_mode:0, + } + } +} + #[derive(Clone)] pub struct GameConfig { - + pieces:Vec, + board:Vec, + pools:[[u8; 7]; 2], + // rules + timing:TimingConfig, +} +impl GameConfig { + pub fn new() -> Self + { + Self { + pieces:Vec::new(), + board:Vec::new(), + pools:[[0; 7]; 2], + + timing:TimingConfig::new(), + } + } } diff --git a/game/src/lib.rs b/game/src/lib.rs index 956fa93..f57e817 100644 --- a/game/src/lib.rs +++ b/game/src/lib.rs @@ -2,11 +2,12 @@ pub mod constant; use constant::*; pub mod util; use util::Hex; -pub mod piece; use piece::Piece; +pub mod piece; use piece::{Piece, PieceClass}; pub mod board; use board::Board; pub mod history; use history::*; pub mod config; use config::GameConfig; mod game; use game::*; +mod ranking; pub use ranking::Ranking; #[derive(Clone, Copy)] pub enum GameStatus { @@ -34,7 +35,7 @@ impl Game { pub fn new() -> Self { Self { - config:GameConfig { }, + config:GameConfig::new(), status:GameStatus::Normal, turn:0, @@ -593,7 +594,7 @@ impl Game { // Knight 1 => { for tile_id in subject_tiles { - if self.can_drop(piece, tile_id, flags::IGNORE_CHECK) { + if self.can_drop(piece, tile_id, flags::IGNORE_CHECK | flags::IGNORE_EXTENT) { plays.push(PlayInfo { valid: true, threat: false, @@ -605,7 +606,7 @@ impl Game { } } - // Caslte + // Castle 2 => { for tile_id in subject_tiles { let piece_hex = Hex::from_tile(piece.tile); diff --git a/game/src/ranking.rs b/game/src/ranking.rs new file mode 100644 index 0000000..3593b49 --- /dev/null +++ b/game/src/ranking.rs @@ -0,0 +1,6 @@ +pub struct Ranking { + +} +impl Ranking { + +} diff --git a/server/src/system/cache/mod.rs b/server/src/system/cache/mod.rs index 40bd461..342e445 100644 --- a/server/src/system/cache/mod.rs +++ b/server/src/system/cache/mod.rs @@ -108,6 +108,6 @@ impl WebCache { pub fn raw(data:Vec) -> Source { Source::Raw(data) } pub fn string(text:&str) -> Source { Source::String(text.to_string()) } - pub fn file

>(path:P) -> Source { Source::File((path.as_ref() as &Path).to_path_buf())} - pub fn markdown

>(path:P) -> Source { Source::MarkdownFile((path.as_ref() as &Path).to_path_buf())} + pub fn file>(path:P) -> Source { Source::File((path.as_ref() as &Path).to_path_buf())} + pub fn markdown>(path:P) -> Source { Source::MarkdownFile((path.as_ref() as &Path).to_path_buf())} } diff --git a/server/src/system/filesystem/mod.rs b/server/src/system/filesystem/mod.rs index 7419b94..109dd16 100644 --- a/server/src/system/filesystem/mod.rs +++ b/server/src/system/filesystem/mod.rs @@ -2,6 +2,8 @@ use std::{ fs::{self, File}, io::{Read, Seek, SeekFrom, Write}, path::Path }; +use const_format::*; + use game::{ history::Play, Game, @@ -25,15 +27,15 @@ const GENERIC_REQUEST :&str = "r.bin"; const GENERIC_STATUS :&str = "s.bin"; const DIR_DATA :&str = "data"; -const DIR_HANDLE :&str = const_format::formatcp!("{}/h", DIR_DATA); -const DIR_SESSION :&str = const_format::formatcp!("{}/s", DIR_DATA); -const DIR_USER :&str = const_format::formatcp!("{}/u", DIR_DATA); +const DIR_HANDLE :&str = formatcp!("{}/h", DIR_DATA); +const DIR_SESSION :&str = formatcp!("{}/s", DIR_DATA); +const DIR_USER :&str = formatcp!("{}/u", DIR_DATA); -const INDEX_HANDLE :&str = const_format::formatcp!("{d}/{f}", d= DIR_HANDLE, f= GENERIC_INDEX); -const INDEX_SESSION :&str = const_format::formatcp!("{d}/{f}", d= DIR_SESSION, f= GENERIC_INDEX); -const INDEX_USER :&str = const_format::formatcp!("{d}/{f}", d= DIR_USER, f= GENERIC_INDEX); +const INDEX_HANDLE :&str = formatcp!("{d}/{f}", d= DIR_HANDLE, f= GENERIC_INDEX); +const INDEX_SESSION :&str = formatcp!("{d}/{f}", d= DIR_SESSION, f= GENERIC_INDEX); +const INDEX_USER :&str = formatcp!("{d}/{f}", d= DIR_USER, f= GENERIC_INDEX); -pub const FILE_SALT :&str = const_format::formatcp!("{}/x.bin", DIR_DATA); +pub const FILE_SALT :&str = formatcp!("{}/x.bin", DIR_DATA); pub struct FileSystem { index_handle:File, diff --git a/www/css/util.css b/www/css/util.css index f60b912..ac2fbdd 100644 --- a/www/css/util.css +++ b/www/css/util.css @@ -7,6 +7,9 @@ button.warn { background-color:#471414; color:#e0e0e0; } +button.active{ + color:#d0b040; +} span.monospace {font-family:monospace;} diff --git a/www/js/game.js b/www/js/game.js index 2236e1f..a9dcd0a 100644 --- a/www/js/game.js +++ b/www/js/game.js @@ -646,7 +646,7 @@ GAME.Game = class { // Check all tiles if not blocking. if(block_directions == 0) { for(let i = 0; i < GAME_DATA.board.tiles.length; ++i) { - if(this.placable_tile(piece, i, {check:false})) { + if(this.placable_tile(piece, i, {check:false, extent:false})) { tiles.push(new GAME.MovementTile(i, true, false, 0, 0)); } } @@ -667,7 +667,7 @@ GAME.Game = class { if(HEX.is_valid_board(tile_hex)) { let tile_id = HEX.hex_to_tile(tile_hex); - if(this.placable_tile(piece, tile_id, {check:false})) { + if(this.placable_tile(piece, tile_id, {check:false, extent:false})) { tiles.push(new GAME.MovementTile(tile_id, true, false, 0, 0)); } } else { break; } diff --git a/www/js/interface.js b/www/js/interface.js index 650828a..a10a09a 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -436,6 +436,8 @@ const INTERFACE = { case INTERFACE.Mode.Review: { document.getElementById("indicator-turn").innerText = INTERFACE_DATA.Replay.turn + " / " + INTERFACE_DATA.Game.history.length; document.getElementById("turn-slider").setAttribute("max", INTERFACE_DATA.Game.history.length); + + INTERFACE.replay_update_auto(); } break; } @@ -1658,6 +1660,7 @@ const INTERFACE = { if(INTERFACE_DATA.Replay.auto) { setTimeout(INTERFACE.replay_auto, 1000); } + INTERFACE.replay_update_auto(); }, replay_auto() { if(INTERFACE_DATA.Replay.auto) { @@ -1668,11 +1671,22 @@ const INTERFACE = { INTERFACE_DATA.Replay.auto = false; } } + INTERFACE.replay_update_auto(); }, replay_off() { INTERFACE_DATA.Replay.auto = false; + INTERFACE.replay_update_auto(); + }, + replay_update_auto() { + let b_auto = document.getElementById("button-auto"); + if(b_auto !== null) { + if(INTERFACE_DATA.Replay.auto) { + b_auto.setAttribute("class", "active"); + } else { + b_auto.removeAttribute("class"); + } + } }, - auto() { let bit = 1 << (INTERFACE_DATA.rotate ^ 1); diff --git a/www/js/scene.js b/www/js/scene.js index af7c717..8a94368 100644 --- a/www/js/scene.js +++ b/www/js/scene.js @@ -877,29 +877,6 @@ const SCENES = { } }, - Subscription:class{ - constructor() { } - load(data) { - if(sessionStorage.getItem("auth") === null) return false; - - UI.mainmenu_account(null, "subscription"); - - // Left Buttons - let buttons_left = [ ]; - - // Right Buttons - let buttons_right = [ ]; - buttons_right.push(UI.button("Cancel", () => { })); - - UI.mainnav(buttons_left, buttons_right); - - // Main Content - - history.pushState(null, "Dzura - About", "/u/" + CONTEXT.Auth.handle); - return true; - } - }, - Invitations:class{ constructor() { this.data = null; @@ -1076,10 +1053,13 @@ const SCENES = { let ind_turn = UI.div([UI.text("0 / 0")]); ind_turn.setAttribute("id", "indicator-turn"); + let button_auto = UI.button(LANG("auto"), () => { INTERFACE.replay_toggle_auto(); }); + button_auto.setAttribute("id", "button-auto"); + UI.mainnav( [ ], [ - UI.button(LANG("auto"), () => { INTERFACE.replay_toggle_auto(); }), + button_auto, UI.button("◀", () => { INTERFACE.replay_off(); INTERFACE.replay_first(); }), UI.button("◁", () => { INTERFACE.replay_off(); INTERFACE.replay_prev(); }), ind_turn, diff --git a/www/js/ui.js b/www/js/ui.js index ae303ad..e426126 100644 --- a/www/js/ui.js +++ b/www/js/ui.js @@ -206,7 +206,6 @@ const UI = { // Bottom Buttons if(CONTEXT.Auth !== null && (handle === null || handle == CONTEXT.Auth.handle)) { buttons_bottom.push(UI.button("Account", () => { SCENE.load(SCENES.Account) }, page == "account")); - buttons_bottom.push(UI.button("Subscription", () => { SCENE.load(SCENES.Subscription) }, page == "subscription")); buttons_bottom.push(UI.button("Invitations", () => { SCENE.load(SCENES.Invitations) }, page == "invitations")); } buttons_bottom.push(UI.button(LANG("back"), () => { SCENE.load(SCENES.Browse); })); diff --git a/www/pages/about/main.md b/www/pages/about/main.md index 0bc4054..42ba01b 100644 --- a/www/pages/about/main.md +++ b/www/pages/about/main.md @@ -4,11 +4,15 @@ Dzura is a two-player abstract strategy game contending the armies of Dawn and D Inspired by the chess family, the game features a variety of pieces, each with its own pattern of movement. Borrowing from shogi, captured pieces may be returned to the board on the capturer's side and pieces that reach the far side of the board are promoted. +Those interested may get more information here: + + - [Discord](https://discord.gg/u2HpSCRkTS) + Dzura is a work of [Project Kirisame](https://kirisame.com). - [Project License](https://ykr.info/license) -© 2024 Yukiri Corporation +© 2024 Yukiri Corporation et al. # User Privacy @@ -16,49 +20,3 @@ Dzura is a work of [Project Kirisame](https://kirisame.com). This website does not collect any information beyond that used to implement user accounts and gameplay. Information is not provided to third parties except in serving the application to clients. - - -# Payment Policy - -### Subscription - -Dzura's core monetization is a modest subscription for access to extra content, including additional reactions, custom games, and media. - -The exact benefits of the subscription may change over time as more content is added. - - -### Pricing - -Dzura's subscription is offered at: - - - USD $2.00 ($1.00 reduced period) - - -### Reduced Period - -Subscriptions activated after the 14th day of the month will be offered at reduced price for the period. - -Subscriptions activated after the 21st day will be included with the next month's period at no additional cost. - - -### Refunds - -Refunds will be automatically accepted up to 3 days after activation of subscription or start of the payment period if the subscription is canceled during that time. - -Refunds or free periods will also be provided at our discretion for any inconveniences to our users. - - -### Cancellation - -Users may cancel their subscriptions at any time under the Subscription page of Account Management. - -Canceled subscriptions will remain active until the end of the period. - -A canceled subscription may be reinstated until the next payment period. - -If a user is not active for a full payment period, their subscription will be automatically canceled. - - -### Customer Service - -**Contact:** service@dzura.com