This repository has been archived by the owner on Aug 26, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBSV3.pl
168 lines (145 loc) · 5.44 KB
/
BSV3.pl
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
/* for usage of substitute */
:- use_module(library(dialect/sicstus/lists)).
/* introduce dynamics */
:- dynamic openList/1.
:- dynamic enemyField/1.
/* ---------------------------------------------- */
/* get next coordinate to attack */
/* from open list */
getPointOfAttack(X, Y) :-
openList([X/Y | T]),
newOpenList(T).
/* if open list is empty, take random values */
getPointOfAttack(X, Y) :-
random(0, 10, X),
random(0, 10, Y).
/* ---------------------------------------------- */
/* helper predicate to set the open list */
newOpenList(NewOpenList) :-
retractall(openList(_)),
asserta(openList(NewOpenList)).
/* ---------------------------------------------- */
/* update the content of the open list */
/* water was hit - nothing to do */
updateOpenList(_, _, 1).
/* last ship destroyed - nothing to do */
updateOpenList(_, _, 4).
/* whole ship destroyed - clear open list and */
/* surround destroyed ship with water */
updateOpenList(X, Y, 3) :-
newOpenList([]),
surroundWithWater(X, Y, X, Y).
/* hit - put surrounding fields in open list and */
/* remove fields if direction of ship is known */
updateOpenList(X, Y, 2) :-
West is X - 1,
appendFreeFieldToList(West, Y),
East is X + 1,
appendFreeFieldToList(East, Y),
North is Y - 1,
appendFreeFieldToList(X, North),
South is Y + 1,
appendFreeFieldToList(X, South),
checkHitDirection(X, Y).
/* ---------------------------------------------- */
/* Neighbours to check for open list */
/* do not append if outside playing field */
appendFreeFieldToList(X, Y) :-
X < 0; X >= 10;
Y < 0; Y >= 10.
/* append if fieldstate is unknown */
appendFreeFieldToList(X, Y) :-
enemyField(Field),
openList(OpenList),
member(X/Y/0, Field),
append(OpenList, [X/Y], NewOpenList),
newOpenList(NewOpenList).
/* do not append other fields */
appendFreeFieldToList(_, _).
/* ---------------------------------------------- */
/* check if ship direction is known from earlier hit */
/* check for vertical ship */
checkHitDirection(X, Y) :-
YNorth is Y - 1,
YSouth is Y + 1,
enemyField(Field),
(member(X/YNorth/2, Field); member(X/YSouth/2, Field)),
ColLeft is X - 1,
ColRight is X + 1,
openList(OpenList),
delete(OpenList, ColLeft/_, OpenListNew),
delete(OpenListNew, ColRight/_, OpenListOut),
newOpenList(OpenListOut)
.
/* check for horizontal ship */
checkHitDirection(X, Y) :-
XWest is X - 1,
XEast is X + 1,
enemyField(Field),
(member(XWest/Y/2, Field); member(XEast/Y/2, Field)),
RowUp is Y - 1,
RowDown is Y + 1,
openList(OpenList),
delete(OpenList, _/RowUp, TempOpenList),
delete(TempOpenList, _/RowDown, NewOpenList),
newOpenList(NewOpenList)
.
/* default - true */
checkHitDirection(_, _).
/* ---------------------------------------------- */
/* surround known and sunk ship with water */
/* do not regard if outside of playing field */
surroundWithWater(X, Y, _, _) :-
X < 0; X >= 10;
Y < 0; Y >= 10.
/* if X, Y mark a hit, also check neighbours */
surroundWithWater(X, Y, OldX, OldY) :-
enemyField(EnemyField),
member(X/Y/2, EnemyField),
surroundEast(X, Y, OldX, OldY),
surroundWest(X, Y, OldX, OldY),
surroundNorth(X, Y, OldX, OldY),
surroundSouth(X, Y, OldX, OldY).
/* if X, Y mark an unknown field it becomes water */
surroundWithWater(X, Y, _, _) :-
enemyField(OldField),
member(X/Y/0, OldField),
substitute(X/Y/0, OldField, X/Y/1, NewField),
retractall(enemyField(_)),
asserta(enemyField(NewField)).
/* default - true */
surroundWithWater(_, _, _, _).
/* ---------------------------------------------- */
/* surround with water - recursion */
/* avoid endless loop with already checked values */
surroundEast(X, _, OldX, _) :-
NewX is X+1,
NewX =:= OldX.
/* check East Neighbour */
surroundEast(X, Y, _, OldY) :-
NewX is X+1,
surroundWithWater(NewX, Y, X, OldY).
/* avoid endless loop with already checked values */
surroundWest(X, _, OldX, _) :-
NewX is X-1,
NewX =:= OldX.
/* check West Neighbour */
surroundWest(X, Y, _, OldY) :-
NewX is X-1,
surroundWithWater(NewX, Y, X, OldY).
/* avoid endless loop with already checked values */
surroundNorth( _, Y, _, OldY) :-
NewY is Y-1,
NewY =:= OldY.
/* check North Neighbour */
surroundNorth( X, Y, OldX, _) :-
NewY is Y-1,
surroundWithWater(X, NewY, OldX, Y).
/* avoid endless loop with already checked values */
surroundSouth( _, Y, _, OldY) :-
NewY is Y+1,
NewY =:= OldY.
/* check South Neighbour */
surroundSouth( X, Y, OldX, _) :-
NewY is Y+1,
surroundWithWater(X, NewY, OldX, Y).