|
Pattern Deduction AI in Connect Four in 1 Move 2023-09-21: An AI trying to do it the Human way - Pattern re0ppp
I think the concept of pattern deduction will be a central and main paradigm in AI because it does not depend on huge computing power and memory size as brute force AI does. In fact pattern deduction is an attempt to simulate a more human and as such smarter form of modelling and reasoning than brute force: an AI trying to do it the human way. For patterns and deduction see among others:
https://en.wikipedia.org/wiki/Pattern
https://en.wikipedia.org/wiki/Deductive_reasoning
Currently I'm working on a connect four AI that scans the board for certain patterns to determine from these patterns which player is winning in how many moves in stead of using brute force for this purpose. Currently the actual pattern deduction, this is which patterns imply a win in how many moves for example a win in 1, 2, 3, ... 42 moves, is done by myself using the visual representation, current AI version and programming code at:
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PEPSSSPEEPSPPSEEEPSSEEEESPEEEEEESEEEEEEPEEE
&relationship=All&drsid=0&pisid=0&page=1
The above link and corresponding first screenshot below (press ctrl+ for more image detail) show the last but one pattern re0ppp (four in a row with one empty rotating position with 0 empty positions below it) from which and only if this player is to move "Player Connects 4 in 1 Moves" is concluded by the AI. In future articles more of the patterns and work will be presented.
The ultimate goal and challenge is developing and programming a datamodel and algoritms that deduct by itself those patterns. Further on the plan is to apply and expand this pattern deduction AI framework on connect four with higher dimensions (unsolvable by brute force AI), chemistry, biochemistry, ecosystems, ... .
A pattern set (pset) is a cohesive set of patterns realising a win in x moves. A standalone pset is a pset that does not depend on extra conditions for all the remaining columns of the board. An all columns pset does depend on extra conditions for all the remaining columns of the board.
There exist one main path for deducing standalone psets going from connects 4 in 0 to connects 4 in 1 move (0->1 winning moves). In other words one main path for deducing the standalone pset re0ppp for connects 4 in 1 from the one pset pppp of connects 4 in 0 moves. This is the omission path or in the opposite direction, from 1 to 0 winning moves, the completion path. Pppp is the one pset of 4 in 0 moves. Player completed pppp with its previous move. To backtrack this one move one p has to be omitted from pppp and replaced by an empty position. As such re0ppp is deduced by ommission of a p from pppp.
I'll make here my first attempt at the ultimate goal, at describing the game and deducting the patterns and from these the game's outcomes with logic statements using an object oriented datamodel of the game and then at automating the deduction.
xMax = 7 and
yMax = 6 and
conn = 4 and
opponent(1) = 2 and
opponent(2) = 1
matrix.pppp(player) <=>
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
matrix(x0, y0 + extent) = player
∀end extent and
matrix.yEmpty(x0) = y0 + conn
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMove:
previousMove >= 0 and previousMove < conn:
matrix(x0 + previousMove, y0 + 1) = 0
Ǝend previousMove
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMove:
previousMove >= 0 and previousMove < conn:
matrix(x0 + previousMove, y0 + previousMove + 1) = 0
Ǝend previousMove
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMove:
previousMove >= 0 and previousMove < conn:
matrix(x0 + previousMove, y0 - previousMove + 1) = 0
Ǝend previousMove
Ǝend x0, y0
matrix.yEmpty(x) = ye <=>
matrix(x, ye) = 0 and
(matrix(x, ye - 1) != 0 or ye = 0)
matrix.rexppp(player, rex) <=>
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
matrix.yEmpty(x0) = y0 + conn - 1 - rex and
∀ extent:
extent >= 0 and extent < conn - 1: and
matrix(x0, y0 + extent) = player
∀end extent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
Ǝ rexExtent:
rexExtent >= 0 and rexExtent < conn:
matrix.yEmpty(x0 + rexExtent) = y0 - rex and
Ǝend rexExtent and
∀ extent:
extent >= 0 and extent < conn and extent != rexExtent:
matrix(x0 + extent, y0) = player
∀end extent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
Ǝ rexExtent:
rexExtent >= 0 and rexExtent < conn:
matrix.yEmpty(x0 + rexExtent) = y0 + rexExtent - rex
Ǝend rexExtent and
∀ extent:
extent >= 0 and extent < conn and extent != rexExtent:
matrix(x0 + extent, y0 + extent) = player
∀end extent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
Ǝ rexExtent:
rexExtent >= 0 and rexExtent < conn:
matrix.yEmpty(x0 + rexExtent) = y0 - rexExtent - rex
Ǝend rexExtent
∀ extent:
extent >= 0 and extent < conn and extent != rexExtent:
matrix(x0 + extent, y0 - extent) = player
∀end extent
Ǝend x0, y0
matrix.re0ppp(player) <=>
matrix.rexppp(player, 0) <=>
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
matrix.yEmpty(x0) = y0 + conn - 1 and
∀ extent:
extent >= 0 and extent < conn - 1: and
matrix(x0, y0 + extent) = player
∀end extent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
Ǝ rexExtent:
rexExtent >= 0 and rexExtent < conn:
matrix.yEmpty(x0 + rexExtent) = y0 and
Ǝend rexExtent and
∀ extent:
extent >= 0 and extent < conn and extent != rexExtent:
matrix(x0 + extent, y0) = player
∀end extent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
Ǝ rexExtent:
rexExtent >= 0 and rexExtent < conn:
matrix.yEmpty(x0 + rexExtent) = y0 + rexExtent
Ǝend rexExtent and
∀ extent:
extent >= 0 and extent < conn and extent != rexExtent:
matrix(x0 + extent, y0 + extent) = player
∀end extent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
Ǝ rexExtent:
rexExtent >= 0 and rexExtent < conn:
matrix.yEmpty(x0 + rexExtent) = y0 - rexExtent
Ǝend rexExtent
∀ extent:
extent >= 0 and extent < conn and extent != rexExtent:
matrix(x0 + extent, y0 - extent) = player
∀end extent
Ǝend x0, y0
game.connects4InMoves(player, 0) <=>
game.matrix.pppp(player) and
game.toMove = opponent(player)
game.afterMove(xMove) <=>
game.matrix.yEmpty(xMove) < yMax - 1 and
game.afterMove(xMove).toMove = opponent(game.toMove) and
game.afterMove(xMove).matrix(xMove, game.matrix.yEmpty(xMove)) = game.toMove and
game.afterMove(xMove).matrix.yEmpty(xMove) = game.matrix.yEmpty(xMove) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != xMove or y != game.matrix.yEmpty(xMove)):
game.afterMove(xMove).matrix(x, y) = game.matrix(x, y)
∀end x, y
game.connects4InMoves(player, 1) <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
game.afterMove(xMove).connects4InMoves(player, 0)
Ǝend xMove
Now, I want to deduct (proof), later automatically by algoritm, that:
game.connects4InMoves(player, 1)
is equivalent with:
game.toMove = player and
game.matrix.rexppp(player, 0)
The latter corresponds with the re0ppp pattern. So there I go. Given:
game.connects4InMoves(player, 1)
Step 1. The system substitutes the above function with its equivalence definition <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
game.afterMove(xMove).connects4InMoves(player, 0)
Ǝend xMove
Step 2. The system substitutes the connects4InMoves(player, 0) function with its equivalence definition <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
game.afterMove(xMove).matrix.pppp(player) and
game.afterMove(xMove).toMove = opponent(player)
Ǝend xMove:
Step 3. The system substitutes the pppp(player) function with its equivalence definition <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0, y0 + extent) = player
∀end extent and
game.afterMove(xMove).matrix.yEmpty(x0) = y0 + conn
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(xMove).matrix.yEmpty(x0 + previousMoveExtent) = y0 + 1
Ǝend previousMoveExtent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(xMove).matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent + 1
Ǝend previousMoveExtent
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(xMove).matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent + 1
Ǝend previousMoveExtent
Ǝend x0, y0
game.afterMove(xMove).toMove = opponent(player)
Ǝend xMove:
Step 4. The system adds the game.afterMove(xMove) function its equivalence definition <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0, y0 + extent) = player
∀end extent and
game.afterMove(xMove).matrix.yEmpty(x0) = y0 + conn and
game.afterMove(xMove).matrix.yEmpty(xMove) = game.matrix.yEmpty(xMove) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != xMove or y != game.matrix.yEmpty(xMove)):
game.afterMove(xMove).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(xMove).matrix.yEmpty(x0 + previousMoveExtent) = y0 + 1
Ǝend previousMoveExtent
game.afterMove(xMove).matrix.yEmpty(xMove) = game.matrix.yEmpty(xMove) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != xMove or y != game.matrix.yEmpty(xMove)):
game.afterMove(xMove).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(xMove).matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent + 1
Ǝend previousMoveExtent and
game.afterMove(xMove).matrix.yEmpty(xMove) = game.matrix.yEmpty(xMove) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != xMove or y != game.matrix.yEmpty(xMove)):
game.afterMove(xMove).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(xMove).matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(xMove).matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent + 1
Ǝend previousMoveExtent
game.afterMove(xMove).matrix.yEmpty(xMove) = game.matrix.yEmpty(xMove) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != xMove or y != game.matrix.yEmpty(xMove)):
game.afterMove(xMove).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0
game.afterMove(xMove).toMove = opponent(player)
Ǝend xMove:
Step 5. The system substitutes xMove with x0 in the first (vertical) Ǝ x0, y0 pattern and with x0 + previousMoveExtent in the horizontal, diagonal up and down patterns. <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0).matrix(x0, y0 + extent) = player
∀end extent and
game.afterMove(x0).matrix.yEmpty(x0) = y0 + conn and
game.afterMove(x0).matrix.yEmpty(x0) = game.matrix.yEmpty(x0) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 or y != game.matrix.yEmpty(x0)):
game.afterMove(x0).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0 + previousMoveExtent).matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.xEmpty(x0 + previousMoveExtent) = y0 + 1
Ǝend previousMoveExtent
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != game.matrix.yEmpty(x0 + previousMoveExtent)):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0 + previousMoveExtent).matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent + 1 and
Ǝend previousMoveExtent and
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != game.matrix.yEmpty(x0 + previousMoveExtent)):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0 + previousMoveExtent).matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent + 1
Ǝend previousMoveExtent
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != game.matrix.yEmpty(x0 + previousMoveExtent)):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0
game.afterMove(x0 + previousMoveExtent).toMove = opponent(player)
Ǝend xMove:
Step 6. From the two yEmpty(x0) statements the system solves
game.matrix.yEmpty(x0) = y0 + conn - 1 for the vertical Ǝ x0, y0 pattern,
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 for the horizontal Ǝ x0, y0 pattern,
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent for the diagonal up pattern and
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent for the diagonal down pattern,
adds these new statements and substitutes game.matrix.yEmpty(x0) with y0 + conn - 1 (vertical) and game.matrix.yEmpty(x0 + previousMoveExtent) with y0 (horizontal) or y0 + previousMoveExtent (diagonal up) or y0 - previousMoveExtent (diagonal down). <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0).matrix(x0, y0 + extent) = player
∀end extent and
game.afterMove(x0).matrix.yEmpty(x0) = y0 + conn and
game.afterMove(x0).matrix.yEmpty(x0) = game.matrix.yEmpty(x0) + 1 and
game.matrix.yEmpty(x0) = y0 + conn - 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 or y != y0 + conn - 1):
game.afterMove(x0).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0 + previousMoveExtent).matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.xEmpty(x0 + previousMoveExtent) = y0 + 1
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 and
Ǝend previousMoveExtent
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0 + previousMoveExtent).matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent + 1
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent
Ǝend previousMoveExtent and
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0 + previousMoveExtent):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn:
game.afterMove(x0 + previousMoveExtent).matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent + 1
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent
Ǝend previousMoveExtent
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0 - previousMoveExtent):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0
game.afterMove(x0 + previousMoveExtent).toMove = opponent(player)
Ǝend xMove:
Step 7. The system integrates ∀ x, y into ∀ extent. <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn and (x0 != x0 or y0 + extent != y0 + conn - 1):
game.matrix(x0, y0 + extent) = player
∀end extent and
game.afterMove(x0).matrix.yEmpty(x0) = y0 + conn and
game.afterMove(x0).matrix.yEmpty(x0) = game.matrix.yEmpty(x0) + 1 and
game.matrix.yEmpty(x0) = y0 + conn - 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 or y != y0 + conn - 1):
game.afterMove(x0).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn and (x0 + extent != x0 + previousMoveExtent or y0 != y0):
game.matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.xEmpty(x0 + previousMoveExtent) = y0 + 1
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 and
Ǝend previousMoveExtent
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn and (x0 + extent != x0 + previousMoveExtent or y0 + extent != y0 + previousMoveExtent):
game.matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent + 1
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent and
Ǝend previousMoveExtent and
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0 + previousMoveExtent):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn and (x0 + extent != x0 + previousMoveExtent or y0 - extent != y0 - previousMoveExtent):
game.matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent + 1
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent
Ǝend previousMoveExtent
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0 - previousMoveExtent):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0
game.afterMove(x0 + previousMoveExtent).toMove = opponent(player)
Ǝend xMove:
Step 8. The system normalizes ∀ extent <=>
game.toMove = player and
Ǝ xMove:
xMove >= 0 and xMove < xMax:
Ǝ x0, y0:
x0 >= 0 and x0 < xMax and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn - 1:
game.matrix(x0, y0 + extent) = player
∀end extent and
game.afterMove(x0).matrix.yEmpty(x0) = y0 + conn and
game.afterMove(x0).matrix.yEmpty(x0) = game.matrix.yEmpty(x0) + 1 and
game.matrix.yEmpty(x0) = y0 + conn - 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 or y != y0 + conn - 1):
game.afterMove(x0).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn and extent != previousMoveExtent:
game.matrix(x0 + extent, y0) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 and
Ǝend previousMoveExtent and
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= 0 and y0 < yMax - conn:
∀ extent:
extent >= 0 and extent < conn and extent != x0 + previousMoveExtent:
game.matrix(x0 + extent, y0 + extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 + previousMoveExtent and
Ǝend previousMoveExtent and
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1 and
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0 + previousMoveExtent):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0 or
Ǝ x0, y0:
x0 >= 0 and x0 < xMax - conn and
y0 >= conn and y0 < yMax:
∀ extent:
extent >= 0 and extent < conn and extent != previousMoveExtent:
game.matrix(x0 + extent, y0 - extent) = player
∀end extent and
Ǝ previousMoveExtent:
previousMoveExtent >= 0 and previousMoveExtent < conn:
game.matrix.yEmpty(x0 + previousMoveExtent) = y0 - previousMoveExtent
Ǝend previousMoveExtent and
game.afterMove(x0 + previousMoveExtent).matrix.yEmpty(x0 + previousMoveExtent) = game.matrix.yEmpty(x0 + previousMoveExtent) + 1
∀ x, y:
x >= 0 and x < xMax and
y >= 0 and y < yMax and
(x != x0 + previousMoveExtent or y != y0 - previousMoveExtent):
game.afterMove(x0 + previousMoveExtent).matrix(x, y) = game.matrix(x, y)
∀end x, y
Ǝend x0, y0
game.afterMove(x0 + previousMoveExtent).toMove = opponent(player)
Ǝend xMove:
Step 9. The system matches the green statements above with the equivalence defintion of matrix.re0ppp(player) and deducts (proofs) as such the re0ppp pattern. Currently this is done for the vertical, horizontal and diagonal up and down Ǝ x0, y0 patterns. <=>
game.toMove = player and
game.matrix.re0ppp(player)
Standalone Pset 1.1
This is thus the standalone pset 1.1 (re0ppp) of 4 in 1 deduced from the standalone pset 0.1 (pppp) from 4 in 0 moves. See the following list of links and screenshots further down for more examples of the re0ppp pattern:
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PSPSSSPEEPSPPSEEPPSESEEESPEEEEEESEEEEEEPEEE
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PSPSSSPEEPSPPSEEPPSSPEESSPSEEEEPSEEEEEEPEEE
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:SSPSSSPEPPSPPSEPPPSSPESSSPESEPSPSEPEESSPEPE
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PSPSSSPPPPSPPSSPPPSSPPSSSPPSSSSPSEPSPSSPEPE
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:SSPSSSPPPPSPPSSESPSSPPESSPPPSEPSSSEPESPPPES
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PSPSSSPPPPSPPSSPPPSSPPSSSPPSSSSPSSPSPSSPPPE
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PSSPPSPSPPSSPSPSSSPPESPPSSPEPSSPPSESPPSSPEP
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:SPSSPSPPSEPSSSPPEPPPSPPEPPSSSEESEEPEEESEESE
&relationship=All&drsid=0&pisid=0&page=1
https://www.tumia.org/en/directory/en/instance.php?tiname=
Connect%20Four:PPSSPSPPSSPSSSPPEPPPSPEEPPSSSEESEEPEEEEEESE
&relationship=All&drsid=0&pisid=0&page=1
Twitter:
https://x.com/nesta_red/status/1881992425096536535
Pattern Deduction AI in Connect Four 2023-09-21: An AI trying to do it the Human way - Pattern re0ppp” was written by Paka Small – 2023/09/21.
|