-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproject-5.qmd
382 lines (297 loc) · 12.7 KB
/
project-5.qmd
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
---
title: "Programming Project 5"
---
```{r}
#| echo: false
#| message: false
#| warning: false
library(tidyverse)
library(readxl)
assignments <- read_excel("assessment_schedule.xlsx") %>%
mutate(formatted_date = format(due_date, "%A, %B %d, %Y"))
```
Programming Projects are to be submitted to [gradescope](https://www.gradescope.com/courses/934148).
**Due date: `r assignments %>% filter(assessment == "Programming Project 5") %>% pull(formatted_date)` at 9pm**
In this programming project you will implement a number of Python functions to implement a simplified version of chess. Make sure you follow the provided [style guide](https://adrianapicoral.com/csc-110/style.html) (you will be graded on it!).
Name your program `one_d_chess.py` to submit to gradescope. Make sure that gradescope gives you the points for passing the test cases.
This programming project is an adaptation of Ben Dicken's 1 Dimensional Chess Programming Assignment.
In this programming project, you will be implementing a simpler variant of chess: 1D Chess! 1D chess is a variant of the game that is played on a board that has only one column of spaces, rather than a grid of spaces, as in typical chess. There are actually [multiple variants of 1D chess](https://www.chessvariants.com/shape.dir/onedim.html). In this PA, you should implement a custom variant of 1D chess, which I'll refer to as "110 1D chess".
## **1D Chess Rules**
In 110 1D chess, the board will be 1 by 9. Each player will get one king, and two knights. The white pieces go on the left, and the black on the right. The starting positions for the pieces of the game should be as follows:
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
Kings and Knights move and kill their opponents differently. Knights can move either left or right, and when they move thy jump two pieces over. If they land on another piece, they kill them and take their spot. The king can move left or right, until they hit either another piece or an edge of the board. If a king hits another piece, they kill them and take their place. In chess, a player cannot typically kill one of their own pieces. In 110 1D chess, a king or knight can kill one of their own, if they hit or land on them, so be careful!
# Functions to implement
## Start Game
Write a function called `create_board` that takes no arguments. It returns a list with the initial state of the board (as shown in the test case below)
Test case:
```{python}
#| eval: false
print( create_board() ) # ["WKi", "WKn", "WKn",
# "EMPTY", "EMPTY", "EMPTY",
# "BKn", "BKn", "BKi"]
```
## Print Board
This functions should have one parameter variable, the board list. The job of this function is to simply print out the board to standard output. If the board is passed in and in the initial game state, the output should look like so:
Test case for initial board state:
```{python}
#| eval: false
board = create_board()
print( printable_board(board) ) # "+-----------------------------------------------------+\n
# | WKi | WKn | WKn | | | | BKn | BKn | BKi |\n
# +-----------------------------------------------------+"
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
## Check move validity
This function has three parameter variables. The board (a list, representing the 1 by 9 board), the position (index) of the player to move, and player (WHITE or BLACK). This function should return a boolean (`True` or `False`). True if the desired move is valid, False otherwise. A move is valid if:
- The position (index) is a valid index in the `board` list
- The position is an index of one of the current player's pieces on the board (for example, position 6 is an index of one of the BLACK's pieces - BKn)
You do not need a while loop or for loop within this function. It can be accomplished with if statements. If the above two conditions are True, the function should return True. In any other case, return False.
Test cases:
```{python}
#| eval: false
board = create_board()
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_valid_move(board, 1, "BLACK" ) == False
assert is_valid_move(board, 9, "BLACK" ) == False
assert is_valid_move(board, -1, "BLACK" ) == False
assert is_valid_move(board, 6, "BLACK" ) == True
assert is_valid_move(board, 2, "WHITE" ) == True
```
## Move a king
This function has the same three parameters as the `is_valid_move` function except the third parameter should be the direction. `move_king` should actually move a king on the board (thus, it should change the board list). In 110 1d Chess, a king can move either left or right. The king will move until either it reaches another piece (killing that piece and taking it’s place), or an end of the board.
This function should move the king at the provided position in the correct direction. You should use a for-loop or while-loop to iterate through the elements in the list and determine the spot it should end up at.
Test cases:
```{python}
#| eval: false
board = create_board()
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
move_king(board, 0, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
move_king(board, 8, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKi | |
+-----------------------------------------------------+
```
## Move a knight
This function has the same three parameters as the `move_king` function. `move_knight` should actually move a knight on the board (thus, it should change the board list). In 110 1d Chess, a knight can move either left or right. A knight moves 2 locations. If it lands on a space that another piece occupies, then it kills that piece. It can jump over other pieces. If it cannot move due to the ending position of the move being out-of-bounds of the board, the knight should stay in its place. Note the biggest differences between a knight and a king here are:
- a knight moves 2 locations each time
- it only moves once if it moves (the king may move multiple times and stop).
This function should move the knight at the provided position in the correct direction.
Test cases:
```{python}
#| eval: false
board = create_board()
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
move_knight(board, 6, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | BKn | | | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
move_knight(board, 2, "RIGHT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | | | WKn | | | BKn | BKi |
+-----------------------------------------------------+
```
## Make a move
Function name is `move` and it has three parameter variables. The board (a list, representing the 1 by 9 board), the position (index) of the player to move, and a direction (either `"LEFT"` or `"RIGHT"`). This function should determine if the piece to be moved is a king or a knight. If it is a king, call the `move_king` function. If a knight, call `move_knight.`
Test case:
```{python}
#| eval: false
board = create_board()
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
move(board, 0, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
move(board, 8, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKi | |
+-----------------------------------------------------+
```
## Game over
This function should be named `is_game_over` and it takes the board list as its only parameter, and should determine if the game is over or not. If the white king does not exist on the board, then the game is over, and black wins. In this case, the function should print `Black wins!` and return `True`. If the black king does not exist on the board, then the game is over, and white wins. In this case, the function should print `White wins!` and return `True`. If both kings are still in the board list, then the function should print nothing, and return `False`. Note you should print `Black wins!` or `White wins!` without adding a new line to the end of string.
Test case:
```{python}
#| eval: false
board = create_board()
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | WKn | | | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 2, "RIGHT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | | | WKn | | BKn | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 6, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | WKn | | | BKn | | | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 1, "RIGHT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | | | WKn | BKn | | | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 4, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| WKi | | BKn | WKn | | | | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 0, "RIGHT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| | | WKi | WKn | | | | BKn | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 7, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| | | WKi | WKn | | BKn | | | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 3, "RIGHT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| | | WKi | | | WKn | | | BKi |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 8, "LEFT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| | | WKi | | | BKi | | | |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == False
move(board, 2, "RIGHT")
print( printable_board(board) )
```
```{html}
+-----------------------------------------------------+
| | | | | | WKi | | | |
+-----------------------------------------------------+
```
```{python}
#| eval: false
assert is_game_over(board) == True
```
```{html}
White wins!
```