-
Notifications
You must be signed in to change notification settings - Fork 1
/
battleship_OOP.py
832 lines (729 loc) · 29.3 KB
/
battleship_OOP.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
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
import os
import random
import sys
import collections
# This doesn't work on cloud9 but works locally
output_to_text = False
if output_to_text:
orig_stdout = sys.stdout
f = file('out.txt', 'w')
sys.stdout = f
board = []
user_board = []
row_label = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
col_label = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
ship_letters = ["A", "B", "C", "S", "D"]
"""
This is the nested dictionary where we store all the data on each ship. Here
we will store name, size, if the ship is placed, how many hits it has, and
if it is sunk. As a ship gets hit, we will increment 'hits' and check if
'hits' == 'size'. When that is true, we set 'is_sunk' to True.
"""
class Ship(object):
def __init__(self, ship_letter):
pass
class Carrier(Ship):
size = 5
def __init__(self):
self.ship_letter = "A"
self.name = "Aircraft Carrier"
self.hits = 0
self.is_placed = False
self.is_sunk = False
class Battleship(Ship):
size = 4
def __init__(self):
self.ship_letter = "B"
self.name = "Battleship"
self.hits = 0
self.is_placed = False
self.is_sunk = False
class Cruiser(Ship):
size = 3
def __init__(self):
self.ship_letter = "C"
self.name = "Cruiser"
self.hits = 0
self.is_placed = False
self.is_sunk = False
class Submarine(Ship):
size = 3
def __init__(self):
self.ship_letter = "S"
self.name = "Submarine"
self.hits = 0
self.is_placed = False
self.is_sunk = False
class Destroyer(Ship):
size = 2
def __init__(self):
self.ship_letter = "D"
self.name = "Destroyer"
self.hits = 0
self.is_placed = False
self.is_sunk = False
ship_info = {}
statistics = {
'hits': 0,
'misses': 0,
'total_guesses' : 0,
'prev_guess' : "",
'hit_streak' : 0,
'biggest_hit_streak' : 0,
'miss_streak' : 0,
'biggest_miss_streak' : 0,
'ships_destroyed': 0,
'times_cheated' : 0
}
ai_targetting = {
"last_hit_coord": "",
"ship": "",
"left": True,
"right": True,
"up": True,
"down": True,
"guess_dir": "",
"aim_radius": 1,
"dir_count": 0,
}
for x in range(10):
board.append(["-"] * 10)
user_board.append(["-"] * 10)
def print_board(board):
x = 0
print " " + " ".join(col_label)
for row in board:
print row_label[x] + " " + " ".join(row)
x += 1
print ""
def print_statistics(mode):
percentage = (float(statistics['hits']) / statistics['total_guesses']) * 100
print "\nGame Statistics:"
print "Hits: " + str(statistics['hits'])
print "Misses: " + str(statistics['misses'])
print "Total Guesses: " + str(statistics['total_guesses'])
print "Percentage Hit: " + str(round(percentage, 2)) + "%"
print "Biggest Hit Streak: " + str(statistics['biggest_hit_streak'])
print "Biggest Miss Streak: " + str(statistics['biggest_miss_streak'])
print "Ships Destroyed: " + str(statistics['ships_destroyed'])
if mode == "D" or mode == "C":
print "Times Cheated: " + str(statistics['times_cheated'])
def get_ship_size(ship_letter):
if ship_letter == "A":
return Carrier.size
elif ship_letter == "B":
return Battleship.size
elif ship_letter == "C":
return Cruiser.size
elif ship_letter == "S":
return Submarine.size
elif ship_letter == "D":
return Destroyer.size
else:
print "Invalid Ship Letter Provided"
raise ValueError
def get_ship_orientation():
# Gets ship orientation input
while True:
print "\nShip orientation options:\
\nH for Horizontal\
\nV for Vertical\
\nG to see Game Board\n"
orientation = (raw_input("Please choose orientation of the ship: ")).upper()
if orientation == "G":
print_board(board)
continue
elif orientation == "H":
print "Horizontal ship orientation selected"
return orientation
elif orientation == "V":
print "Vertical ship orientation selected"
return orientation
else:
print "\nPlease choose H or V"
continue
def get_ship_coordinate(orientation):
# Gets ship coordinate as input
while True:
print "\nEnter a coordinate for row A-J and column 1-10:\
\nExample: 'A4'\
\nEnter 'G' to see Game Board\n"
if orientation == "H":
coordinate = (raw_input("\nEnter the left-most coordinate of the ship: ")).upper()
elif orientation == "V":
coordinate = (raw_input("\nEnter coordinate for the top of the ship: ")).upper()
if orientation == "G":
print_board(board)
continue
else:
row, col = coordinate[0], coordinate[1:]
# Check if row and column are in our row and column label list
if row in row_label and col in col_label:
print "Coordinate " + coordinate + " selected.\n"
return coordinate
else:
print "Coordinate invalid. Try again.\n"
continue
def check_boundaries(ship_letter, orientation, coordinate):
# Make sure the ship fits in boundries of game board
# Split coordinate in to row and column data
row, col = coordinate[0], coordinate[1:]
# Match the coordinate info with row and column index in grid
row_index = row_label.index(row)
col_index = col_label.index(col)
# Make sure the ship size + row/column index don't exceed gameboard length
if orientation == "H":
if col_index + get_ship_size(ship_letter) > len(col_label):
return False
return True
elif orientation == "V":
if row_index + get_ship_size(ship_letter) > len(row_label):
return False
return True
return None # error case
def space_available(ship_letter, orientation, coordinate):
# Split coordinate in to row and column data
row, col = coordinate[0], coordinate[1:]
# Match the coordinate info with row and column index in grid
row_index = row_label.index(row)
col_index = col_label.index(col)
# Check if all the spaces you are trying to place in are still empty "-"s
if orientation == "H":
for x in range(get_ship_size(ship_letter)):
if board[row_index][col_index + x] != "-":
return False
return True
elif orientation == "V":
for x in range(get_ship_size(ship_letter)):
if board[row_index + x][col_index] != "-":
return False
return True
return None # error case
def place_ship(ship_letter, orientation, coordinate):
# Place ship letter on game board
# Split coordinate in to row and column data
row, col = coordinate[0], coordinate[1:]
# Match the coordinate info with row and column index in grid
row_index = row_label.index(row)
col_index = col_label.index(col)
# Replace each "-" with the ship letter provided
if orientation == "H":
for x in range(get_ship_size(ship_letter)):
board[row_index][col_index + x] = ship_letter
elif orientation == "V":
for x in range(get_ship_size(ship_letter)):
board[row_index + x][col_index] = ship_letter
def get_rand_orientation():
orientation = random.choice( ['H', 'V'] )
return orientation
def get_rand_ship():
while True:
ship_letter = random.choice( ['A', 'B', 'C', 'S', 'D'] )
if ship_letter not in ship_info.keys():
return ship_letter
else:
continue
def get_rand_coord():
# THis will be used to get random coordinates
row_coord = chr(random.randrange(97,107)).upper()
col_coord = str(random.randint(1,10))
return row_coord + col_coord
def reset_aim():
# This resets the aim after the last hit has been exhausted
ai_targetting['last_hit_coord'] = ""
ai_targetting['ship'] = ""
ai_targetting['left'] = True
ai_targetting['right'] = True
ai_targetting['up'] = True
ai_targetting['down'] = True
ai_targetting['guess_dir'] = ""
ai_targetting['dir_count'] = 0
ai_targetting['aim_radius'] = 1
def check_aim():
# Check to see if there are still directions that haven't been misses
if ai_targetting['left'] or ai_targetting['right'] or ai_targetting['up'] or ai_targetting['down']:
return True
return False
def check_edge_case(row_index, col_index):
# This checks for an error where it tries to guess out of bounds
if ((ai_targetting['guess_dir'] == 'left' and col_index == 0) or
(ai_targetting['guess_dir'] == 'right' and col_index == (len(col_label) - 1)) or
(ai_targetting['guess_dir'] == 'up' and row_index == 0) or
(ai_targetting['guess_dir'] == 'down' and row_index == (len(row_label) - 1))):
return True
else:
return False
def ai_aimed_coord(direction):
"""
If we have a hit, the AI starts on that coordinate and exhausts all outward directions
until miss or out of bounds. This code receives the direction and the radius
and checks to see if the next target is in the boundary. If it is not, it stops looking
in that direction
"""
row, col = ai_targetting['last_hit_coord'][0], ai_targetting['last_hit_coord'][1:]
row_index = row_label.index(row)
col_index = col_label.index(col)
in_bounds = False
if ai_targetting[direction] == True:
ai_targetting['guess_dir'] = direction
if direction == 'up':
row_aimed = row_index - ai_targetting['aim_radius']
if row_aimed < len(row_label):
in_bounds = True
coordinate = row_label[row_aimed] + col_label[col_index]
else:
ai_targetting[direction] = False
elif direction == 'down':
row_aimed = row_index + ai_targetting['aim_radius']
if row_aimed < len(row_label):
in_bounds = True
coordinate = row_label[row_aimed] + col_label[col_index]
else:
ai_targetting[direction] = False
elif direction == 'right':
col_aimed = col_index + ai_targetting['aim_radius']
if col_aimed < len(col_label):
in_bounds = True
coordinate = row_label[row_index] + col_label[col_aimed]
else:
ai_targetting[direction] = False
elif direction == 'left':
col_aimed = col_index - ai_targetting['aim_radius']
if col_aimed < len(col_label):
in_bounds = True
coordinate = row_label[row_index] + col_label[col_aimed]
else:
ai_targetting[direction] = False
if in_bounds:
return coordinate
def ai_get_coord():
"""
If there is a hit, uses AI targetting for next coordinate. Otherwise, generate random coordinate
This AI takes the coordinate of the first hit, and goes outward in each direction one at a time until
it encounters a miss in that direction. It keeps going until all directions hit miss or boundary.
"""
aim_tries = 0
directions = ['left', 'right', 'up', 'down']
while True:
# If there was a hit and not all directions have been exhausted( encounted a miss)
if ai_targetting['last_hit_coord'] != "" and check_aim():
coordinate = ai_aimed_coord(directions[ai_targetting['dir_count']])
if ai_targetting['dir_count'] < 3:
ai_targetting['dir_count'] += 1
else:
ai_targetting['dir_count'] = 0
ai_targetting['aim_radius'] += 1
if not coordinate:
continue
else:
reset_aim()
coordinate = get_rand_coord()
row, col = coordinate[0], coordinate[1:]
row_index = row_label.index(row)
col_index = col_label.index(col)
# If the coordinate is good, return it to program
if board[row_index][col_index] != "*" and board[row_index][col_index] != "X":
return coordinate
# If the target is a miss, stop guessing in that direction
elif board[row_index][col_index] == "X":
ai_targetting[ai_targetting['guess_dir']] = False
# If the target is already hit and the target will be a boundary next, stop this direction
elif board[row_index][col_index] == "*" and check_edge_case(row_index, col_index):
ai_targetting[ai_targetting['guess_dir']] = False
else:
aim_tries += 1
def verify_response(coordinate, response):
# Check if user is cheating and gives wrong response
sunk = False
row, col = coordinate[0], coordinate[1:]
row_index = row_label.index(row)
col_index = col_label.index(col)
# Update hit counter for ship if it is a hit and check to see if sunk
if board[row_index][col_index] != "-":
hits = ship_info[board[row_index][col_index]].hits
size = ship_info[board[row_index][col_index]].size
if (hits + 1) == size:
sunk = True
if response == "H":
if board[row_index][col_index] != "-" and not sunk:
ship_info[board[row_index][col_index]].hits += 1
return True
return False
elif response == "M":
if board[row_index][col_index] == "-":
return True
return False
elif response == "S":
if board[row_index][col_index] != "-" and sunk:
ship_info[board[row_index][col_index]].hits += 1
ship_info[board[row_index][col_index]].is_sunk = True
return True
return False
else: # if it receives G or bad input
return True
def ai_attack(human_response=True):
# AI guesses coordinates and attacks ships that have been placed
coordinate = ai_get_coord()
row, col = coordinate[0], coordinate[1:]
row_index = row_label.index(row)
col_index = col_label.index(col)
print_board(board)
while True:
print "\nComputer: Attacking " + coordinate + "..."
print "\nHit, Miss, or Sunk?\
\nH for Hit\
\nM for Miss\
\nS for Sunk\
\nG to see Game Board\n"
if human_response:
response = (raw_input("Please choose one: ")).upper()
else:
# For AI vs AI mode
response = random.choice(['H', 'M', 'S'])
not_cheater = verify_response(coordinate, response)
if not not_cheater:
statistics['times_cheated'] += 1
print "\nSTOP CHEATING SCRUB!!!"
if response == "G":
print_board(board)
continue
# Update statistics and gameplay for a hit
elif response == "H":
if not_cheater:
print "\nComputer: YES!!!\n"
# For the first hit, store the coordinates of the hit for AI targetting
if ai_targetting['last_hit_coord'] == "":
ai_targetting['last_hit_coord'] = coordinate
board[row_index][col_index] = "*"
statistics['hits'] += 1
statistics['miss_streak'] = 0
statistics['total_guesses'] += 1
if statistics['prev_guess'] == "H" or statistics['prev_guess'] == "S":
statistics['hit_streak'] +=1
if statistics['hit_streak'] > statistics['biggest_hit_streak']:
statistics['biggest_hit_streak'] = statistics['hit_streak']
statistics['prev_guess'] = "H"
break
else:
continue
# Update statistics and gameplay for a miss
elif response == "M":
if not_cheater:
print "\nComputer: I missed? :( \n"
# For a miss, if AI targetting is on, stop looking in directions that are misses
if ai_targetting['last_hit_coord'] != "":
ai_targetting[ai_targetting['guess_dir']] = False
board[row_index][col_index] = "X"
statistics['misses'] += 1
statistics['total_guesses'] += 1
statistics['hit_streak'] = 0
if statistics['prev_guess'] == "M":
statistics['miss_streak'] +=1
if statistics['miss_streak'] > statistics['biggest_miss_streak']:
statistics['biggest_miss_streak'] = statistics['miss_streak']
statistics['prev_guess'] = "M"
break
else:
continue
# Update statistics and gameplay when ship is sunk
elif response == "S":
if not_cheater:
print ship_info[board[row_index][col_index]].name + " destroyed!"
print "\nComputer: KABOOM!\n"
board[row_index][col_index] = "*"
statistics['hits'] += 1
statistics['miss_streak'] = 0
statistics['total_guesses'] += 1
statistics['ships_destroyed'] += 1
if statistics['prev_guess'] == "H" or statistics['prev_guess'] == "S":
statistics['hit_streak'] +=1
if statistics['hit_streak'] > statistics['biggest_hit_streak']:
statistics['biggest_hit_streak'] = statistics['hit_streak']
statistics['prev_guess'] = "S"
break
else:
continue
else:
print "\nPlease enter valid input"
continue
def get_response(coordinate):
# Computer generates response to give user
sunk = False
row, col = coordinate[0], coordinate[1:]
row_index = row_label.index(row)
col_index = col_label.index(col)
# Update hit counter for ship if it is a hit and check to see if sunk
if board[row_index][col_index] != "-":
hits = ship_info[board[row_index][col_index]].hits
size = ship_info[board[row_index][col_index]].size
if (hits + 1) == size:
sunk = True
if board[row_index][col_index] != "-" and not sunk:
ship_info[board[row_index][col_index]].hits += 1
user_board[row_index][col_index] = "*"
return "H"
elif board[row_index][col_index] == "-":
user_board[row_index][col_index] = "X"
return "M"
elif board[row_index][col_index] != "-" and sunk:
ship_info[board[row_index][col_index]].hits += 1
ship_info[board[row_index][col_index]].is_sunk = True
user_board[row_index][col_index] = "*"
return "S"
else:
return "Logic error"
def human_attack():
"""
Similar to AI attack, human attack takes user input of a coordinate
and determines hit, miss, or sunk and outputs desired result. Updates
user gameboard to reflect this.
"""
while True:
print_board(user_board)
coordinate = (raw_input("Enter the coordinate you would like to attack (i.e. 'A1'): ")).upper()
row, col = coordinate[0], coordinate[1:]
if row in row_label and col in col_label:
row_index = row_label.index(row)
col_index = col_label.index(col)
if user_board[row_index][col_index] == "-":
response = get_response(coordinate)
if response == "H":
print "\nComputer: Hit. Lucky shot.\n"
statistics['hits'] += 1
statistics['miss_streak'] = 0
statistics['total_guesses'] += 1
if statistics['prev_guess'] == "H" or statistics['prev_guess'] == "S":
statistics['hit_streak'] +=1
if statistics['hit_streak'] > statistics['biggest_hit_streak']:
statistics['biggest_hit_streak'] = statistics['hit_streak']
statistics['prev_guess'] = "H"
break
# Update statistics and gameplay for a miss
elif response == "M":
print "\nComputer: HAH! YOU MISSED!! \n"
statistics['misses'] += 1
statistics['total_guesses'] += 1
statistics['hit_streak'] = 0
if statistics['prev_guess'] == "M":
statistics['miss_streak'] +=1
if statistics['miss_streak'] > statistics['biggest_miss_streak']:
statistics['biggest_miss_streak'] = statistics['miss_streak']
statistics['prev_guess'] = "M"
break
# Update statistics and gameplay when ship is sunk
elif response == "S":
print ship_info[board[row_index][col_index]].name + " destroyed!"
print "Computer: You got that one, but you won't get the rest!!\n"
statistics['hits'] += 1
statistics['miss_streak'] = 0
statistics['total_guesses'] += 1
statistics['ships_destroyed'] += 1
if statistics['prev_guess'] == "H" or statistics['prev_guess'] == "S":
statistics['hit_streak'] +=1
if statistics['hit_streak'] > statistics['biggest_hit_streak']:
statistics['biggest_hit_streak'] = statistics['hit_streak']
statistics['prev_guess'] = "S"
break
else:
print "Response returned bad data"
else:
print "You already guessed there! Try somewhere else.\n"
else:
print "Please enter a valid coordinate.\n"
def create_ship(ship_letter):
if ship_letter == "A":
ship_info[ship_letter] = Carrier()
elif ship_letter == "B":
ship_info[ship_letter] = Battleship()
elif ship_letter == "C":
ship_info[ship_letter] = Cruiser()
elif ship_letter == "S":
ship_info[ship_letter] = Submarine()
elif ship_letter == "D":
ship_info[ship_letter] = Destroyer()
else:
print "Invalid Ship Letter Provided"
raise ValueError
ship_info[ship_letter].is_placed = True
def defend_placement():
'''
If they enter a ship, we get the orientation and coordinate, then
check and make sure it is in the boundary and there is space for
the ship. If so, place the boat and and update ship count and
is_placed for that ship to reflect boat placement.
This is pulling ship_info data from a nested dictionary I made at the
top so that we could make the code cleaner (it was really bad w/o it)
'''
ship_count = 0
# Loop until all 5 ships are placed
while ship_count < 5:
print "Please place one of each ship.\
\nA to place Aircraft Carrier (Size: 5)\
\nB to place Battleship (Size: 4)\
\nC to place Cruiser (Size: 3)\
\nS to place Submarine (Size: 3)\
\nD to place Destroyer (Size: 2)\
\nG to see Game Board\n"
ship_letter = (raw_input("Please enter ship type: ")).upper()
# Print game board if they want it
if ship_letter == "G":
print_board(board)
continue
elif ship_letter in ship_letters:
if ship_letter not in ship_info:
while ship_letter not in ship_info:
orientation = get_ship_orientation()
coordinate = get_ship_coordinate(orientation)
boundary_check = check_boundaries(ship_letter, orientation, coordinate)
if boundary_check:
space_check = space_available(ship_letter, orientation, coordinate)
if space_check == False:
print "There is already another ship there!\n"
else:
print "Ship out of bounds.\n"
if boundary_check and space_check:
print "Location Valid. Placing ship.\n"
place_ship(ship_letter, orientation, coordinate)
ship_count += 1
create_ship(ship_letter)
print "Ship placed!\n"
print_board(board)
else:
print "Location Invalid. Try again.\n"
continue
else:
print ship_info[ship_letter].name + " already placed! Try another.\n"
else:
print "Please choose valid ship option\n"
continue
else:
print "All ships placed correctly! Congratulations!\n"
def attack_placement():
'''
The computer will randomly place ships on the board. The user will then enter coordinates
and attempt to sink all the ships. Once the ships have all be sunk the game will end.
'''
ship_count = 0
# Loop until all 5 ships are placed
while ship_count < 5:
ship_letter = get_rand_ship()
if ship_letter not in ship_info:
while ship_letter not in ship_info:
orientation = get_rand_orientation()
coordinate = get_rand_coord()
boundary_check = check_boundaries(ship_letter, orientation, coordinate)
if boundary_check:
space_check = space_available(ship_letter, orientation, coordinate)
if boundary_check and space_check:
place_ship(ship_letter, orientation, coordinate)
ship_count += 1
create_ship(ship_letter)
else:
print "Computer: My ships are in position. Bring it on!\n"
class Game(object):
'''
This is the main Game class that calls all the methods needed to execute the Battleship game.
'''
def __init__(self):
# perhaps we can store statistics here
# and/or the game board
pass
@classmethod
def defend(cls):
# Defend mode game
game_over = False
print "\nEntering defend mode...\n"
defend_placement()
print "Computer beginning its attack...\n"
while game_over == False:
ai_attack()
for ship in ship_info:
if ship_info[ship].is_sunk == False:
break
else:
print "Computer: GOT YOUR SHIPS, PITIFUL HUMAN!\n"
game_over = True
continue
else:
print "\nGame over!\n"
print ""
print_board(board)
print_statistics("D")
# sys.exit()
@classmethod
def attack(cls):
# Attack mode game
game_over = False
print "\nEntering attack mode...\n"
attack_placement()
# print_board(board)
# print_board(user_board)
while game_over == False:
human_attack()
for ship in ship_info:
if ship_info[ship].is_sunk == False:
break
else:
print "Computer: Well I'll be damned... you did it. Congratulations, human.\n"
game_over = True
continue
else:
print "\nGame over!\n"
print ""
print_board(user_board)
print_statistics("A")
@classmethod
def ai_mode(cls):
# AI places ships and AI attacks
# This mode is to look at statistics for AI performance
# and help debug if necessary
game_over = False
human_response = False
print "\nEntering AI mode...\n"
attack_placement()
print "Computer beginning its attack..."
while game_over == False:
ai_attack(human_response)
for ship in ship_info:
# print ship, ship_info[ship]['is_sunk']
if ship_info[ship].is_sunk == False:
break
else:
game_over = True
continue
else:
print "\nGame over!\n"
print ""
print_board(board)
print_statistics("C")
# sys.exit()
@classmethod
def start_game(cls):
# Main game method
while True:
print "\nWelcome to Battleship! Prepare to die.\n"
print "Please choose game mode.\
\nA for Attack Mode\
\nD for Defend Mode\
\nC for Computer Fight\
\nQ to Quit\n"
choice = (raw_input("Enter choice: ")).upper()
if choice.upper() == 'A':
cls.attack()
break
elif choice.upper() == 'D':
cls.defend()
break
elif choice.upper() == 'C':
cls.ai_mode()
break
elif choice.upper() == 'Q':
sys.exit()
else:
print "Invalid choice"
continue
battleship_game = Game()
battleship_game.start_game()
if output_to_text:
sys.stdout = orig_stdout
f.close()