How do I write a predicate to check for a Horizontal, vertical or diagonal wins for a tictactoe game in Alloy? I'm kind of struggling with the syntax below is my code:
open util/ordering [Time] as T
sig Time {}
abstract sig Game {
turn, winner, loser: Game
}
abstract sig Player {
opponent:Player
}
sig X extends Player {}
sig O extends Player {}
fact {
all t:Time| all p: Player | no p.opponent
all t: Time | all p: Player | all g:Game | one g.turn
all t:Time | all g:Game | one g.winner & g.loser
}
pred HorizontalWin {
}
I think your model might not be appropriate for this game. For example, I don't see a 3x3 grid in your model, so it is not clear how to express any property about the state of the game.
There are several other issues with your model. For example, the Game sig is abstract and it has no concrete subsigs, so instances of this model can never contain any games (thus turn, winner, and loser fields will always be empty as well). Also, you probably want to use the Time signature somewhere (either put some fields in it, or make other fields use it, e.g., turn: Player -> Time) and then add some facts about every two consecutive time steps to properly connect the game moves. Here is an idea:
open util/ordering [Move] as M
abstract sig Player {}
one sig X, O extends Player {}
abstract sig Cell {}
one sig C00, C01, C02, C10, C11, C12, C20, C21, C22 extends Cell {}
sig Board {
grid: Cell -> lone Player
}
sig Move {
player: Player,
pos: Cell,
board, board': Board // pre and post board
} {
// must choose an empty grid cell
no board.grid[pos]
// set the `pos` cell to `player`
board'.grid[pos] = player
// all other grid cells remain the same
all c: Cell - pos | board'.grid[c] = board.grid[c]
}
fact {
// empty board at the beginning
no M/first.board.grid
all m: Move {
some M/next[m] => {
// alternate players each move
M/next[m].player != m.player
// connect boards
M/next[m].board = m.board'
}
}
}
run {} for 9 but 10 Board
Related
I have to realize an application which permits to reserve a seat in a store. There are no sintax error, but I don't understand why terminal reply me "predicate not consistent". Can u help me?
This is my code:
open util/integer
sig Email{}
sig CF{}
sig Time{
hour: one Int,
minute:one Int,
second: one Int
}
abstract sig RegisteredUser{
email: one Email
}
sig User extends RegisteredUser{
cf: one CF
}
sig SM extends RegisteredUser{
cf: one CF,
store: one Store
}
sig Location{}
sig Date{}
abstract sig Status {}
//only one of this can be true
one sig Waiting extends Status {}
one sig Expired extends Status{}
one sig Pending extends Status{}
sig Ticket{
owner:one User,
date: one Date,
time: one Time,
status : one Status,
}
sig Visit{
owner:one User,
date: one Date,
time: one Time,
duration:one Time,
status : one Status,
products: some Product,
category: some Category,
}
//tickets are assumed with a default duration time of 15 min and entrance one for time, so 4*8=32 visit per day
sig TicketQueue {
max_visit:one Int,
ticket: some Ticket,
manager: one SM
}
sig VisitQueue{
category: some Category,
visit: some Visit,
manager: one SM
}
sig Store{
max_simultaneous: one Int,
location: one Location,
visitqueue: one VisitQueue,
ticketqueue: one TicketQueue,
product_category: some Category
}
sig Category{
simultaneous_seats: one Int,
}
sig Product{
category: one Category
}
// Constraints
// Registration data for the system are unique(Unique username and Fiscal Code)
fact registrationDataUniqueness {
no disjoint u1, u2: RegisteredUser | u1.email = u2.email
no disjoint u1,u2: User | u1.cf = u2.cf
no disjoint s1,s2: SM | s1.cf = s2.cf
no disjoint s:SM, u:User | s.cf=u.cf
}
//Ticket and Visit can have only one of status' values defined before
fact requestConsistency {
all s: Status | (s = Waiting && s != Expired && s !=Pending ) || (s != Waiting && s = Expired && s != Pending) || (s !=Waiting && s != Expired && s = Pending)
}
//SM can manage only one Store
fact StoreUniqueness{
no disjoint s1,s2: SM |s1.store=s2.store
}
// the same ticket or visit cannot be of two or more different user
fact UserUniqueness{
no disjoint t1,t2: Ticket | t1.owner=t2.owner
no disjoint v1,v2: Visit | v1.owner=v2.owner
}
//different products can not be of the same category
fact CategoryUniqueness{
no disjoint p1,p2: Product | p1.category=p2.category
}
//different stores can't have the same ticket or visit queue
fact QueueUniqueness{
no disjoint s1,s2: Store | s1.ticketqueue=s2.ticketqueue
no disjoint s1,s2: Store | s1.visitqueue=s2.visitqueue
}
//different tickets cannot have the same time
fact TimeUniqueness{
no disjoint t1,t2: Ticket | t1.time = t2.time
}
//for semplicity,in the visit/ticket queue, we consider "active" only visit/ticket with Waiting status
fact StatusQueue{
all tq:TicketQueue | tq.ticket.status=Waiting
all vq:VisitQueue | vq.visit.status=Waiting
}
//one ticket/visit can not belong to two or more different queue
fact ReservationUniqueness{
no disjoint tq1,tq2:TicketQueue | tq1.ticket=tq2.ticket
no disjoint vq1,vq2:VisitQueue | vq1.visit=vq2.visit
}
//SM is unique for a specific store, and its related ticket/visit queue
fact SMUniqueness{
no disjoint s1,s2: Store | s1.ticketqueue.manager=s2.ticketqueue.manager
and s1.visitqueue.manager=s2.visitqueue.manager
and s1.ticketqueue.manager=s2.visitqueue.manager
and s1.visitqueue.manager=s2.ticketqueue.manager
}
//different tickets/visits associated with the same user have different time
fact UniqueTimeUser {
all u: User, t1, t2: Ticket, v1,v2:Visit | ((u in t1.owner) and (u in t2.owner) and (u in v1.owner) and (u in v2.owner)
and (t1 != t2) and (v1 !=v2))
implies (t1.time != t2.time)
and (v1.time != v2.time)
}
//different ticket and visit associated with the same user have different time
fact UniqueTimeUser2 {
all u: User, t: Ticket, v:Visit | ((u in t.owner) and (u in v.owner) )
implies (v.time != t.time)
}
//Maximum number of visit with the same time for category
fact MaxTime{
all v:Visit, c: Category |(( c in v.category)) implies #v.time< c.simultaneous_seats
}
//Considering meaningfull integer value
fact PossibleValues{
all c: Category | c.simultaneous_seats>1 and c.simultaneous_seats<5
all s: Store | s.max_simultaneous >0 and s.max_simultaneous<50
all t: Ticket | t.time.hour>7 and t.time.hour<21 and ((t.time.minute=15) || (t.time.minute=30) || (t.time.minute=45)) and t.time.second=0
all v: Visit | v.time.hour>7 and v.time.hour<21 and ((v.time.minute=15) || (v.time.minute=30) || (v.time.minute=45)) and v.time.second=0 and v.duration.hour=0 and v.duration.minute>0 and v.duration.minute=<30 and v.duration.second=0
all tq: TicketQueue | tq.max_visit=32
}
pred addTicket[ t :Ticket,ti,ti':Time, tq, tq':TicketQueue]{
//precondition
ti' not in Ticket.time
#tq.ticket< tq.max_visit //seats available
//postconditions
tq'.manager= tq.manager
tq'.ticket= tq.ticket+t
t in tq'.ticket
#tq'.ticket< tq.max_visit
all t': Ticket | t' in tq.ticket implies t' in tq'.ticket
}
pred show{
#User = 4
#Store = 2
#SM = 2
#Category = 3
#TicketQueue = 2
#VisitQueue= 2
#Category = 5
some v, v': Visit | v.time != v'.time
#Ticket = 5
#Visit=5
}
run show for 4
This is the complete response of Alloy terminal:
Executing "Run show for 4"
Solver=sat4j Bitwidth=4 MaxSeq=4 SkolemDepth=1 Symmetry=20
15098 vars. 840 primary vars. 17697 clauses. 28ms.
No instance found. Predicate may be inconsistent. 1ms.
Have you run unsat core (using the MiniSAT with Unsat Core solver)? That might give you a hint. Another thought: I would simplify the model first and then only add features as you need them. I'm not sure that you really need to split the times into hours, minutes and seconds. That adds a lot of solver complexity, perhaps needlessly.
General observations:
Some inconsistences in your show predicate:
#Category = 3
#Category = 5
Your scope is definitely too small. You can't expect 5 Visit elements if you have a general scope of 4.
I'd rewrite your show predicate and run command as follows:
pred show{
some v, v': Visit | v.time != v'.time
}
run show for 10 but 7 Int, exactly 4 User, exactly 2 Store, exactly 2 SM, exactly 3 Category, exactly 2 TicketQueue, exactly 2 VisitQueue, exactly 5 Ticket, exactly 5 Visit
Notice the 7 Int.
It means that your model will contain int type atoms that represent all the integers you can express with a bitwidth of 7 (interval is [-64,63]).
As Daniel wrote, i'd also advise to stay as abstract as possible when you model in Alloy and thus to prefer concepts over quantitative values.
I concur with the previous advice of simplifying and would add to use check statements to test as you go. I'm not an expert with Alloy, so I take it slow and test early and often.
One thing that sticks out to me immediately is that your "show" predicate seems to be specifying multiplicities for some signatures that are greater than those allowed by the run statement ("for 4"). I've never specified multiplicity in a predicate that way, so I don't know how Alloy handles that. Offhand, those seem like contradictory constraints.
Also, I figured this out the hard way, but Alloy counts instances (atoms) of extended signatures as instances (atoms) of the parent(s). So, be aware of that.
The following model represents a sequence of actions given a certain pre-defined order.
open util/ordering[Time]
abstract sig Action {pre: set Action}
one sig A, B, C, D extends Action {}
fact{
pre = A -> B + D -> B + D -> C
}
sig Time { queue: Action -> lone State}
abstract sig State {}
one sig Acted, Ok, Nok extends State{}
pred Queue [t, t': Time] {
some a: Action-(t.queue).State |
a.pre in (t.queue).Ok + (t.queue).Nok and t'.queue=t.queue+(a->Acted)
}
pred Reply [t, t': Time] {
some a: (t.queue).Acted |
some s: State-Acted | t'.queue=t.queue++(a->s)
}
fact {
no first.queue
last.queue=Action->Ok or last.queue = Action -> Nok
all t:Time-last | Queue[t,t.next] or Reply[t,t.next]
}
run {last.queue=Action->Ok and some t:Time-last | t.queue = Action->Nok} for 9
With the run I would like to have a sequence where the last queueing action goes OK but some action failed before. However I don't get any instance.
Can someone explain me what am I doing wrong?
Regards, Andre.
The problem comes from the fact that once an action has, at a given time, a state which is Nok then it can't be changed back to another state in a future time(as suggested by the two quantifier in the Queue and Reply predicates).
The analyzer thus can't find an instance where in the final Time, all the actions are in an Ok state and where at a given time an action is in a Nok State. (This is what you request in your run command)
Hope it helps
If I have an Alloy model in the following format
one sig player {
name: String,
spot: set position
}
sig position {
Attack: Bool,
accuracy: int,
strength: int,
}
If I want to have a cetain rule such that each player can have 1 to 3 positions. Is there a way to create such a prediction or fact to do this?
Thanks,
You can add an appended fact to the player sig to specify that constraint. The cardinality operator (#) can be used to express the "set size" e.g.,
one sig player {
name: String,
spot: set position
} {
#position <= 1 && position >= 3
}
Given the below definition:
sig Name,Addr{}
sig Book{ addr : Name -> some Addr}
Let Name = { (J),(t), (b)}
Addr = {(1), (2)}
Book = {(bb0)}
I was curious that in the relation addr : Name -> some Addr, what is the multiplicity of the Name in the second column. Moreover, is the below possible
addr = {(bbo, j , 1), (bb0, j, 2)}
I trying to learn if j can occur more than once in the second column
The short answer is yes, but I only figured it out by trying, you have to define your model properly though:
abstract sig Name,Addr{}
abstract sig Book{ addr : Name -> some Addr}
one sig J,t,b extends Name {}
one sig a1,a2 extends Addr {}
one sig bb0 extends Book {}
run { #addr > 3 } for 4 int
Execute it and use the evaluator to evaluate addr you will see that it contains more than 3 elements, two of which have the same Name atom.
This question already exists:
Closed 10 years ago.
Possible Duplicate:
3 player card game turn system
I'm making a GUI 3 player card game (1 human and 2 computers). Each player has 3 cards in hand. In each round there is a dealer and the first player to play a card is the player at the right of the dealer. Each player can only play after the left player has played. (It's the basis of a card game)
After each player had put the 3 cards on the table. The dealer button passes to the player at the right and a new round begin.
I need help to do a function to control the turns, which can see whose turn it is to play. I it is human turn, it waits for input. If it is computer turn, it calls the action function of the calss.
What I have now is a Card class with a Suit and a Value.
A Deck class that is a list of Cards ( this class has a suffle function and a draw card function)
I have a Table class that had a list of cards ( that is where the cards go when a player plays them)
I have a Player class ( the same class is for human and computer player - is this good? )
The Player class have a Hand class ( thats where the 3 cards of the player are )
The Game class has one deck, one table and 3 players.
I have the function that the human is the first to play and moves one card to the table, then the 2 computer players move one card each. This only works if the human player is the first to play. Once the 3 cards of each player are played, begins another round, in this round is not the player but the computer to first play.
I don't have the idea how to make one system to control this. I don't want code, but the idea itself.
Thanks
I would have some properties like the following in my Player class:
public bool IsComputer { get; set; }
public bool IsCurrentTurn { get; set; }
public int TurnOrder { get; set; }
That way, you can write your logic based on if they are human or not and if it is their turn or not. You would use the TurnOrder property to determine whose turn it is next.
So if you are creating your Player objects like this:
Player player1 = new Player();
You could add to your main logic something like this:
if (player1.IsComputer)
{
PerformTurn();
}
else //Human
{
//Logic to wait and allow human player to do his or her turn here
}
Edit:
To determine whose turn it is, I would first have my players in a List of Player. Example:
List<Player> players = new List<Player>
{
new Player {Name = "Player 1", IsComputer = false, TurnOrder = 0, IsCurrentTurn = true},
new Player {Name = "Player 2", IsComputer = true, TurnOrder = 1, IsCurrentTurn = false},
new Player {Name = "Player 3", IsComputer = true, TurnOrder = 2, IsCurrentTurn = false}
};
Second, I would create a function that uses the TurnOrder property of each player to determine whose turn it is next. A method like this would do it:
public Player GetNextPlayer()
{
Player currentPlayer = players.First(x => x.IsCurrentTurn);
//if player is last in the turn order return first player
if (currentPlayer.TurnOrder == players.Max(x => x.TurnOrder).TurnOrder)
{
return players.Min(x => x.TurnOrder);
}
else
{
return players.First(x => x.TurnOrder == (currentPlayer.TurnOrder + 1));
}
}
Of course, you could just use the index of the list and skip using the TurnOrder altogether, although if you wanted to expand your game, using the index as the turn order may hurt you later on. I think the TurnOrder property is much more flexible.
To get the next player in the turn, just use this:
Player currentPlayer = GetNextPlayer();