Skip to content

Commit e0e4394

Browse files
committed
More accurately determine where to place tiles after Undo
1 parent 75a0623 commit e0e4394

File tree

5 files changed

+35
-13
lines changed

5 files changed

+35
-13
lines changed

Diff for: TODO.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
- CD: https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/
44
- Put everyone's discards in front of their hand (suggested by Mom)
5-
- Bug: Can't undo to get first discarded tile of the game from bot (human went last, missed a discarded tile, can't go back to beginning of game). If there are no human actions to go back to, Undo should return to beginning of game.
5+
- If no undoable moves, Undo button should reset the game to get first discarded tile of the game from bot (human went last, missed a discarded tile, can't go back to beginning of game).
66
- Bug: Undoing a win after a bot drew a tile hung bot (workaround: paused & unpaused bots)
77
- Shrink tile sizes on mobile
88
- Lobby not receiving bot player added
@@ -33,7 +33,7 @@
3333
- Display everyone's wind direction instead of staircase
3434
- Animate deal: 4 at a time goes into people's hand
3535
- Sanity check for (possible race condition) bug: rearranging hand leads to duplicate tiles. Last time it happened after peek tile got put into hand, and user drag & dropped that new tile.
36-
- Remember sorted hand so it doesn't get reshuffled when losing internet connection
36+
- Remember sorted hand in browser so it doesn't get reshuffled when losing internet connection
3737

3838
## Future rule enforcement
3939
- Winning tile was the last one picked up

Diff for: lib/mjw/core/seat.ex

+29-9
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,36 @@ defmodule Mjw.Seat do
211211
Enum.filter([seat.peektile, seat.wintile], & &1)
212212
end
213213

214-
# Doesn't check wintile because it can never be populated in an undo_state
214+
defp restore_to_hand(%__MODULE__{} = seat, %__MODULE__{} = undo_state_seat, tile)
215+
when undo_state_seat.peektile == tile do
216+
%{seat | peektile: tile}
217+
end
218+
219+
# When restoring a tile to a hand during an Undo, the hand probably changed
220+
# since then so it's not always easy to determine the ideal position. We can
221+
# assume players sort their hands, so attempt to restore it next to the tile
222+
# that would follow it by sort order. If not available it goes to the end.
215223
defp restore_to_hand(%__MODULE__{} = seat, %__MODULE__{} = undo_state_seat, tile) do
216-
if undo_state_seat.peektile == tile do
217-
%{seat | peektile: tile}
218-
else
219-
removed_from_list =
220-
[:exposed, :concealed, :hiddengongs]
221-
|> Enum.find(fn list -> tile in Map.get(undo_state_seat, list) end)
224+
# Doesn't check wintile because it can never be populated in an undo_state
225+
removed_from_list =
226+
[:exposed, :concealed, :hiddengongs]
227+
|> Enum.find(fn list -> tile in Map.get(undo_state_seat, list) end)
222228

223-
seat |> Map.update!(removed_from_list, fn list -> list ++ [tile] end)
224-
end
229+
seat
230+
|> Map.update!(removed_from_list, fn list ->
231+
sorted_list = (list ++ [tile]) |> Mjw.Tile.sort()
232+
sorted_list_index = sorted_list |> Enum.find_index(&(&1 == tile))
233+
insert_before_tile = sorted_list |> Enum.at(sorted_list_index + 1)
234+
235+
insert_before_index =
236+
if insert_before_tile do
237+
list |> Enum.find_index(&(&1 == insert_before_tile))
238+
else
239+
length(list)
240+
end
241+
242+
Enum.slice(list, 0, insert_before_index) ++
243+
[tile] ++ Enum.slice(list, insert_before_index..-1//1)
244+
end)
225245
end
226246
end

Diff for: lib/mjw/core/tile.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ defmodule Mjw.Tile do
55
@tile_format_regex ~r/^[ncbwd][a-z1-9]-[0-3]$/
66

77
@doc """
8-
Sort according to beauty, with special tiles last
8+
Sort by suit and then number
99
"""
1010
def sort(tiles) do
1111
Enum.sort_by(tiles, fn tile ->

Diff for: test/mjw/core/seat_test.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ defmodule Mjw.SeatTest do
587587

588588
result = Mjw.Seat.merge_for_undo(seat, undo_state_seat)
589589

590-
assert result == %{seat | hiddengongs: ["n3-0", "n4-0", "n3-1"]}
590+
assert result == %{seat | hiddengongs: ["n3-0", "n3-1", "n4-0"]}
591591
end
592592

593593
test "restores a tile removed from the peektile by the undoable action" do

Diff for: test/mjw/core/tile_test.exs

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ defmodule Mjw.TileTest do
2727
"we-0",
2828
"we-1",
2929
"b9-0",
30+
"b8-0",
3031
"b9-1",
3132
"n1-3",
3233
"dp-0",
@@ -40,6 +41,7 @@ defmodule Mjw.TileTest do
4041
"n1-3",
4142
"c1-0",
4243
"b1-3",
44+
"b8-0",
4345
"b9-0",
4446
"b9-1",
4547
"we-0",

0 commit comments

Comments
 (0)