Browse Source

bottom merging and game over mechanic etc

master 0.1.3
Julian Noble 2 years ago
parent
commit
4f5ecc96ed
  1. 53
      lib/bottom.ex
  2. 59
      lib/tetris.ex
  3. 35
      test/bottom_test.exs
  4. 44
      test/tetris_test.exs

53
lib/bottom.ex

@ -15,4 +15,57 @@ defmodule Tetris.Bottom do
Enum.any?(points, &collides?(bottom,&1))
end
def complete_ys(bottom) do
bottom
|> Map.keys
|> Enum.map(&elem(&1, 1))
|> Enum.uniq
|> Enum.filter(fn row -> complete?(bottom, row) end)
end
def complete?(bottom, row) do
count =
bottom
|> Map.keys
|> Enum.filter(fn {_x,y} -> y == row end)
|> Enum.count
count == 10
end
def collapse_row(bottom, row) do
bad_keys =
bottom
|> Map.keys
|> Enum.filter(fn {_x,y} -> y == row end)
bottom
|> Map.drop(bad_keys)
|> Enum.map(&move_bad_points_up(&1, row))
|> Map.new
end
def move_bad_points_up({{x, y}, {x, y, colour}}, row) when y < row do
#move_bad_poitns_down ???
{{x, y+1}, {x, y+1, colour}}
end
def move_bad_points_up(key_value, _row) do
key_value
end
def full_collapse(bottom) do
# a bottom less completed row
rows =
bottom
|> complete_ys()
|> Enum.sort
new_bottom =
Enum.reduce(rows, bottom, &collapse_row(&2, &1))
{Enum.count(rows), new_bottom}
end
end

59
lib/tetris.ex

@ -8,7 +8,59 @@ defmodule Tetris do
end
def try_move(brick, bottom, f) do
def drop(brick, bottom, colour) do
new_brick =
Brick.down(brick)
maybe_do_drop(
Bottom.collides?(bottom, prepare(new_brick)),
bottom,
brick,
new_brick,
colour
)
end
def maybe_do_drop(true=_collided,bottom, old_brick, _new_block, colour) do
new_brick = Brick.new_random
points =
old_brick
|> prepare
|> Points.with_colour(colour)
{count, new_bottom} =
bottom
|> Bottom.merge(points)
|> Bottom.full_collapse
%{
brick: new_brick,
bottom: new_bottom,
score: score(count),
game_over: Bottom.collides?(new_bottom, prepare(new_brick))
}
end
def maybe_do_drop(false=_collided,bottom, _old_brick, new_block, _colour) do
%{
brick: new_block,
bottom: bottom,
score: 1,
game_over: false
}
end
def score(0), do: 0
def score(count) do
100 * round(:math.pow(2, count))
end
def try_left(brick, bottom), do: try_move(brick,bottom, &Brick.left/1)
def try_right(brick, bottom), do: try_move(brick,bottom, &Brick.right/1)
def try_spin(brick, bottom), do: try_move(brick,bottom, &Brick.spin_90/1)
defp try_move(brick, bottom, f) do
new_brick = f.(brick)
if Bottom.collides?(bottom, prepare(new_brick)) do
@ -17,9 +69,4 @@ defmodule Tetris do
new_brick
end
end
def try_left(brick, bottom), do: try_move(brick,bottom, &Brick.left/1)
def try_right(brick, bottom), do: try_move(brick,bottom, &Brick.right/1)
def try_spin(brick, bottom), do: try_move(brick,bottom, &Brick.spin_90/1)
end

35
test/bottom_test.exs

@ -26,4 +26,39 @@ defmodule BottomTest do
}
assert actual == expected
end
test "compute complete ys" do
bottom = new_bottom(20, [{{19, 19}, {19, 19, :red}}])
assert complete_ys(bottom) == [20]
end
test "collapse single row" do
bottom = new_bottom(20, [{{19, 19}, {19, 19, :red}}])
actual = Map.keys(collapse_row(bottom, 20))
refute {19,19} in actual
assert {19, 20} in actual
assert Enum.count(actual) == 1
#IO.inspect collapse_row(bottom, 20)
end
test "full collapse with single row" do
bottom = new_bottom(20, [{{19, 19}, {19, 19, :red}}])
{actual_count, actual_bottom} = full_collapse(bottom)
assert actual_count == 1
assert {19,20} in Map.keys(actual_bottom)
end
def new_bottom(complete_row, xtras) do
(xtras ++
(1..10
|> Enum.map( fn x ->
{{x, complete_row}, {x,complete_row, :red}}
end)))
|> Map.new
end
end

44
test/tetris_test.exs

@ -22,5 +22,49 @@ defmodule TetrisTest do
assert actual == brick
end
test "drops without merging" do
brick = Brick.new(%{location: {5,5}})
bottom = %{}
expected = %{
brick: Brick.down(brick),
bottom: %{},
score: 1,
game_over: false
}
actual = drop(brick, bottom, :red)
assert actual == expected
end
test "drops and merges" do
brick = Brick.new(%{location: {5,16}})
bottom = %{}
%{score: score, bottom: actual_bottom} =
Tetris.drop(brick, bottom, :red)
assert Map.get(actual_bottom, {7,20}) == {7,20, :red}
assert score == 0
end
test "drops and merges with collapse" do
brick = Brick.new(%{location: {5,16}})
bottom =
for x <- 1..10, y <- 17..20, x != 7 do
{{x,y}, {x,y, :red}}
end
|> Map.new
%{score: score, bottom: actual_bottom} =
Tetris.drop(brick, bottom, :red)
assert actual_bottom == %{}
assert score == 1600
end
end

Loading…
Cancel
Save