-
Notifications
You must be signed in to change notification settings - Fork 0
/
multiplayer.frg
165 lines (132 loc) · 5.09 KB
/
multiplayer.frg
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
#lang forge "curiosity modeling" "[email protected]"
abstract sig Boolean {}
one sig True, False extends Boolean {}
// whether we should have actual defined empty space that extends space
// he thinks that the adjacency checking isn't working
one sig Game {
initial1: one Player,
initial2: one Player,
// make both of these {next is linear}, don't use and just new line to separate them
next1: pfunc Player -> Player,
next2: pfunc Player -> Player
}
abstract sig Space {}
sig BoatSpot extends Space {
hit: one Boolean
}
sig MissedStrike extends Space {}
sig Boat {
spot1: one BoatSpot,
spot2: one BoatSpot
}
abstract sig Player {
board: pfunc Int -> Int -> Space,
// boat1: one Boat,
// boat2: one Boat,
// boat3: one Boat,
boats: set Boat,
// if we have performance difficulties, it's possible that there's overhead with keeping the boards synced -- seek advice!
my_turn: one Boolean,
has_won: one Boolean
}
one sig Player1, Player2 extends Player {}
// to decide whose turn it is, need to count MissedStrikes and hit BoatSpots
pred wellformed {
some Player1
some Player2
some Player1.board
some Player2.board
#{p: Player | p != Player1 and p!= Player2} = 0
#{boat: Boat | boat in Player1.boats} = 3
#{boat: Boat | boat in Player2.boats} = 3
#{Player1.boats & Player2.boats} = 0
// dimensions of each board
all row, col : Int | {
(row < 0 or col < 0 or row > 3 or col > 3) implies (no Player1.board[row][col] and no Player2.board[row][col])
}
all space: Space | {
// if a space object exists, it must be on a board
some player : Player | {
some row, col: Int | {
player.board[row][col] = space
}
}
// Can't have the same BoatSpot in multiple locations on one board or have the same BoatSpot on different boards
(no (Player1.board.space & Player2.board.space)) and one (Player1.board.space + Player2.board.space)
}
// each BoatSpot belongs to only 1 boat
all boat: Boat | {
// spot at spot1 can't be the same as spot at spot2
boat.spot1 != boat.spot2
// spot belonging to one boat can't belong to any other boat
all boat2: Boat | boat2 != boat implies {
boat.spot1 != boat2.spot1
boat.spot1 != boat2.spot2
boat.spot2 != boat2.spot2
boat.spot2 != boat2.spot1
}
// BoatSpots of this Boat are positioned vertically or horizontally -- no diagonal
some row, col: Int | {
Player1.board[row][col] = boat.spot1 implies (Player1.board[row][add[col,1]] = boat.spot2 or Player1.board[row][add[col,-1]] = boat.spot2 or Player1.board[add[row,1]][col] = boat.spot2 or Player1.board[add[row,-1]][col] = boat.spot2)
Player2.board[row][col] = boat.spot1 implies (Player2.board[row][add[col,1]] = boat.spot2 or Player2.board[row][add[col,-1]] = boat.spot2 or Player2.board[add[row,1]][col] = boat.spot2 or Player2.board[add[row,-1]][col] = boat.spot2)
}
}
}
pred initState {
// only boat spots that aren't hit, no strikes
no MissedStrike
all spot : BoatSpot | {
spot.hit = False
}
// no one has won
Player1.has_won = False
Player2.has_won = False
// it's exactly one player's turn
(Player1.my_turn = True and Player2.my_turn = False) or (Player1.my_turn = False and Player2.my_turn = True)
}
// This is true when p has lost the game
pred finalState[p: Player] {
// all boat spots on player's board are hit
all spot : BoatSpot | {
some row, col : Int | {p.board[row][col] = spot} implies {
spot.hit = True
}
}
}
// pred changeTurn {
// }
// checks that the selected row, col for the move is valid
pred validLocation[row: Int, col: Int, p: Player] {
// on board
(row >= 0 and col >= 0 and row <= 3 and col <= 3)
// either empty or boat spot that isn't hit
(no p.board[row][col]) or (some spot: BoatSpot | (p.board[row][col] = spot and spot.hit = False))
}
pred move[pre1: Player, post1: Player, pre2: Player, post2: Player, row: Int, col: Int] {
// guard: neither board is in final state
// should wellformed be part of the guard?
// if board1's turn:
// if validSpot[row, col, board2]:
// if boat spot:
// post2[row][col].hit = 1
// if nothing:
// post2[row][col] = MissedStrike
// post1 = pre1 // only one board changes at a time
// same for board2
// if finalState of board1: set board2 has_won to 1
// if finalState of board2: set board1 has_won to 1
// if it was board1's turn, it's board2's
// vice versa
}
pred traces {
// init[Game.initial1]
// init[Game.initial2]
// all b1, b2: Player | some (Game.next1[b1] and Game.next2[b2]) implies {
// some row, col: Int, p: Player | {
// move[b, Game.next[b], row, col, p]
// }
// or
// doNothing[b, Game.next[b]]
// }
}
run {wellformed} for exactly 2 Player, exactly 6 Boat, exactly 12 BoatSpot, 5 Int