Skip to content

Commit b6fab92

Browse files
authored
Merge pull request #304 from TruncateGame/feat/stable-hands
Change tile placements to be slot-based
2 parents 6cdad10 + 768d269 commit b6fab92

File tree

19 files changed

+185
-86
lines changed

19 files changed

+185
-86
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
fetch-depth: 1
3434

3535
- name: Cache
36-
uses: actions/cache@v2
36+
uses: actions/cache@v4
3737
with:
3838
path: |
3939
~/.cargo/registry

truncate_client/src/lil_bits/board.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,14 @@ impl<'a> BoardUI<'a> {
173173
interactions.selected_tile_on_board = None;
174174
}
175175

176-
if let Some((tile, _)) =
176+
if let Some((tile_index, tile)) =
177177
interactions.selected_tile_in_hand
178178
{
179-
msg = Some(PlayerMessage::Place(
179+
msg = Some(PlayerMessage::Place {
180180
coord,
181-
*hand.get(tile).unwrap(),
182-
));
181+
slot: Some(tile_index),
182+
tile,
183+
});
183184

184185
interactions.selected_tile_in_hand = None;
185186
interactions.selected_square_on_board = None;
@@ -197,12 +198,15 @@ impl<'a> BoardUI<'a> {
197198
}
198199
}
199200

200-
if let Some(tile) = interactions.released_tile {
201-
if tile.1 == coord {
202-
msg = Some(PlayerMessage::Place(
201+
if let Some((tile_index, tile, released_coord)) =
202+
interactions.released_tile
203+
{
204+
if released_coord == coord {
205+
msg = Some(PlayerMessage::Place {
203206
coord,
204-
*hand.get(tile.0).unwrap(),
205-
));
207+
slot: Some(tile_index),
208+
tile,
209+
});
206210
interactions.selected_tile_in_hand = None;
207211
interactions.selected_tile_on_board = None;
208212
interactions.released_tile = None;

truncate_client/src/lil_bits/hand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl<'a> HandUI<'a> {
189189
coord: Some(coord), ..
190190
}) = depot.interactions.hovered_unoccupied_square_on_board
191191
{
192-
depot.interactions.released_tile = Some((i, coord));
192+
depot.interactions.released_tile = Some((i, *char, coord));
193193
}
194194
}
195195

truncate_client/src/regions/active_game/mod.rs

+2-14
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ impl ActiveGame {
288288
player_number: _,
289289
next_player_number,
290290
board,
291-
hand: _,
291+
hand,
292292
changes,
293293
game_ends_at,
294294
paused,
@@ -334,19 +334,7 @@ impl ActiveGame {
334334
.insert(board_change.detail.coordinate, board_change.clone());
335335
}
336336

337-
for hand_change in changes.iter().filter_map(|c| match c {
338-
Change::Hand(change) => Some(change),
339-
_ => None,
340-
}) {
341-
for removed in &hand_change.removed {
342-
if let Some(pos) = self.hand.iter().position(|t| t == removed) {
343-
self.hand.remove(pos);
344-
}
345-
}
346-
let reduced_length = self.hand.len();
347-
self.hand.0.extend(&hand_change.added);
348-
self.new_hand_tiles = (reduced_length..self.hand.len()).collect();
349-
}
337+
self.hand = hand;
350338

351339
self.time_changes = changes
352340
.iter()

truncate_client/src/regions/single_player.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -649,10 +649,11 @@ impl SinglePlayerState {
649649
}
650650

651651
let next_move = match next_msg {
652-
Some((player, PlayerMessage::Place(position, tile))) => Some(Move::Place {
652+
Some((player, PlayerMessage::Place { coord, slot, tile })) => Some(Move::Place {
653653
player,
654+
slot,
654655
tile,
655-
position,
656+
position: coord,
656657
}),
657658
Some((player, PlayerMessage::Swap(from, to))) => Some(Move::Swap {
658659
player,

truncate_client/src/regions/tutorial.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ fn action_to_move(player: usize, action: &str) -> Move {
5252
} else if from.len() == 1 {
5353
Move::Place {
5454
player,
55+
slot: None,
5556
tile: from.chars().next().unwrap(),
5657
position: to_pos,
5758
}
@@ -296,6 +297,7 @@ impl TutorialState {
296297
// TODO: Use some special infinite bag?
297298
bag: TileBag::latest(None).1,
298299
judge: Judge::new(vec![]),
300+
move_sequence: vec![],
299301
battle_count: 0,
300302
turn_count: 0,
301303
player_turn_count: vec![0, 0],
@@ -547,10 +549,11 @@ impl TutorialState {
547549
}
548550

549551
let Some(game_move) = (match msg {
550-
PlayerMessage::Place(position, tile) => Some(Move::Place {
552+
PlayerMessage::Place { coord, slot, tile } => Some(Move::Place {
551553
player: 0,
554+
slot,
552555
tile,
553-
position,
556+
position: coord,
554557
}),
555558
PlayerMessage::Swap(from, to) => Some(Move::Swap {
556559
player: 0,

truncate_client/src/utils/control_devices/keyboard.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,11 @@ pub fn handle_input(
130130
let current_selection = ensure_board_selection(depot);
131131

132132
if let Some(char) = hand.get(key) {
133-
msg = Some(PlayerMessage::Place(current_selection, *char))
133+
msg = Some(PlayerMessage::Place {
134+
coord: current_selection,
135+
slot: Some(key),
136+
tile: *char,
137+
});
134138
}
135139
}
136140
}
@@ -143,10 +147,11 @@ pub fn handle_input(
143147
) {
144148
let current_selection = ensure_board_selection(depot);
145149

146-
msg = Some(PlayerMessage::Place(
147-
current_selection,
148-
letter.chars().next().unwrap(),
149-
))
150+
msg = Some(PlayerMessage::Place {
151+
coord: current_selection,
152+
slot: None,
153+
tile: letter.chars().next().unwrap(),
154+
})
150155
}
151156
}
152157

truncate_client/src/utils/depot.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub struct HoveredRegion {
2424
#[derive(Clone, Default)]
2525
pub struct InteractionDepot {
2626
pub view_only: bool,
27-
pub released_tile: Option<(usize, Coordinate)>,
27+
pub released_tile: Option<(usize, char, Coordinate)>,
2828
pub dragging_tile_on_board: Option<(Coordinate, Square)>,
2929
pub selected_tile_on_board: Option<(Coordinate, Square)>,
3030
pub hovered_tile_on_board: Option<(Coordinate, Square)>,

truncate_core/src/error.rs

+7
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,11 @@ pub enum GamePlayError {
3838

3939
#[error("Player {player:?} doesn't have a '{tile:?}' tile")]
4040
PlayerDoesNotHaveTile { player: usize, tile: char },
41+
42+
#[error("Player {player:?} doesn't have a '{tile:?}' tile in slot {slot}")]
43+
PlayerDoesNotHaveTileInSlot {
44+
player: usize,
45+
tile: char,
46+
slot: usize,
47+
},
4148
}

truncate_core/src/game.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub struct Game {
3838
pub board: Board,
3939
pub bag: TileBag,
4040
pub judge: Judge,
41+
pub move_sequence: Vec<Move>,
4142
pub battle_count: u32,
4243
pub turn_count: u32,
4344
pub player_turn_count: Vec<u32>,
@@ -72,6 +73,7 @@ impl Game {
7273
board,
7374
bag: TileBag::generation(rules.tile_generation, tile_seed),
7475
judge: Judge::default(),
76+
move_sequence: vec![],
7577
battle_count: 0,
7678
turn_count: 0,
7779
player_turn_count: Vec::with_capacity(2),
@@ -104,6 +106,7 @@ impl Game {
104106
board,
105107
bag: TileBag::generation(rules.tile_generation, tile_seed),
106108
judge: Judge::default(),
109+
move_sequence: vec![],
107110
battle_count: 0,
108111
turn_count: 0,
109112
player_turn_count: Vec::with_capacity(2),
@@ -412,7 +415,7 @@ impl Game {
412415
}
413416

414417
self.recent_changes = match self.make_move(
415-
next_move,
418+
next_move.clone(),
416419
attacker_dictionary,
417420
defender_dictionary,
418421
cached_word_judgements,
@@ -423,6 +426,7 @@ impl Game {
423426
return Err(format!("{msg}"));
424427
}
425428
};
429+
self.move_sequence.push(next_move);
426430

427431
// Track any new tiles that the player may have gained vision of from this turn
428432
{
@@ -548,6 +552,7 @@ impl Game {
548552
match game_move {
549553
Move::Place {
550554
player,
555+
slot,
551556
tile,
552557
position: player_reported_position,
553558
} => {
@@ -579,8 +584,21 @@ impl Game {
579584
return Err(GamePlayError::NonAdjacentPlace);
580585
}
581586

582-
if !self.players[player].has_tile(tile) {
583-
return Err(GamePlayError::PlayerDoesNotHaveTile { player, tile });
587+
match slot {
588+
Some(slot) => {
589+
if !self.players[player].has_tile_in_slot(tile, slot) {
590+
return Err(GamePlayError::PlayerDoesNotHaveTileInSlot {
591+
player,
592+
tile,
593+
slot,
594+
});
595+
}
596+
}
597+
None => {
598+
if !self.players[player].has_tile(tile) {
599+
return Err(GamePlayError::PlayerDoesNotHaveTile { player, tile });
600+
}
601+
}
584602
}
585603

586604
changes.push(Change::Board(BoardChange {
@@ -589,7 +607,7 @@ impl Game {
589607
.set(position, player, tile, attacker_dictionary)?,
590608
action: BoardChangeAction::Added,
591609
}));
592-
changes.push(self.players[player].use_tile(tile, &mut self.bag)?);
610+
changes.push(self.players[player].use_tile(tile, slot, &mut self.bag)?);
593611

594612
self.resolve_attack(
595613
player,

truncate_core/src/messages.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ pub enum PlayerMessage {
4343
EditName(String),
4444
StartGame,
4545
Resign,
46-
Place(Coordinate, char),
46+
Place {
47+
coord: Coordinate,
48+
slot: Option<usize>,
49+
tile: char,
50+
},
4751
Swap(Coordinate, Coordinate),
4852
Rematch,
4953
Pause,
@@ -103,7 +107,9 @@ impl fmt::Display for PlayerMessage {
103107
PlayerMessage::EditName(name) => write!(f, "Set name to {name}"),
104108
PlayerMessage::StartGame => write!(f, "Start the game"),
105109
PlayerMessage::Resign => write!(f, "Resign"),
106-
PlayerMessage::Place(coord, tile) => write!(f, "Place {} at {}", tile, coord),
110+
PlayerMessage::Place { coord, slot, tile } => {
111+
write!(f, "Place slot {:?} ({}) at {}", slot, tile, coord)
112+
}
107113
PlayerMessage::Swap(a, b) => write!(f, "Swap the tiles at {} and {}", a, b),
108114
PlayerMessage::Rematch => write!(f, "Rematch!"),
109115
PlayerMessage::Pause => write!(f, "Pause!"),

0 commit comments

Comments
 (0)