@ADoctor/

Pre-release AS 2019 (Commented)

Python

Original name: WrithingPleasantApache

fork
loading
Files
  • main.py
  • game1.txt
  • game2.txt
  • game3.txt
  • game4.txt
main.py
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
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
# Skeleton Program for the AQA A1 Summer 2019 examination
# this code should be used in conjunction with the Preliminary Material
# written by the AQA AS1 Programmer Team
# developed in a Python 3 environment

# Version number: 0.1.3


SPACE = '     '
UNUSED = 'XXXXX'

BOARD_SIZE = 8
NUMBER_OF_PIECES = 12
MAX_MOVES = 50
ROW = 0
COLUMN = 1
DAME = 2

#The class for each move, 50 will be created and put into a list ultimately
#Then when there are 'valid moves/valid jumps' the values of each instance that is valid
#will be updated. 

class MoveRecord:
  def __init__(self):
    self.Piece = ''
    self.NewRow = -1
    self.NewColumn = -1
    self.CanJump = False

#reads in the text file for a game
def LoadPieces(FileHandle, PlayersPieces):   
  for Index in range(NUMBER_OF_PIECES + 1):
    PlayersPieces[Index][ROW] = int(FileHandle.readline())
    PlayersPieces[Index][COLUMN] = int(FileHandle.readline())
    PlayersPieces[Index][DAME] = int(FileHandle.readline())
    print('PlayersPieces from Loadpieces looks like this', PlayersPieces)
  return PlayersPieces

#makes the chequered pattern board
def CreateNewBoard(Board): 
  for ThisRow in range(BOARD_SIZE):
    for ThisColumn in range(BOARD_SIZE):
      if (ThisRow + ThisColumn) % 2 == 0:
        Board[ThisRow][ThisColumn] = UNUSED
      else:
        Board[ThisRow][ThisColumn] = SPACE
  return Board

#passes the board and A which is a 2d list, row is 0, column is 1

def AddPlayerA(Board, A):
  for Index in range(1, NUMBER_OF_PIECES + 1):
    PieceRow = A[Index][ROW]
    PieceColumn = A[Index][COLUMN]
    PieceDame = A[Index][DAME]
    if PieceRow > -1:
      if PieceDame == 1:
        Board[PieceRow][PieceColumn] = 'A' + str(Index)
      else:
        Board[PieceRow][PieceColumn] = 'a' + str(Index)
  return Board
    
def AddPlayerB(Board, B):      
  for Index in range(1, NUMBER_OF_PIECES + 1):
    PieceRow = B[Index][ROW]
    PieceColumn = B[Index][COLUMN]
    PieceDame = B[Index][DAME]
    if PieceRow > -1:
      if PieceDame == 1:
        Board[PieceRow][PieceColumn] = 'B' + str(Index)
      else:
        Board[PieceRow][PieceColumn] = 'b' + str(Index)   
  return Board

def DisplayErrorCode(ErrorNumber):
  print('Error ', ErrorNumber)
  
def SetUpBoard(Board, A, B, FileFound):
  FileName = 'game1.txt'
  Answer = input('Do you want to load a saved game? (Y/N): ')
  if Answer == 'Y' or Answer == 'y':
    FileName = input('Enter the filename: ')
  try:
    FileHandle = open(FileName, 'r')
    FileFound = True
    A = LoadPieces(FileHandle, A)
    B = LoadPieces(FileHandle, B)
    FileHandle.close()
    Board = CreateNewBoard(Board)
    Board = AddPlayerA(Board, A)
    Board = AddPlayerB(Board, B)
  except:
    DisplayErrorCode(4)
  return Board, A, B, FileFound

#prints out the board heading
def PrintHeading():
  print('    ', end='')
  for BoardColumn in range(BOARD_SIZE):
    print('{0:3}'.format(BoardColumn), end='   ')
  print()

#prints out each row of the board
  
def PrintRow(Board, ThisRow):
  print('   |', end='')
  for BoardColumn in range(BOARD_SIZE):
    if Board[ThisRow][BoardColumn] == UNUSED:
      print(Board[ThisRow][BoardColumn], end='|')
    else:
      print(SPACE, end='|')
  print()

#prints the middle row of the board

def PrintMiddleRow(Board, ThisRow):    
  print('{0:>2}'.format(ThisRow), end=' |')
  for BoardColumn in range(BOARD_SIZE):
    if Board[ThisRow][BoardColumn] == UNUSED or Board[ThisRow][BoardColumn] == SPACE:
      print(Board[ThisRow][BoardColumn], end='|')
    else:
     print('{0:>4}'.format(Board[ThisRow][BoardColumn]), end=' |')
  print()

#prints out the dotted lines       
def PrintLine():  
  print('   ', end='')
  for BoardColumn in range(BOARD_SIZE):
    print('------', end='')
  print('-')

#combines the above functions to actually create the board
def DisplayBoard(Board):
  PrintHeading()
  PrintLine()
  for ThisRow in range(BOARD_SIZE):
    PrintRow(Board, ThisRow)
    PrintMiddleRow(Board, ThisRow)
    PrintRow(Board, ThisRow)
    PrintLine()
    
#prints the different parts of the board - when game being read from text file
def PrintPlayerPieces(A, B):
  print()
  print('Player A:')
  print(A)
  print('Player B:')
  print(B)
  print()

#clears the move list after each turn, ready to be populated next go
  
def ClearList(ListOfMoves):
  for Index in range(MAX_MOVES):
    ListOfMoves[Index].Piece = ''
    ListOfMoves[Index].NewRow = -1
    ListOfMoves[Index].NewColumn = -1
    ListOfMoves[Index].CanJump = False
  return ListOfMoves

#test for a valid move i.e. if the board space is empty

def ValidMove(Board, NewRow, NewColumn):
  Valid = False
  if NewRow in range(BOARD_SIZE) and NewColumn in range(BOARD_SIZE):  
    if Board[NewRow][NewColumn] == SPACE: 
      Valid = True        
  return Valid

#test for a valid jump 

def ValidJump(Board, PlayersPieces, Piece, NewRow, NewColumn):
  Valid = False
  MiddlePiece = ''
  Player = Piece[0].lower()
  Index = int(Piece[1:])
  if Player == 'a':
    OppositePiecePlayer = 'b'
  else:
    OppositePiecePlayer = 'a'
  if NewRow in range(BOARD_SIZE) and NewColumn in range(BOARD_SIZE):  
    if Board[NewRow][NewColumn] == SPACE: 
      CurrentRow = PlayersPieces[Index][ROW]
      CurrentColumn = PlayersPieces[Index][COLUMN]
      MiddlePieceRow = (CurrentRow + NewRow) // 2
      MiddlePieceColumn = (CurrentColumn + NewColumn) // 2
      MiddlePiece = Board[MiddlePieceRow][MiddlePieceColumn]
      MiddlePiecePlayer = MiddlePiece[0].lower()
      if MiddlePiecePlayer != OppositePiecePlayer and MiddlePiecePlayer != ' ':
        Valid = True       
  return Valid

#creates the possible moves

def ListPossibleMoves(Board, PlayersPieces, NextPlayer, ListOfMoves):

  #ListOfMoves is just a list with 50 different instances of the class move
  #record
                      
  #up the board or down the board
  if NextPlayer == 'a':
    Direction = 1
  else:
    Direction = -1
  NumberOfMoves = 0
  #for 1 to 12 as each player has 12 pieces                    
  for i in range(1, NUMBER_OF_PIECES + 1):
    #each piece has a name i.e. a1, a2, a3, a4
    Piece = NextPlayer + str(i)
    #on the first look Piece is a1
    #this value would be playerspieces [1][0]
                      
    CurrentRow = PlayersPieces[i][ROW]
    #this vlaue would be [1][1] in first loop
    CurrentColumn = PlayersPieces[i][COLUMN]

    #this piece of code checks to see if PlayerPieces[1][2] is 1
    #if it is then the piece is changed to upper case
                      
    if PlayersPieces[i][DAME] == 1:
      Piece = Piece.upper()

    #a newRow value is ascertained with current row and whichever direction we
    #are going in dependant on being player a or b
    #columns direction doesnt change for either player, so left -1 and right +1
    NewRow = CurrentRow + Direction  
    LeftColumn = CurrentColumn - 1
    RightColumn = CurrentColumn + 1
    #uses the valid move function and if it returns true do print out the move
    if ValidMove(Board, NewRow, LeftColumn):
      print(Piece, ' can move to ', NewRow, ' , ', LeftColumn)
      #increase the number of moves by 1 each time this is true and prints out
      NumberOfMoves += 1

      #in the list of moves[1].piece this is the value of piece
      #in the list of moves[1].NewRow this is the value of the new row
      #newcolumn is set to value of left column
      #for this move we havent ascertained yet whether we can jump so set to false
      ListOfMoves[NumberOfMoves].Piece = Piece
      ListOfMoves[NumberOfMoves].NewRow = NewRow
      ListOfMoves[NumberOfMoves].NewColumn = LeftColumn
      ListOfMoves[NumberOfMoves].CanJump = False

    #Do the same process to see if there are any valid moves to the right
    #uses valid move to check for a valid move
    if ValidMove(Board, NewRow, RightColumn):
      #if this is a valid move then it will print it out
      print(Piece, ' can move to ', NewRow, ' , ', RightColumn)
      #we increase the number of moves variable
      NumberOfMoves += 1
        
      ListOfMoves[NumberOfMoves].Piece = Piece
      ListOfMoves[NumberOfMoves].NewRow = NewRow
      ListOfMoves[NumberOfMoves].NewColumn = RightColumn
      ListOfMoves[NumberOfMoves].CanJump = False


     #now testing if we can jump
    #again row has to use a variable as it will differ for player A or B
    JumpRow = CurrentRow + Direction + Direction
    JumpLeftColumn = CurrentColumn - 2
    JumpRightColumn = CurrentColumn + 2

    
    if ValidJump(Board, PlayersPieces, Piece, JumpRow, JumpLeftColumn):
      print(Piece, ' can jump to ', JumpRow, ' , ', JumpLeftColumn)
      NumberOfMoves += 1
      ListOfMoves[NumberOfMoves].Piece = Piece
      ListOfMoves[NumberOfMoves].NewRow = JumpRow
      ListOfMoves[NumberOfMoves].NewColumn = JumpLeftColumn
      ListOfMoves[NumberOfMoves].CanJump = True 
    if ValidJump(Board, PlayersPieces, Piece, JumpRow, JumpRightColumn):
      print(Piece, ' can jump to ', JumpRow, ' , ', JumpRightColumn)    
      NumberOfMoves += 1
      ListOfMoves[NumberOfMoves].Piece = Piece
      ListOfMoves[NumberOfMoves].NewRow = JumpRow
      ListOfMoves[NumberOfMoves].NewColumn = JumpRightColumn
      ListOfMoves[NumberOfMoves].CanJump = True 
  print('There are ', NumberOfMoves, ' possible moves')

  #effectively we are returning the whole list of instances but several of those
  #elements will now have values in them (the valid moves)
                      
  return ListOfMoves

def ListEmpty(ListOfMoves):
  if ListOfMoves[1].Piece == '':
    return True
  else:
    return False


#in this function we ask the player to select which piece theyd like to move
#we check for a few things 1. that the list of moves is not empty. 2. Whether t
#piece they've selected exists in our list, it will check the .Piece attribute
#the 'error 1' code is when player has selected a piece that does exist in the
#allowed moves list                      
                      
def SelectMove(ListOfMoves):
  ValidPiece = False
  while not ValidPiece:
    Found = False
    EndOfList = False
    Piece = input('Which piece do you want to move? ')
    Index = 0
    if Piece == '':
      EndOfList = True

    #loop through all of the pieces incrementing the index by 1 to try to find the
    #correct piece
    while not Found and not EndOfList:
      Index += 1
      if ListOfMoves[Index].Piece == Piece:
        Found = True
      elif ListOfMoves[Index].Piece == '':
        EndOfList = True
        DisplayErrorCode(1) 
    if Found:
        ValidPiece = True

  #do this if the piece has been chosen correctly and the index will be its position
  #in the array
  ChosenPieceIndex = Index
  ValidMove = False
  while not ValidMove:
    #ask this first
    RowString = input('Which row do you want to move to? ')
    ColumnString = input('Which column do you want to move to? ')
    #then try 
    try:
      NewRow = int(RowString)
      NewColumn = int(ColumnString)
      Found = False
      EndOfList = False 
      Index = ChosenPieceIndex - 1
      while not Found and not EndOfList:
        Index += 1
        if ListOfMoves[Index].Piece != Piece:
          EndOfList = True
          DisplayErrorCode(2)  
        elif ListOfMoves[Index].NewRow == NewRow and ListOfMoves[Index].NewColumn == NewColumn:
          Found = True
      ValidMove = Found
    except:
      DisplayErrorCode(3)  
  return Index



def MoveDame(Board, Player, NewRow, NewColumn):
  if Player == 'a':
    for i in [1, 3, 5, 7]:
      if Board[0][i] == SPACE: 
        NewColumn = i
        NewRow = 0
        break   
  else:
    for i in [0, 2, 4, 6]:
      if Board[BOARD_SIZE - 1][i] == SPACE: 
        NewColumn = i
        NewRow = BOARD_SIZE - 1
        break   
  return NewRow, NewColumn

#moves the piece to the new place
  
def MovePiece(Board, PlayersPieces, ChosenPiece, NewRow, NewColumn):
  Index = int(ChosenPiece[1:])
  CurrentRow = PlayersPieces[Index][ROW]
  CurrentColumn = PlayersPieces[Index][COLUMN]
  Board[CurrentRow][CurrentColumn] = SPACE
  
  if NewRow == BOARD_SIZE - 1 and PlayersPieces[Index][DAME] == 0:
    Player = 'a'
    PlayersPieces[0][1] += 1
    PlayersPieces[Index][DAME] = 1
    ChosenPiece = ChosenPiece.upper()
    NewRow, NewColumn = MoveDame(Board, Player, NewRow, NewColumn) 
  elif NewRow == 0 and PlayersPieces[Index][DAME] == 0:
    Player = 'b'
    PlayersPieces[0][1] += 1
    PlayersPieces[Index][DAME] = 1
    ChosenPiece = ChosenPiece.upper()
    NewRow, NewColumn = MoveDame(Board, Player, NewRow, NewColumn) 
  PlayersPieces[Index][ROW] = NewRow
  PlayersPieces[Index][COLUMN] = NewColumn
  Board[NewRow][NewColumn] = ChosenPiece  
  return Board, PlayersPieces



def MakeMove(Board, PlayersPieces, OpponentsPieces, ListOfMoves, PieceIndex):
  PlayersPieces[0][0] += 1
  if PieceIndex > 0:
    Piece = ListOfMoves[PieceIndex].Piece
    NewRow = ListOfMoves[PieceIndex].NewRow
    NewColumn = ListOfMoves[PieceIndex].NewColumn
    PlayersPieceIndex = int(Piece[1:])
    CurrentRow = PlayersPieces[PlayersPieceIndex][ROW]
    CurrentColumn = PlayersPieces[PlayersPieceIndex][COLUMN]
    Jumping = ListOfMoves[PieceIndex].CanJump
    Board, PlayersPieces = MovePiece(Board, PlayersPieces, Piece, NewRow, NewColumn)
    if Jumping:
      MiddlePieceRow = (CurrentRow + NewRow) // 2
      MiddlePieceColumn = (CurrentColumn + NewColumn) // 2
      MiddlePiece = Board[MiddlePieceRow][MiddlePieceColumn]
      print('jumped over ', MiddlePiece)
  return Board, PlayersPieces, OpponentsPieces

def SwapPlayer(NextPlayer):
  if NextPlayer == 'a':
    return 'b'
  else:
    return 'a'

def PrintResult(A, B, NextPlayer):
  print('Game ended')
  print(NextPlayer, ' lost this game as they cannot make a move')
  PrintPlayerPieces(A, B)
  
def Game():

  #creates 2 lists which effectively creates an empty 2d array for the board
  A = [[0, 0, 0] for Piece in range(NUMBER_OF_PIECES + 1)]
  B = [[0, 0, 0] for Piece in range(NUMBER_OF_PIECES + 1)]
  Board = [['' for Column in range(BOARD_SIZE)] for Row in range(BOARD_SIZE)]
  
  #creates 50 instances of the class moverecord and stores them in a list. 
  ListOfMoves = [MoveRecord() for Move in range(MAX_MOVES)]
  GameEnd = False
  FileFound = False
  NextPlayer = 'a'
  Board, A, B,  FileFound = SetUpBoard(Board, A, B, FileFound)
  
  if not FileFound:
    GameEnd = True
  while not GameEnd:
    PrintPlayerPieces(A, B)
    
    DisplayBoard(Board)
    
    print('Next Player: ', NextPlayer)

    #passes the list of moves to the function clear list which clears the list
    #of moves
    ListOfMoves = ClearList(ListOfMoves)
    if NextPlayer == 'a':
      #recreates the list of moves using the list of possible moves function
      ListOfMoves = ListPossibleMoves(Board, A, NextPlayer, ListOfMoves)
      #checks to see if the list of moves is empty i.e. player can't move anywhere
      if not ListEmpty(ListOfMoves):
        
        PieceIndex = SelectMove(ListOfMoves)
        Board, A, B = MakeMove(Board, A, B, ListOfMoves, PieceIndex)
        NextPlayer = SwapPlayer(NextPlayer)
      else:
        GameEnd = True
    else:
      ListOfMoves = ListPossibleMoves(Board, B, NextPlayer, ListOfMoves)
      if not ListEmpty(ListOfMoves):
        PieceIndex = SelectMove(ListOfMoves)
        Board, B, A = MakeMove(Board, B, A, ListOfMoves, PieceIndex)
        NextPlayer = SwapPlayer(NextPlayer)
      else:
        GameEnd = True
  if FileFound:
    PrintResult(A, B , NextPlayer)
      
if __name__ == "__main__":
  Game()