Skip to content
The Go game, implemented with Phoenix LiveView.
Branch: master
Clone or download
Pull request Compare This branch is 11 commits ahead of starter.
jeffkreeftmeijer Add Game.legal?/2 to handle to ko rule
Aside from allowing the player to undo and redo moves, keeping history
allows us to implement Go's ko rule.

> A play is illegal if it would have the effect (after all steps of the
> play have been completed) of creating a position that has occurred
> previously in the game.

Go prevents players from making moves that revert the board to a
previous state. In practice, this happens when a stone is captured, and
the newly added stone is immediately taken by the other player.

Currently, we validate moves in the `State.legal?/2` function, which
checks if a position is empty, and makes sure placing a stone on that
position has liberties.

To implement the ko rule, we need the history of game states, meaning we
need access to the `Game` struct. To do that, we add a function named
`Game.legal?/2`.

    # lib/hayago/game.ex
    defmodule Hayago.Game do
      # ...

      def legal?(game, position) do
        State.legal?(Game.state(game), position) and not repeated_state?(game, position)
      end

      defp repeated_state?(game, position) do
        %Game{history: [%State{positions: tentative_positions} | history]} =
          Game.place(game, position)

        Enum.any?(history, fn %State{positions: positions} ->
          positions == tentative_positions
        end)
      end

      # ...
    end

Our new function takes the game struct as its first argument, and the
position a new stone is places as the second. It calls `State.legal?/2`
to make sure the already-implemented rules are satisfied. Then, it makes
sure the new state hasn't already happened using `repeated_state?/2`, a
private function that places the stone and compares the new state to the
history list.

Finally, we'll update the template to switch from using `State.legal?/2`
directly to using `Game.legal?/2`, which takes the game history in
account.

    # lib/hayago_web/templates/game/index.html.leex
    # ...

    <div class="board <%= @state.current %>">
      <%= for {value, index} <- Enum.with_index(@state.positions) do %>
        <%= if Hayago.Game.legal?(@GAMe, index) do %>
          <button phx-click="place" phx-value="<%= index %>" class="<%= value %>"></button>
        <% else %>
          <button class="<%= value %>" disabled="disabled"></button>
        <% end %>
      <% end %>
    </div>

    # ...
Latest commit abe3e79 Jun 25, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets
config Install Phoenix LiveView according to its README Jun 24, 2019
lib Add Game.legal?/2 to handle to ko rule Jul 4, 2019
priv/gettext $ mix phx.new hayago --no-ecto Jun 24, 2019
test Add Game.legal?/2 to handle to ko rule Jul 4, 2019
.formatter.exs $ mix phx.new hayago --no-ecto Jun 24, 2019
.gitignore
README.md Update README Jul 4, 2019
mix.exs Install Phoenix LiveView according to its README Jun 24, 2019
mix.lock Install Phoenix LiveView according to its README Jun 24, 2019

README.md

Hayago

The Go game, implemented with Phoenix LiveView.

Hayago (早碁) means "quick go" or "fast go". In the context of Go, it means "quick play".

Usage

Check out the starter branch to follow along with the first and second article. The master branch holds the completed and deployed version of the project.

You can’t perform that action at this time.