Good thinking there, Lirtosaist!

I am doing a re-design of the AI, and I am getting the AI's move priorities in line. So far, the routine's priorities are as follows:

**NoahK wrote:**

1) Place the winning move

2) Prevent the player from placing the winning move on the next turn (eg. if the player has 2 in a row, place the third one to block it)

3) Move in a corner adjacent to a spot already played

4) Move in an edge of a adjacent to a spot already played

5) Make a random move

I think it would work better like this:

**NoahK wrote:**

1) Place the winning move

2) Prevent the player from placing the winning move on the next turn (eg. if the player has 2 in a row, place the third one to block it)

3) Play the center spot

4) Move in a corner adjacent to a spot already played

5) Move in an edge adjacent to a spot already played

6) Make a random move

<Edit>

In searching for Tic-Tac-Toe AI, I found this little list:

StackExcange Link

**recursion.ninja on StackExchange wrote:**

The following algorithm will allow you (or the AI) to always deny your opponent victory:

Win: If you have two in a row, you can place a third to get three in a row.

Block: If the opponent has two in a row, you must play the third to block the opponent.

Fork: Create an opportunity where you have two threats to win (two non-blocked lines of 2).

Blocking an opponent's fork: If there is a configuration where the opponent can fork, you must block that fork.

Center: You play the center if open.

Opposite corner: If the opponent is in the corner, you play the opposite corner.

Empty corner: You play in a corner square.

Empty side: You play in a middle square on any of the 4 sides.

Pick the highest possible on the list

I will do my best to implement this, though the forking may be hard to do.

<Edit some more>

I've fiddled around with using that algorithm I found, and here are the results:

**SourceCoder 3 (OPTICODE) wrote:**

:ClrList L1

:0->T

:4->U

://Check for Win and Block (if Win, Winning move is located at T)

:For(S,1,3

:For(Q,1,3

:If [A](S,Q-1+(Q=1))=[A](S,Q+1-(Q=3)) and [A](S,Q-1+(Q=1))not([A](S,4-Q

:Then

:S+(4-Q)[i]->L1(1+dim(L1

:If U=[A](S,Q+1-(Q=3

:dim(L1->T

:End

:If [A](Q-1+(Q=1),S)=[A](Q+1-(Q=3),S) and [A](Q-1+(Q=1),S)not([A](4-Q,S

:Then

:4-Q+S[i]->L1(1+dim(L1

:If U=[A](Q+1-(Q=3),S

:dim(L1->T

:End

:End

:End

:

://Check for forking

:If not(dim(L1

:Then

://code coming soon (hopefully)

:End

:

://Check to block a fork

:If not(dim(L1

:Then

://code coming soon (hopefully)

:End

:

://Play the center if possible

:If not(dim(L1

:Then

:If not([A](2,2

:2+2[i]->L1(1+dim(L1

:End

:

://Play a corner opposite the opponent. (or opposite self, as that is a peudo-fork-maker, and will stand for the fork code for now

:If not(dim(L1

:Then

:For(S,1,3,2

:For(Q,1,3,2

:If [A](4-S,4-Q) and not([A](S,Q

:S+Q[i]->L1(1+dim(L1

:End

:End

:End

:

://Play random open corner

:If not(dim(L1

:Then

:For(S,1,3,2

:For(Q,1,3,2

:If not([A](S,Q

:S+Q[i]->L1(1+dim(L1

:End

:End

:End

:

://Play random open edge

:If not(dim(L1

:Then

:For(S,1,3,2

:If not([A](2,S

:2+S[i]->L1(1+dim(L1

:If not([A](S,2

:S+2[i]->L1(1+dim(L1

:End

:End

:

://Finish it off

:not(T)randInt(1,dim(L1))+T->S

:real(L1(S->I

:imag(L1(S->J

This also implements Lirtosaist's imaginary list idea. This code is a charm!

It is only 503 bytes on the calc, and that includes the empty If-Then's. And it's super smart acting now!

The shell I am using to use the AI code it the same as before, just with a call to this new program:

**Code:** ```
:DSS6
```

"0810081008100810FFFF081008500B100D500B500810FFFF0810081008100810"

SetUpEditor

AxesOff

0->O

0->N

Lbl 0

ClrHome

{3,3->dim([A]

Fill(0,[A]

Menu("Tic-Tac-Toe AI","Play",1,"Quit",2

Lbl 1

ClrDraw

~33->Xmin

61->Ymax

~1->Ymin

61->Xmax

For(A,0,60,20

Line(A,0,A,60

Line(0,A,60,A

End

Text(20,0,"GAMES WON

Text(26,0,"O: ",O

Text(32,0,"X: ",N

1->P

2->A

2->B

0->W

0->R

Repeat W or theta=45

If B>3

3->B

Text(0,0,"O'S TURN

Pt-On(20A-10,20B-10

Repeat theta

getKey->theta

End

Pt-Off(20A-10,20B-10

A+(theta=26 and A<3)-(theta=24 and A>1->A

B+(theta=25 and B<3)-(theta=34 and B>1->B

Pt-On(20A-10,20B-10

If theta=105 and not([A](A,B)

Then

R+1->R

Pt-Off(20A-10,20B-10

Circle(20A-10,20B-10,7

1->[A](A,B

0->D

0->E

0->W

For(C,1,3

[A](1,C)+[A](2,C)+[A](3,C->D

[A](C,1)+[A](C,2)+[A](C,3->E

If D=3 or E=3

1->W

If D=12 or E=12

2->W

End

[A](1,1)+[A](2,2)+[A](3,3->D

[A](3,1)+[A](2,2)+[A](1,3->E

If D=3 or E=3

1->W

If D=12 or E=12

2->W

If R<9 and not(W

Then

R+1->R

Text(0,0,"X'S TURN

prgmOPTICODE

4->[A](I,J

Line(20I-3,20J-3,20I-17,20J-17

Line(20I-3,20J-17,20I-17,20J-3

Pt-Off(20I-10,20J-10

End

End

0->D

0->E

0->W

For(C,1,3

[A](1,C)+[A](2,C)+[A](3,C->D

[A](C,1)+[A](C,2)+[A](C,3->E

If D=3 or E=3

1->W

If D=12 or E=12

2->W

End

[A](1,1)+[A](2,2)+[A](3,3->D

[A](3,1)+[A](2,2)+[A](1,3->E

If D=3 or E=3

1->W

If D=12 or E=12

2->W

If R=9 and not(W

45->theta

End

If W

Then

O+(W=1->O

N+(W=2->N

Text(0,0,sub("OX",W,1)," WINS! "

Text(26,7,O

Text(32,7,N

Pause

Else

Text(0,0,"TIE! "

Pause

End

Goto 0

Lbl 2

ClrHome

Stop

Once this gets optimized (PT_), we should be getting closer and closer to a <1kb size! (Right now the shell here is 1115 and the new AI is 527)

WHOOO THIS IS COMING ALONG AWESOMELY!!!

This is probably the 7th edit to this post...

Here is a screenshot of the new AI in action:

It's pretty good.