-
Notifications
You must be signed in to change notification settings - Fork 6
/
SnakeModel.elm
106 lines (70 loc) · 2.1 KB
/
SnakeModel.elm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
module SnakeModel where
import Maybe exposing (withDefault)
import List exposing ((::), drop, head, isEmpty, map, reverse)
import Set
type alias Position =
{ x: Int
, y: Int
}
type alias Delta =
{ dx: Int
, dy: Int
}
type alias Snake =
{ front: List Position
, back: List Position
}
type alias SnakeState =
{ snake: Snake
, delta: Delta
, food: Maybe Position
, ticks: Int
, gameOver: Bool
}
initialSnake =
{ front = [{x = 0, y = 0}, {x = 0, y = -1}, {x = 0, y = -2}, {x = 0, y = -3}]
, back = []
}
initialDelta = { dx = 0, dy = 1 }
initialFood = Nothing
initialState =
{ snake = initialSnake
, delta = initialDelta
, food = initialFood
, ticks = 0
, gameOver = False
}
type Event = Tick Position | Direction Delta | NewGame | Ignore
boardSize = 15
boxSize = boardSize + boardSize + 1
velocity = 5
nextPosition : Snake -> Delta -> Position
nextPosition snake {dx,dy} =
let headPosition = head snake.front |> withDefault {x=0,y=0}
in { x = headPosition.x + dx, y = headPosition.y + dy }
moveSnakeForward : Snake -> Delta -> Maybe Position -> Snake
moveSnakeForward snake delta food =
let next = nextPosition snake delta
tailFunction =
case food of
Nothing -> drop 1
Just f -> if next == f then identity else drop 1
in
if isEmpty snake.back
then { front = [next]
, back = (tailFunction << reverse) snake.front }
else { front = next :: snake.front
, back = tailFunction snake.back }
isInSnake : Snake -> Position -> Bool
isInSnake snake position =
let frontSet = Set.fromList <| map toString snake.front
backSet = Set.fromList <| map toString snake.back
in
Set.member (toString position) frontSet || Set.member (toString position) backSet
collision : SnakeState -> Bool
collision state =
let next = nextPosition state.snake state.delta
in
if abs next.x > boardSize || abs next.y > boardSize || isInSnake state.snake next
then True
else False