@@ -45,13 +45,46 @@ func (m *model) spawnEnemy() {
45
45
m.table [row ][col ] = enemy
46
46
}
47
47
48
+ func (m * model ) moveEnemies () {
49
+ for row := 1 ; row < tableHeight - 1 ; row ++ {
50
+ for col := 1 ; col < tableWidth - 1 ; col ++ {
51
+ if m.table [row ][col ] == enemy {
52
+ // Move enemy randomly to one of the four directly neighbooring cells if it is empty
53
+ // or contains the player. Borders, items and other enemies will block enemy moves though.
54
+
55
+ neighboors := [4 ][2 ]int {
56
+ [2 ]int {row - 1 , col }, // Top neighboor.
57
+ [2 ]int {row , col + 1 }, // Right neighboor.
58
+ [2 ]int {row + 1 , col }, // Bottom neighboor.
59
+ [2 ]int {row , col - 1 }, // Right neighboor.
60
+ }
61
+
62
+ targetIndex := rand .Intn (len (neighboors ))
63
+ targetRow := neighboors [targetIndex ][0 ]
64
+ targetCol := neighboors [targetIndex ][1 ]
65
+
66
+ if m.table [targetRow ][targetCol ] == empty {
67
+ // Target cell is empty. Move enemy and clear the old one.
68
+ m.table [targetRow ][targetCol ] = enemy
69
+ m.table [row ][col ] = empty
70
+ } else if m.table [targetRow ][targetCol ] == player {
71
+ // Target cell contains the player. Attack and stop further processing, this game is over!
72
+ m .gameOver = true
73
+
74
+ return
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+
48
81
func (m * model ) randomFreeCoordinates () (row , col int ) {
49
82
// Generate some random coordinates.
50
83
row , col = randomCoordinates ()
51
84
52
85
// Check that the random cell is empty.
53
86
// If not repeat randomizing until we find an empty cell.
54
- for m.table [row ][col ] != 0 {
87
+ for m.table [row ][col ] != empty {
55
88
row , col = randomCoordinates ()
56
89
}
57
90
@@ -74,7 +107,7 @@ func (m *model) movePlayer(row, col int) {
74
107
}
75
108
76
109
// Clear old player location.
77
- m.table [m.playerRow ][m.playerCol ] = 0
110
+ m.table [m.playerRow ][m.playerCol ] = empty
78
111
79
112
if m.table [row ][col ] == enemy {
80
113
// We ran into an enemy. Signal game over and skip further
@@ -137,12 +170,15 @@ func (m *model) playerRight() {
137
170
// to use for a new game.
138
171
func (m * model ) init () {
139
172
// Clear and reset all fields as init() is also used for restarting
140
- // an existing game. Therefore our model needs to be fresh.
141
- // By default, all entries in our table have value zero as type rune
142
- // is based on int and represents symbols. Initially, all cells are
143
- // empty.
144
- var table [tableHeight ][tableWidth ]rune
145
- m .table = table
173
+ // an existing game. Therefore, our model needs to be fresh.
174
+
175
+ // Initially, set every cell to our empty symbol.
176
+ for row := 0 ; row < tableHeight ; row ++ {
177
+ for col := 0 ; col < tableWidth ; col ++ {
178
+ m.table [row ][col ] = empty
179
+ }
180
+ }
181
+
146
182
m .playerRow = 0
147
183
m .playerCol = 0
148
184
m .score = 0
@@ -208,12 +244,16 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
208
244
return m , tea .Quit
209
245
case "up" :
210
246
m .playerUp ()
247
+ m .moveEnemies ()
211
248
case "down" :
212
249
m .playerDown ()
250
+ m .moveEnemies ()
213
251
case "left" :
214
252
m .playerLeft ()
253
+ m .moveEnemies ()
215
254
case "right" :
216
255
m .playerRight ()
256
+ m .moveEnemies ()
217
257
}
218
258
}
219
259
@@ -237,16 +277,11 @@ func (m *model) View() string {
237
277
return builder .String ()
238
278
}
239
279
240
- // Iterate our table (2d array) and print non-empty fields as set in
241
- // our model. Empty (zero) fields shall be printed with a blank space.
280
+ // Iterate our table (2d array) and print the cells.
242
281
for _ , row := range m .table {
243
282
244
283
for _ , cell := range row {
245
- if cell == 0 {
246
- builder .WriteRune (empty )
247
- } else {
248
- builder .WriteRune (cell )
249
- }
284
+ builder .WriteRune (cell )
250
285
}
251
286
252
287
// Go to next line after each row.
0 commit comments