Add retire implementation.

This commit is contained in:
yukirij 2024-08-19 01:15:43 -07:00
parent f81e9343ce
commit aca4e7acb1
5 changed files with 167 additions and 100 deletions

View File

@ -48,6 +48,7 @@ impl Game {
{ {
let player = (self.turn & 1) as u8; let player = (self.turn & 1) as u8;
if self.complete { return Err(()); }
// //
// TODO: // TODO:
@ -58,69 +59,82 @@ impl Game {
// Move piece on board. // Move piece on board.
if if play.source == 0 { if match play.source {
if let Some(pid) = self.board.tiles[play.from as usize].piece { 0 => {
if let Some(mut piece) = self.board.pieces[pid as usize] { if let Some(pid) = self.board.tiles[play.from as usize].piece {
let mut swap = false; 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(tid) = self.board.tiles[play.to as usize].piece {
if let Some(target) = &mut self.board.pieces[tid as usize] { if let Some(target) = &mut self.board.pieces[tid as usize] {
// Check for piece swap. // Check for piece swap.
if piece.player == target.player { if piece.player == target.player {
swap = true; swap = true;
target.tile = play.from; target.tile = play.from;
// Check for target promotion. // Check for target promotion.
let hex = Hex::from_tile(play.from); let hex = Hex::from_tile(play.from);
if !target.promoted && target.has_promotion() && Hex::is_back(hex.x, hex.y, target.player) { if !target.promoted && target.has_promotion() && Hex::is_back(hex.x, hex.y, target.player) {
target.promoted = true; 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. // Destroy piece if captured.
else { if !swap { self.board.pieces[tid as usize] = None; }
self.pool[piece.player as usize][target.class as usize] += 1; }
// 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. self.turn += 1;
if !swap { self.board.pieces[tid as usize] = None; } 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. self.turn += 1;
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;
}
}
true true
} else { false } } else { false }
} else { false } }
}
// Player retired.
// Place piece from pool. 2 => {
else { self.complete = true;
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);
true true
} else { false } }
_ => false,
} { } {
self.turn += 1;
self.history.push(*play); self.history.push(*play);
Ok(()) Ok(())
} else { Err(()) } } else { Err(()) }

View File

@ -483,10 +483,36 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
// SessionRetire // SessionRetire
QRPacketData::QSessionRetire(request) => { QRPacketData::QSessionRetire(request) => {
use game::history::Play;
println!("Request: Session Retire"); println!("Request: Session Retire");
if let Some(_session) = app.sessions.get_mut(&request.token) { let mut packets = Vec::<QRPacket>::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)) Some(QRPacket::new(0, QRPacketData::None))
@ -537,7 +563,7 @@ pub async fn thread_system(mut app:App, bus:Bus<protocol::QRPacket>)
if let Some(sid) = session_id { if let Some(sid) = session_id {
if let Some(session) = app.sessions.get_mut(&sid) { 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) if (user_id == session.p_dawn.user && session.game.turn & 1 == 0)
|| (user_id == session.p_dusk.user && session.game.turn & 1 == 1) { || (user_id == session.p_dusk.user && session.game.turn & 1 == 1) {

View File

@ -204,6 +204,7 @@ GAME.Game = class {
]; ];
this.state = { this.state = {
code:0,
check:false, check:false,
checkmate:false, checkmate:false,
}; };
@ -285,61 +286,70 @@ GAME.Game = class {
// - Improve data safety validation. // - Improve data safety validation.
// //
if(this.state.code != 0) { return false; }
let player = this.turn & 1; let player = this.turn & 1;
// Move piece on board. // Move piece on board.
if(play.source == 0) { switch(play.source) {
let piece_id = this.board.tiles[play.from].piece; case 0: {
let piece = this.board.pieces[piece_id]; let piece_id = this.board.tiles[play.from].piece;
piece.tile = play.to; let piece = this.board.pieces[piece_id];
this.board.tiles[play.from].piece = null; piece.tile = play.to;
this.board.tiles[play.from].piece = null;
let target_id = this.board.tiles[play.to].piece; let target_id = this.board.tiles[play.to].piece;
if(target_id !== null) { if(target_id !== null) {
let target = this.board.pieces[target_id]; let target = this.board.pieces[target_id];
// Swap piece with moving piece. // Swap piece with moving piece.
if(target.player == piece.player) { if(target.player == piece.player) {
target.tile = play.from; target.tile = play.from;
this.board.tiles[play.from].piece = target_id; this.board.tiles[play.from].piece = target_id;
// Check if swap is promoted. // Check if swap is promoted.
let hex = HEX.tile_to_hex(target.tile); let hex = HEX.tile_to_hex(target.tile);
hex.y -= MATH.sign_branch(target.player); hex.y -= MATH.sign_branch(target.player);
if(!target.promoted && target.has_promotion() && !HEX.is_valid(hex)) { if(!target.promoted && target.has_promotion() && !HEX.is_valid(hex)) {
target.promoted = true; 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. this.board.tiles[play.to].piece = piece_id;
else {
this.pools[piece.player].pieces[target.piece] += 1; // Check if piece is promoted.
this.board.pieces[target_id] = null; 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. // Play retired.
let hex = HEX.tile_to_hex(piece.tile); case 2: {
hex.y -= MATH.sign_branch(piece.player); this.state.code = 2;
if(!piece.promoted && piece.has_promotion() && !HEX.is_valid(hex)) { } break;
piece.promoted = true;
}
} }
// 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. // Recalculate new board state.
this.update_board(); this.update_board();
@ -550,6 +560,12 @@ GAME.Const = {
Pool: 1, Pool: 1,
}, },
State: {
Ongoing: 0,
Complete: 1,
Retire: 2,
},
Direction: [ Direction: [
new MATH.Vec2(0, 1), new MATH.Vec2(0, 1),
new MATH.Vec2(1, 1), new MATH.Vec2(1, 1),

View File

@ -563,7 +563,10 @@ const INTERFACE = {
let message = null; let message = null;
ctx.fillStyle = INTERFACE.Color.Text; 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; ctx.fillStyle = INTERFACE.Color.HintCheck;
if(GAME_DATA.state.checkmate) { if(GAME_DATA.state.checkmate) {
message = "Checkmate"; message = "Checkmate";
@ -716,6 +719,7 @@ const INTERFACE = {
handles: [null, null], handles: [null, null],
board_state: [ ], board_state: [ ],
play: null, play: null,
retire:false,
Ui: { Ui: {
scale: 0, scale: 0,
@ -778,6 +782,10 @@ const INTERFACE = {
GAME_DATA.turn = data.turn; GAME_DATA.turn = data.turn;
INTERFACE_DATA.play = data.play; 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.dawn.length > 0) { INTERFACE_DATA.handles[0] = data.dawn; }
if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; } if(data.dusk.length > 0) { INTERFACE_DATA.handles[1] = data.dusk; }

View File

@ -10,9 +10,12 @@ LANGUAGE.Terms = {
Dawn: new LANGUAGE.Term( "Dawn", "暁" ), Dawn: new LANGUAGE.Term( "Dawn", "暁" ),
Dusk: new LANGUAGE.Term( "Dusk", "黄昏" ), Dusk: new LANGUAGE.Term( "Dusk", "黄昏" ),
Handle: new LANGUAGE.Term( "Handle", "" ), Handle: new LANGUAGE.Term( "Handle", "" ),
Secret: new LANGUAGE.Term( "Secret", "" ), Secret: new LANGUAGE.Term( "Secret", "" ),
Browse: new LANGUAGE.Term( "Resume", "" ), Browse: new LANGUAGE.Term( "Browse", "" ),
Resume: new LANGUAGE.Term( "Resume", "" ), Resume: new LANGUAGE.Term( "Resume", "" ),
Check: new LANGUAGE.Term( "Check", "王手" ),
Checkmate: new LANGUAGE.Term( "Checkmate", "詰み" ),
}; };