CS1950Y Lecture #6-8: Tic Tac Toe Board Code
Date 2/4-2/8, 2019



    // Feb 4th + Feb 6th

    abstract sig Player {}
    one sig X extends Player {}
    one sig O extends Player {}

    abstract sig Index {}
    one sig One extends Index {}
    one sig Two extends Index {}
    one sig Three extends Index {}

    sig Board {
      places: (Index -> Index) -> Player
    }

    fact atMostOnePerSquare {
      all b: Board | {
        all r, c: Index | {
          //#b.places[r][c] <= 1
    	  lone b.places[r][c]
        }
      }
    }

    run notenough {#places = 9} for 3 int
    // give 2^5 ints to count with (32)
    run enough {#places = 9} for 5 int

    pred xturn[b: Board] {
      #{r, c: Index | b.places[r][c] = X} =
      #{r, c: Index | b.places[r][c] = O}
    }

    pred oturn[b: Board] {
     // not xturn[b]
      sub[#{r, c: Index | b.places[r][c] = X}, 1] =
      #{r, c: Index | b.places[r][c] = O}

    }

    run xturn for 5 int
    run oturn for 5 int

    pred winning[b: Board, p: Player] {
      winH[b, p] or
      winV[b, p] or
      winD[b, p]
    }

    pred winH[b: Board, p: Player] {
    //  b.places[One][One] = p and b.places[One][Two] = p and b.places[One][Three] = p
      some r: Index | {
        b.places[r][One] = p
        b.places[r][Two] = p
        b.places[r][Three] = p
      }
    }

    pred winV[b: Board, p: Player] {
      some c: Index | {
        b.places[One][c] = p
        b.places[Two][c] = p
        b.places[Three][c] = p
      }
    }

    pred winD[b: Board, p: Player] {
      (b.places[One][One] = p and
      b.places[Two][Two] = p and
      b.places[Three][Three] = p)
      or
      (b.places[One][Three] = p and
      b.places[Two][Two] = p and
      b.places[Three][One] = p)
    }

    pred valid[b: Board] {
      xturn[b] || oturn[b]
    }

    run winningvalid {
      some b: Board |
        some p: Player |
          winning[b, p] and valid[b]
    } for 5 int

    pred move[b: Board, r,c: Index, p: Player, b': Board] {
       no b.places[r][c]
       //b'.places[r][c] = p
       b'.places = b.places + (r -> c -> p)
       p = X implies xturn[b]
       p = O implies oturn[b]
    }

    pred move2[b: Board, r,c: Index, p: Player, b': Board] {
       b'.places = b.places + (r -> c -> p)
       p = X implies xturn[b]
       p = O implies oturn[b]
    }

    run move for 2 Board, 5 int

    pred differentmoves {
      some b: Board, r, c: Index, p: Player, b': Board | {
        not (move[b, r, c, p, b'] iff move2[b, r, c, p, b'])
        //b.places != b'.places
      }
    }

    run differentmoves for 2 Board, 5 int


    pred bothTurn {
      some b: Board | {
        xturn[b]
        oturn[b]
      }
    }
    run bothTurn for 1 Board, 5 int

    pred NOTxwinimpliesoturn {
      some b: Board | {
        (xturn[b] or oturn[b])
        not (winning[b, X] implies oturn[b])
      }
    }
    run NOTxwinimpliesoturn for 1 Board, 5 int