From aca4e7acb190784b9c150350a2d1ee619adc33e9 Mon Sep 17 00:00:00 2001 From: yukirij Date: Mon, 19 Aug 2024 01:15:43 -0700 Subject: [PATCH] Add retire implementation. --- game/src/game/mod.rs | 114 +++++++++++++++++++++---------------- server/src/manager/data.rs | 30 +++++++++- www/js/game.js | 102 +++++++++++++++++++-------------- www/js/interface.js | 10 +++- www/js/language.js | 11 ++-- 5 files changed, 167 insertions(+), 100 deletions(-) diff --git a/game/src/game/mod.rs b/game/src/game/mod.rs index 7dd818f..e244f6c 100644 --- a/game/src/game/mod.rs +++ b/game/src/game/mod.rs @@ -48,6 +48,7 @@ impl Game { { let player = (self.turn & 1) as u8; + if self.complete { return Err(()); } // // TODO: @@ -58,69 +59,82 @@ impl Game { // Move piece on board. - if if play.source == 0 { - if let Some(pid) = self.board.tiles[play.from as usize].piece { - if let Some(mut piece) = self.board.pieces[pid as usize] { - let mut swap = false; + if match play.source { + 0 => { + if let Some(pid) = self.board.tiles[play.from as usize].piece { + if let Some(mut piece) = self.board.pieces[pid as usize] { + let mut swap = false; - if let Some(tid) = self.board.tiles[play.to as usize].piece { - if let Some(target) = &mut self.board.pieces[tid as usize] { + if let Some(tid) = self.board.tiles[play.to as usize].piece { + if let Some(target) = &mut self.board.pieces[tid as usize] { - // Check for piece swap. - if piece.player == target.player { - swap = true; - target.tile = play.from; + // Check for piece swap. + if piece.player == target.player { + swap = true; + target.tile = play.from; - // Check for target promotion. - let hex = Hex::from_tile(play.from); - if !target.promoted && target.has_promotion() && Hex::is_back(hex.x, hex.y, target.player) { - target.promoted = true; + // Check for target promotion. + let hex = Hex::from_tile(play.from); + if !target.promoted && target.has_promotion() && Hex::is_back(hex.x, hex.y, target.player) { + target.promoted = true; + } + } + + // Add captured piece to pool. + else { + self.pool[piece.player as usize][target.class as usize] += 1; } } - - // Add captured piece to pool. - else { - self.pool[piece.player as usize][target.class as usize] += 1; + + // Destroy piece if captured. + if !swap { self.board.pieces[tid as usize] = None; } + } + + // Set tile/piece associations. + if swap { + self.board.tiles[play.from as usize].piece = self.board.tiles[play.to as usize].piece; + } else { + self.board.tiles[play.from as usize].piece = None; + } + self.board.tiles[play.to as usize].piece = Some(pid); + piece.tile = play.to; + + self.board.pieces[pid as usize] = Some(piece); + + // Check for piece promotion. + let hex = Hex::from_tile(play.to); + if !piece.promoted && piece.has_promotion() && Hex::is_back(hex.x, hex.y, piece.player) { + if let Some(piece) = &mut self.board.pieces[pid as usize] { + piece.promoted = true; } } - // Destroy piece if captured. - if !swap { self.board.pieces[tid as usize] = None; } - } + self.turn += 1; + true + } else { false } + } else { false } + } + + // Place piece from pool. + 1 => { + if self.pool[player as usize][play.from as usize] > 0 && self.board.tiles[play.to as usize].piece.is_none() { + self.pool[player as usize][play.from as usize] -= 1; + let piece = Piece::new(play.from, player); + self.board.set_piece(piece, play.to); - // Set tile/piece associations. - if swap { - self.board.tiles[play.from as usize].piece = self.board.tiles[play.to as usize].piece; - } else { - self.board.tiles[play.from as usize].piece = None; - } - self.board.tiles[play.to as usize].piece = Some(pid); - piece.tile = play.to; - - self.board.pieces[pid as usize] = Some(piece); - - // Check for piece promotion. - let hex = Hex::from_tile(play.to); - if !piece.promoted && piece.has_promotion() && Hex::is_back(hex.x, hex.y, piece.player) { - if let Some(piece) = &mut self.board.pieces[pid as usize] { - piece.promoted = true; - } - } + self.turn += 1; true } else { false } - } else { false } - } - - // Place piece from pool. - else { - if self.pool[player as usize][play.from as usize] > 0 && self.board.tiles[play.to as usize].piece.is_none() { - self.pool[player as usize][play.from as usize] -= 1; - let piece = Piece::new(play.from, player); - self.board.set_piece(piece, play.to); + } + + // Player retired. + 2 => { + self.complete = true; true - } else { false } + } + + _ => false, } { - self.turn += 1; self.history.push(*play); Ok(()) } else { Err(()) } diff --git a/server/src/manager/data.rs b/server/src/manager/data.rs index 940702e..57c9686 100644 --- a/server/src/manager/data.rs +++ b/server/src/manager/data.rs @@ -483,10 +483,36 @@ pub async fn thread_system(mut app:App, bus:Bus) // SessionRetire QRPacketData::QSessionRetire(request) => { + use game::history::Play; println!("Request: Session Retire"); - if let Some(_session) = app.sessions.get_mut(&request.token) { + let mut packets = Vec::::new(); + let play = Play { + source: 2, + from: 0, + to: 0, + }; + + if let Some(session) = app.sessions.get_mut(&request.token) { + if !session.game.complete { + session.game.process(&play).ok(); + + for (cid, _) in session.get_connections() { + packets.push(QRPacket::new( + cid, + QRPacketData::QGamePlay(PacketGamePlay { + status: STATUS_OK, + turn: session.game.turn, + play, + }), + )); + } + } + } + + for packet in packets { + app.send_response(packet).await; } Some(QRPacket::new(0, QRPacketData::None)) @@ -537,7 +563,7 @@ pub async fn thread_system(mut app:App, bus:Bus) if let Some(sid) = session_id { if let Some(session) = app.sessions.get_mut(&sid) { - if session.p_dawn.user.is_some() && session.p_dusk.user.is_some() { + if !session.game.complete && (session.p_dawn.user.is_some() && session.p_dusk.user.is_some()) { if (user_id == session.p_dawn.user && session.game.turn & 1 == 0) || (user_id == session.p_dusk.user && session.game.turn & 1 == 1) { diff --git a/www/js/game.js b/www/js/game.js index a132247..4061927 100644 --- a/www/js/game.js +++ b/www/js/game.js @@ -204,6 +204,7 @@ GAME.Game = class { ]; this.state = { + code:0, check:false, checkmate:false, }; @@ -285,61 +286,70 @@ GAME.Game = class { // - Improve data safety validation. // + if(this.state.code != 0) { return false; } + let player = this.turn & 1; // Move piece on board. - if(play.source == 0) { - let piece_id = this.board.tiles[play.from].piece; - let piece = this.board.pieces[piece_id]; - piece.tile = play.to; - this.board.tiles[play.from].piece = null; + switch(play.source) { + case 0: { + let piece_id = this.board.tiles[play.from].piece; + let piece = this.board.pieces[piece_id]; + piece.tile = play.to; + this.board.tiles[play.from].piece = null; - let target_id = this.board.tiles[play.to].piece; - if(target_id !== null) { - let target = this.board.pieces[target_id]; - - // Swap piece with moving piece. - if(target.player == piece.player) { - target.tile = play.from; - this.board.tiles[play.from].piece = target_id; + let target_id = this.board.tiles[play.to].piece; + if(target_id !== null) { + let target = this.board.pieces[target_id]; + + // Swap piece with moving piece. + if(target.player == piece.player) { + target.tile = play.from; + this.board.tiles[play.from].piece = target_id; - // Check if swap is promoted. - let hex = HEX.tile_to_hex(target.tile); - hex.y -= MATH.sign_branch(target.player); - if(!target.promoted && target.has_promotion() && !HEX.is_valid(hex)) { - target.promoted = true; + // Check if swap is promoted. + let hex = HEX.tile_to_hex(target.tile); + hex.y -= MATH.sign_branch(target.player); + if(!target.promoted && target.has_promotion() && !HEX.is_valid(hex)) { + target.promoted = true; + } + } + + // Add captured piece to pool and destroy. + else { + this.pools[piece.player].pieces[target.piece] += 1; + this.board.pieces[target_id] = null; } } - - // Add captured piece to pool and destroy. - else { - this.pools[piece.player].pieces[target.piece] += 1; - this.board.pieces[target_id] = null; + + this.board.tiles[play.to].piece = piece_id; + + // Check if piece is promoted. + let hex = HEX.tile_to_hex(piece.tile); + hex.y -= MATH.sign_branch(piece.player); + if(!piece.promoted && piece.has_promotion() && !HEX.is_valid(hex)) { + piece.promoted = true; } - } + this.turn++; + } break; - this.board.tiles[play.to].piece = piece_id; + // Place piece from pool. + case 1: { + this.board.set_piece( + play.from, + player, + play.to + ); + this.pools[this.turn & 1].pieces[play.from] -= 1; + this.turn++; + } break; - // Check if piece is promoted. - let hex = HEX.tile_to_hex(piece.tile); - hex.y -= MATH.sign_branch(piece.player); - if(!piece.promoted && piece.has_promotion() && !HEX.is_valid(hex)) { - piece.promoted = true; - } + // Play retired. + case 2: { + this.state.code = 2; + } break; } - // Place piece from pool. - else { - this.board.set_piece( - play.from, - player, - play.to - ); - this.pools[this.turn & 1].pieces[play.from] -= 1; - } - - this.turn++; - // Recalculate new board state. this.update_board(); @@ -550,6 +560,12 @@ GAME.Const = { Pool: 1, }, + State: { + Ongoing: 0, + Complete: 1, + Retire: 2, + }, + Direction: [ new MATH.Vec2(0, 1), new MATH.Vec2(1, 1), diff --git a/www/js/interface.js b/www/js/interface.js index 0aced5d..8170aa1 100644 --- a/www/js/interface.js +++ b/www/js/interface.js @@ -563,7 +563,10 @@ const INTERFACE = { let message = null; ctx.fillStyle = INTERFACE.Color.Text; - if(GAME_DATA.state.check) { + if(GAME_DATA.state.code == GAME.Const.State.Retire) { + ctx.fillStyle = INTERFACE.Color.HintCheck; + message = "Retire"; + } else if(GAME_DATA.state.check) { ctx.fillStyle = INTERFACE.Color.HintCheck; if(GAME_DATA.state.checkmate) { message = "Checkmate"; @@ -716,6 +719,7 @@ const INTERFACE = { handles: [null, null], board_state: [ ], play: null, + retire:false, Ui: { scale: 0, @@ -778,6 +782,10 @@ const INTERFACE = { GAME_DATA.turn = data.turn; INTERFACE_DATA.play = data.play; + if(INTERFACE_DATA.play.source == 2) { + GAME_DATA.state.code = 2; + } + if(data.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; } if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; } diff --git a/www/js/language.js b/www/js/language.js index 9f741c8..5a17cbf 100644 --- a/www/js/language.js +++ b/www/js/language.js @@ -10,9 +10,12 @@ LANGUAGE.Terms = { Dawn: new LANGUAGE.Term( "Dawn", "暁" ), Dusk: new LANGUAGE.Term( "Dusk", "黄昏" ), - Handle: new LANGUAGE.Term( "Handle", "" ), - Secret: new LANGUAGE.Term( "Secret", "" ), + Handle: new LANGUAGE.Term( "Handle", "" ), + Secret: new LANGUAGE.Term( "Secret", "" ), - Browse: new LANGUAGE.Term( "Resume", "" ), - Resume: new LANGUAGE.Term( "Resume", "" ), + Browse: new LANGUAGE.Term( "Browse", "" ), + Resume: new LANGUAGE.Term( "Resume", "" ), + + Check: new LANGUAGE.Term( "Check", "王手" ), + Checkmate: new LANGUAGE.Term( "Checkmate", "詰み" ), };