-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathai.py
138 lines (119 loc) · 5.5 KB
/
ai.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
import random
from sentence import Sentence
class MinesweeperAI:
def __init__(self, height, width):
self.height = height
self.width = width
self.moves_made = set()
self.mines = set()
self.safes = set()
self.knowledge = []
def mark_mine(self, cell):
self.mines.add(cell)
for sentence in self.knowledge:
sentence.mark_mine(cell)
def mark_safe(self, cell):
self.safes.add(cell)
for sentence in self.knowledge:
sentence.mark_safe(cell)
def add_knowledge(self, cell, count):
self.moves_made.add(cell)
self.mark_safe(cell)
# removing empty sentences
for sent in self.knowledge:
if len(sent.cells) == 0:
self.knowledge.remove(sent)
# removing safes and mines from knowledge
for sent in self.knowledge:
for safe in self.safes:
if safe in sent.cells.copy():
print(f'removing new safe {safe} from {sent.cells} = {sent.count}\n')
sent.cells.difference_update({safe})
for mine in self.mines:
if mine in sent.cells.copy():
print(f'removing new mine {mine} from {sent.cells} = {sent.count}\n')
sent.cells.difference_update({mine})
sent.count -= 1
# add a new sentence to the knowledge
neighbors = []
if cell[0] == 0:
if cell[1] == 0: # (0,0) corner
for n1 in range(0, 2):
for n2 in range(0, 2):
neighbors.append((cell[0] + n1, cell[1] + n2))
elif cell[1] == self.width - 1: # (0,7) corner
for n1 in range(0, 2):
for n2 in range(-1, 1):
neighbors.append((cell[0] + n1, cell[1] + n2))
else: # (0,j) row
for n1 in range(0, 2):
for n2 in range(-1, 2):
neighbors.append((cell[0] + n1, cell[1] + n2))
elif cell[0] == self.height - 1:
if cell[1] == 0: # (7,0) corner
for n1 in range(-1, 1):
for n2 in range(0, 2):
neighbors.append((cell[0] + n1, cell[1] + n2))
elif cell[1] == self.width - 1: # (7,7) corner
for n1 in range(-1, 1):
for n2 in range(-1, 1):
neighbors.append((cell[0] + n1, cell[1] + n2))
else: # (7,j) row
for n1 in range(-1, 1):
for n2 in range(-1, 2):
neighbors.append((cell[0] + n1, cell[1] + n2))
elif (cell[1] == 0) and (cell[0] > 0) and (cell[0] < self.width - 1): # (i,0) column
for n1 in range(-1, 2):
for n2 in range(0, 2):
neighbors.append((cell[0] + n1, cell[1] + n2))
elif (cell[1] == self.height - 1) and (cell[0] > 0) and (cell[0] < self.width - 1): # (i,7) column
for n1 in range(-1, 2):
for n2 in range(-1, 1):
neighbors.append((cell[0] + n1, cell[1] + n2))
else:
for n1 in range(-1, 2):
for n2 in range(-1, 2):
neighbors.append((cell[0] + n1, cell[1] + n2))
for neigh in neighbors:
if neigh in self.safes:
neighbors.remove(neigh)
elif neigh in self.mines:
if count > 0:
count -= 1
neighbors.remove(neigh)
self.knowledge.append(Sentence(neighbors, count))
print(f'adding knowledge: {self.knowledge[-1].cells}={self.knowledge[-1].count}')
for sent in self.knowledge:
aux = []
if sent.count == 0:
for newsafe in sent.cells.copy():
self.mark_safe(newsafe)
aux.append(newsafe)
self.knowledge.remove(sent)
elif sent.count == len(sent.cells):
aux = []
for newmine in sent.cells.copy():
self.mark_mine(newmine)
aux.append(newmine)
self.knowledge.remove(sent)
for sent in self.knowledge:
if len(sent.cells) == 0:
self.knowledge.remove(sent)
# add any new sentences from inference to the knowledge base
# {A,B,C,D,E} = 3 and {A,B,C} = 1 => {D,E} = 2
for sent0 in self.knowledge:
for sent1 in self.knowledge:
if sent0.cells < sent1.cells:
print(f'getting infered knowledge from {sent0.cells} = {sent0.count} and {sent1.cells} = {sent1.count}\n')
self.knowledge.append(Sentence(sent1.cells.difference(sent0.cells), sent1.count - sent0.count))
self.knowledge.remove(sent1)
print(f'infered knowledge added:{self.knowledge[-1].cells} = {self.knowledge[-1].count}. Removing {sent1.cells} = {sent1.count}')
def make_safe_move(self):
if len(self.safes) - len(self.moves_made) > 0:
return self.safes.difference(self.moves_made).pop()
def make_random_move(self):
if len(self.safes) - len(self.moves_made) < 1:
auxcell = (random.randint(0, self.width - 1), random.randint(0, self.height - 1))
while (auxcell not in self.moves_made.union(self.mines)) and (
len(self.safes) + len(self.mines) < (self.height - 1) * (self.width - 1)):
return auxcell