146 lines
4.4 KiB
Rust
146 lines
4.4 KiB
Rust
use log::{debug, trace};
|
|
use spacetimedb::{ReducerContext, reducer};
|
|
|
|
use crate::tables::{player::player, *};
|
|
use jong_types::states::TurnState;
|
|
|
|
pub fn deal_hands(ctx: &ReducerContext, lobby_id: u32) {
|
|
let players = ctx.db.player().lobby_id().filter(lobby_id);
|
|
let bots = ctx.db.bot().lobby_id().filter(lobby_id);
|
|
|
|
let mut wall = ctx.db.wall().lobby_id().find(lobby_id).unwrap();
|
|
|
|
// FIXME rectify deal orders
|
|
for mut player in players {
|
|
let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13);
|
|
wall = ctx.db.wall().lobby_id().update(wall);
|
|
tiles.sort_by_key(|t| t.tile);
|
|
player.hand = tiles;
|
|
ctx.db.player().id().update(player);
|
|
}
|
|
for mut bot in bots {
|
|
let mut tiles = wall.tiles.split_off(wall.tiles.len() - 13);
|
|
wall = ctx.db.wall().lobby_id().update(wall);
|
|
tiles.sort_by_key(|t| t.tile);
|
|
bot.hand = tiles;
|
|
ctx.db.bot().id().update(bot);
|
|
}
|
|
}
|
|
|
|
#[reducer]
|
|
pub fn draw_tile(ctx: &ReducerContext) {
|
|
let mut player = ctx.db.player().identity().find(ctx.sender).unwrap();
|
|
let mut wall = ctx.db.wall().lobby_id().find(player.lobby_id).unwrap();
|
|
|
|
// TODO if no more tiles, exhaust somehow
|
|
|
|
player.drawn_tile = wall.tiles.pop();
|
|
|
|
ctx.db.wall().lobby_id().update(wall);
|
|
ctx.db.player().id().update(player);
|
|
}
|
|
|
|
// TODO make sure this can't be called or just error here?
|
|
#[reducer]
|
|
pub fn discard_tile(ctx: &ReducerContext, tile_id: u32) -> Result<(), String> {
|
|
let mut player = ctx.db.player().identity().find(ctx.sender).unwrap();
|
|
let mut lobby = ctx.db.lobby().id().find(player.lobby_id).unwrap();
|
|
|
|
let dealt_tile = if let Some(dealt) = ctx.db.tile().id().find(tile_id) {
|
|
if let Some(drawn) = player.drawn_tile {
|
|
if drawn.id == dealt.id {
|
|
// dealt from drawn tile
|
|
dealt
|
|
} else if let Some((i, _)) = player
|
|
.hand
|
|
.iter()
|
|
.enumerate()
|
|
.find(|(_, t)| t.id == tile_id)
|
|
{
|
|
// dealt from hand
|
|
let dealt = player.hand.remove(i);
|
|
player.hand.push(drawn);
|
|
player.hand.sort_by_key(|t| t.tile);
|
|
|
|
dealt
|
|
} else {
|
|
return Err(format!(
|
|
"player {} attempted to deal tile {} not in hand or drawn",
|
|
player.id, tile_id
|
|
));
|
|
}
|
|
} else {
|
|
return Err(format!(
|
|
"player {} attempted to deal tile {} without having drawn",
|
|
player.id, tile_id
|
|
));
|
|
}
|
|
} else {
|
|
return Err(format!(
|
|
"player {} attempted to deal nonexistant tile {}",
|
|
player.id, tile_id
|
|
));
|
|
};
|
|
|
|
player.pond.push(dealt_tile);
|
|
player.drawn_tile = None;
|
|
lobby.turn_state = TurnState::RonChiiPonKan;
|
|
|
|
let player = ctx.db.player().id().update(player);
|
|
ctx.db.lobby().id().update(lobby);
|
|
|
|
debug!("player {} discarded tile {:?}", player.id, dealt_tile.tile);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[reducer]
|
|
pub fn skip_call(ctx: &ReducerContext) {
|
|
trace!("skip_call");
|
|
|
|
let player = ctx.db.player().identity().find(ctx.sender).unwrap();
|
|
let mut lobby = ctx.db.lobby().id().find(player.lobby_id).unwrap();
|
|
|
|
lobby.turn_state = TurnState::Tsumo;
|
|
lobby.current_idx += 1;
|
|
if lobby.current_idx >= 3 {
|
|
lobby.current_idx = 0;
|
|
}
|
|
|
|
// FIXME where better can this go
|
|
bot_moves(ctx, &mut lobby);
|
|
|
|
ctx.db.player().id().update(player);
|
|
ctx.db.lobby().id().update(lobby);
|
|
}
|
|
|
|
fn bot_moves(ctx: &ReducerContext, lobby: &mut Lobby) {
|
|
let mut wall = ctx.db.wall().lobby_id().find(lobby.id).unwrap();
|
|
if let Some(PlayerOrBot::Bot { id }) = lobby.players.get(lobby.current_idx as usize + 1) {
|
|
let mut bot = ctx.db.bot().id().find(id).unwrap();
|
|
bot.pond.push(wall.tiles.pop().unwrap());
|
|
ctx.db.bot().id().update(bot);
|
|
lobby.turn_state = TurnState::RonChiiPonKan;
|
|
} else {
|
|
lobby.turn_state = TurnState::Tsumo;
|
|
}
|
|
|
|
lobby.current_idx += 1;
|
|
if lobby.current_idx >= 3 {
|
|
lobby.current_idx = 0;
|
|
}
|
|
}
|
|
|
|
// #[view(name = view_player_hand, public)]
|
|
// pub fn view_player_hand(ctx: &ViewContext) -> Option<Hand> {
|
|
// ctx.db
|
|
// .player()
|
|
// .identity()
|
|
// .find(ctx.sender)
|
|
// .map(|p| ctx.db.hand().id().find(p.hand_id))?
|
|
// }
|
|
|
|
// #[reducer]
|
|
// pub fn sort_hand(ctx: &ReducerContext) {
|
|
// todo!()
|
|
// }
|