Merge branch 'main' into is5
This commit is contained in:
commit
c1dd925976
@ -1,4 +1,42 @@
|
||||
use crate::{Piece, PieceClass};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TimingConfig {
|
||||
game_limit:Option<u32>,
|
||||
// Time available to each player
|
||||
play_limit:Option<u32>,
|
||||
// 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<PieceClass>,
|
||||
board:Vec<Piece>,
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
6
game/src/ranking.rs
Normal file
6
game/src/ranking.rs
Normal file
@ -0,0 +1,6 @@
|
||||
pub struct Ranking {
|
||||
|
||||
}
|
||||
impl Ranking {
|
||||
|
||||
}
|
4
server/src/system/cache/mod.rs
vendored
4
server/src/system/cache/mod.rs
vendored
@ -108,6 +108,6 @@ impl WebCache {
|
||||
|
||||
pub fn raw(data:Vec<u8>) -> Source { Source::Raw(data) }
|
||||
pub fn string(text:&str) -> Source { Source::String(text.to_string()) }
|
||||
pub fn file<P :AsRef<Path>>(path:P) -> Source { Source::File((path.as_ref() as &Path).to_path_buf())}
|
||||
pub fn markdown<P :AsRef<Path>>(path:P) -> Source { Source::MarkdownFile((path.as_ref() as &Path).to_path_buf())}
|
||||
pub fn file<P:AsRef<Path>>(path:P) -> Source { Source::File((path.as_ref() as &Path).to_path_buf())}
|
||||
pub fn markdown<P:AsRef<Path>>(path:P) -> Source { Source::MarkdownFile((path.as_ref() as &Path).to_path_buf())}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -7,6 +7,9 @@ button.warn {
|
||||
background-color:#471414;
|
||||
color:#e0e0e0;
|
||||
}
|
||||
button.active{
|
||||
color:#d0b040;
|
||||
}
|
||||
|
||||
span.monospace {font-family:monospace;}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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); }));
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user