Skip to content

Commit

Permalink
More accurately determine where to place tiles after Undo
Browse files Browse the repository at this point in the history
  • Loading branch information
m1foley committed Jul 3, 2024
1 parent 75a0623 commit e0e4394
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 13 deletions.
4 changes: 2 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

- CD: https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/
- Put everyone's discards in front of their hand (suggested by Mom)
- 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.
- 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).
- Bug: Undoing a win after a bot drew a tile hung bot (workaround: paused & unpaused bots)
- Shrink tile sizes on mobile
- Lobby not receiving bot player added
Expand Down Expand Up @@ -33,7 +33,7 @@
- Display everyone's wind direction instead of staircase
- Animate deal: 4 at a time goes into people's hand
- 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.
- Remember sorted hand so it doesn't get reshuffled when losing internet connection
- Remember sorted hand in browser so it doesn't get reshuffled when losing internet connection

## Future rule enforcement
- Winning tile was the last one picked up
38 changes: 29 additions & 9 deletions lib/mjw/core/seat.ex
Original file line number Diff line number Diff line change
Expand Up @@ -211,16 +211,36 @@ defmodule Mjw.Seat do
Enum.filter([seat.peektile, seat.wintile], & &1)
end

# Doesn't check wintile because it can never be populated in an undo_state
defp restore_to_hand(%__MODULE__{} = seat, %__MODULE__{} = undo_state_seat, tile)
when undo_state_seat.peektile == tile do
%{seat | peektile: tile}
end

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

seat |> Map.update!(removed_from_list, fn list -> list ++ [tile] end)
end
seat
|> Map.update!(removed_from_list, fn list ->
sorted_list = (list ++ [tile]) |> Mjw.Tile.sort()
sorted_list_index = sorted_list |> Enum.find_index(&(&1 == tile))
insert_before_tile = sorted_list |> Enum.at(sorted_list_index + 1)

insert_before_index =
if insert_before_tile do
list |> Enum.find_index(&(&1 == insert_before_tile))
else
length(list)
end

Enum.slice(list, 0, insert_before_index) ++
[tile] ++ Enum.slice(list, insert_before_index..-1//1)
end)
end
end
2 changes: 1 addition & 1 deletion lib/mjw/core/tile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Mjw.Tile do
@tile_format_regex ~r/^[ncbwd][a-z1-9]-[0-3]$/

@doc """
Sort according to beauty, with special tiles last
Sort by suit and then number
"""
def sort(tiles) do
Enum.sort_by(tiles, fn tile ->
Expand Down
2 changes: 1 addition & 1 deletion test/mjw/core/seat_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ defmodule Mjw.SeatTest do

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

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

test "restores a tile removed from the peektile by the undoable action" do
Expand Down
2 changes: 2 additions & 0 deletions test/mjw/core/tile_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ defmodule Mjw.TileTest do
"we-0",
"we-1",
"b9-0",
"b8-0",
"b9-1",
"n1-3",
"dp-0",
Expand All @@ -40,6 +41,7 @@ defmodule Mjw.TileTest do
"n1-3",
"c1-0",
"b1-3",
"b8-0",
"b9-0",
"b9-1",
"we-0",
Expand Down

0 comments on commit e0e4394

Please sign in to comment.