Omnimaga

Calculator Community => Other Calc-Related Projects and Ideas => TI Z80 => Topic started by: Radical Pi on March 09, 2010, 12:51:08 am

Title: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 09, 2010, 12:51:08 am
EDIT 2: This code is outdated. The final version is in a later post in this topic.

This is what I've been working on all day. It isn't completely finished; I realized just a few minutes ago that I totally forgot to handle a tied game, and it doesn't give you any fancy victory message when you win. And you will win, since the AI opponent is just "choose a random column." But I didn't make this for the AI; I made it for everything else.

The main program is MAINLOOP (obviously) and I made GRAVITY a subprogram because it saves a few bytes. That brings me to the main reason I made this topic... I want to see if this can be optimized any more than it already is. I think I've already done a decent enough job on it, but I really want to make it as small as it can be.

I've attached both programs, and here's the code too:

Code: [Select]
MAINLOOP
:Disp "WILL YOU MOVE
:Input "FIRST? Y/N: ",Str1
:Str1≠"Y→T
:{6,7→dim([A]
:Fill 0,[A]
:ClrHome
:For(A,2,7
:Output(A,2,". . . . . . .
:End
:Output(8,2,"-------------
:Repeat W
:If T
:Then
:Repeat not([A](1,Ans
:randInt(1,7→C
:End
:prgmGRAVITY
:Else
:DelVar M4→C
:Repeat M
:Output(1,2C,"V
:Repeat max(K={21,24,26,45
:getKey→K
:End
:If K=45
:Return
:If K=21 and not([A](1,C
:Then
:prgmGRAVITY
:1→M
:Output(1,2C,"
:End
:If K≠21
:Then
:Output(1,2C,"
:C-25+Ans→C
:Ans-7(Ans=8)+7not(Ans→C
:End
:End
:End
:{1,1,1,1→{L1}
:T+1→T
:1→A
:While A<4 and R+A≤6 and Ans
:If T=[A](R+A,C
:Then
:1+{L1}(1→{L1}(1
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and C-A≥1 and Ans
:If T=[A](R,C-A
:Then
:1+{L1}(2→{L1}(2
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and C+A≤7 and Ans
:If T=[A](R,C+A
:Then
:1+{L1}(2→{L1}(2
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R+A≤6 and C+A≤7 and Ans
:If T=[A](R+A,C+A
:Then
:1+{L1}(3→{L1}(3
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R-A≥1 and C-A≥1 and Ans
:If T=[A](R-A,C-A
:Then
:1+{L1}(3→{L1}(3
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R+A≤6 and C-A≥1 and Ans
:If T=[A](R+A,C-A
:Then
:1+{L1}(4→{L1}(4
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R-A≥1 and C+A≤7 and Ans
:If T=[A](R-A,C+A
:Then
:1+{L1}(4→{L1}(4
:A+1→A
:Else
:0
:End
:End
:max(3<{L1}→W
:not(T-1→T
:End

GRAVITY
:DelVar  RR
:Repeat Ans=5 or [A](Ans+1,C
:Ans+1
:End
:Ans+(Ans=5 and not([A](6,C→R
:T+1→[A](Ans,C
:Output(R+1,2C,sub("XO",T+1,1

In particular, I'm wondering if there's a less ridiculous way of figuring out when a player wins (which is the section in MAINLOOP from the :{1,1,1,1→{L1} line to the :max(3<{L1}→W line). And I know I could already save a few bytes in that section by incrementing T for its duration. But what else? I've hit my limit already :(

EDIT: I did that T+1→T optimization and saved six bytes. And it also made me catch a bug I didn't even know was there. I've updated the attached file with this fix too.
Title: Re: A typical Connect 4 game in TI-Basic
Post by: meishe91 on March 09, 2010, 12:59:20 am
Hmmm...I don't have time to look over it a whole lot right now (since I'm probably gonna have to pull an all-nighter from homework already...) but I will check it out when I have time. It looks nice though.
By the way, by the time I get a chance to look at it, it will already have been looked at by someone more experienced :P
Title: Re: A typical Connect 4 game in TI-Basic
Post by: DJ Omnimaga on March 09, 2010, 01:18:38 am
Cool to hear you're starting coding ^^

Also good idea to start with smaller projects too (like Connect 4), some people usually start with a massive RPG or platformer x.x.

Unfortunately I am not as good for optimizing and reading people code, so it migth be better someone else check the code for deepest optimizations.

I'll give it a try later, though. :)
Title: Re: A typical Connect 4 game in TI-Basic
Post by: meishe91 on March 09, 2010, 01:48:32 am
Isn't Eeems pretty good at spotting optimizations?
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Eeems on March 09, 2010, 01:54:42 am
I'm ok at some, but that requires me to have the time to sit and read through the code. And unfortunatly I just saw this right as I decided it was too late for me to be up, so I'll have to wait until tomorrow before diving into this.

Edit: hmm, I took a quick peek, and isn't there a way to add all the columns of a matrix? Or is it rows? That could help for checking for a win.
Title: Re: A typical Connect 4 game in TI-Basic
Post by: meishe91 on March 09, 2010, 01:57:08 am
Ah ok, I just saw that you looked over tifreak's code so ya, just thought you might be. But ya, I know what you mean.
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Eeems on March 09, 2010, 02:00:59 am
Well I'm pretty good at optimizing my own code, but it's not so easy for me to optimize other peoples code.
I do consider myself an ok optimizer though.
Title: Re: A typical Connect 4 game in TI-Basic
Post by: meishe91 on March 09, 2010, 02:02:34 am
Ya, I would bet that is how most people are. Because you know what you're trying to do with your own code so you kinda see the things better, if that makes sense. But cool...I need to get better at it.
Back on topic though, as I said, I shall check this out when I have time :)
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 09, 2010, 02:12:24 am
There's cumSum( for finding the cumulative sum of a matrix's columns, but that can't really help me at all, not the way I'm currently storing the grid. Plus, it would only do anything useful for the downwards victory.
The fact that you can win diagonally is what makes this so hard to make more efficient, I think.
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Eeems on March 09, 2010, 09:14:23 am
Well cumSum() can also help if you T[A] which just rotates the matrix.
But yeah diagnal is kind of hard.

EDIT (DJ_Omni made the "T" an exponent with bbcode tags since it could have been confusing)
Title: Re: A typical Connect 4 game in TI-Basic
Post by: ztrumpet on March 09, 2010, 10:20:05 am
That looks very nice!  I think the check code is as optimized as it can get in its current state.  You could probably do something tricky to get it smaller, but I'm not sure what you would have to do.  It looks great!  Great job! ;D
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 10, 2010, 05:15:07 pm
Here are the finished versions of both programs. Now it doesn't go into an infinite loop if you fill up the board :D
Again, if anyone sees any optimizations, don't hesitate to tell me; I literally want to shave off every byte possible. I still think there must be a better way to check if a player has won, but I have no idea how.

Also, if anyone has any idea how I could improve the AI (as in, make an AI that does more than choose a random unfilled column), I'd love to hear it.

Anyway, here's the code. A zip of it is attached too.

Code: (prgmCONNECT4) [Select]
:Disp  "WILL YOU MOVE
:Input "FIRST? Y/N: ",Str1
:Str1≠"Y→T
:{6,7→dim([A]
:Fill 0,[A]
:ClrHome
:For(A,2,7
:Output(A,2,". . . . . . .
:End
:Output(8,2,"-------------
:DelVar URepeat W or U=42
:If T
:Then
:Repeat not([A](1,Ans
:randInt(1,7→C
:End
:prgmZG
:Else
:DelVar M4→C
:Repeat M
:Output(1,2C,"V
:Repeat max(K={21,24,26,45
:getKey→K
:End
:If K=45
:Return
:If K=21 and not([A](1,C
:Then
:prgmZG
:1→M
:Output(1,2C,"
:End
:If K≠21
:Then
:Output(1,2C,"
:C-25+Ans→C
:Ans-7(Ans=8)+7not(Ans→C
:End
:End
:End
:{1,1,1,1→L1
:T+1→T
:1→A
:While A<4 and R+A≤6 and Ans
:If T=[A](R+A,C
:Then
:1+L1(1→L1(1
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and C-A≥1 and Ans
:If T=[A](R,C-A
:Then
:1+L1(2→L1(2
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and C+A≤7 and Ans
:If T=[A](R,C+A
:Then
:1+L1(2→L1(2
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R+A≤6 and C+A≤7 and Ans
:If T=[A](R+A,C+A
:Then
:1+L1(3→L1(3
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R-A≥1 and C-A≥1 and Ans
:If T=[A](R-A,C-A
:Then
:1+L1(3→L1(3
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R+A≤6 and C-A≥1 and Ans
:If T=[A](R+A,C-A
:Then
:1+L1(4→L1(4
:A+1→A
:Else
:0
:End
:End
:1→A
:While A<4 and R-A≥1 and C+A≤7 and Ans
:If T=[A](R-A,C+A
:Then
:1+L1(4→L1(4
:A+1→A
:Else
:0
:End
:End
:max(3<L1→W
:not(T-1→T
:U+1→U
:End
:ClrHome
:If Ans≠42 and W
:Then
:Disp "YOU "+sub("LOSEWIN!",4T+1,4
:Else
:"TIED GAME

Code: (prgmZG) [Select]
:DelVar  RR
:Repeat Ans=5 or [A](Ans+1,C
:Ans+1
:End
:Ans+(Ans=5 and not([A](6,C→R
:T+1→[A](Ans,C
:Output(R+1,2C,sub("XO",T+1,1
Title: Re: A typical Connect 4 game in TI-Basic
Post by: DJ Omnimaga on March 10, 2010, 11:19:14 pm
cool I'll update the file on my computer. I didn't got time to try the other version because of work and I was busy messing with my Nspire and Axe. Hopefully I should be able to test later (and maybe do a screenshot)
Title: Re: A typical Connect 4 game in TI-Basic
Post by: _player1537 on March 13, 2010, 02:20:38 pm
I was working on a project like this a couple weeks ago.  I also tried to make an AI if it would help you.  atm it only checks for an instant win/lose then places it, otherwise it puts a random peice.  If you'd like to look at it I'll send it to the computer.  Hope I can help.

(Also I forgot to mention that my code can be far from readable as I abuse the Ans variable :P)
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 13, 2010, 04:03:38 pm
I'd love to take a look at your AI, especially if it can help me optimize my win-checking code, which it sounds like it can
Title: Re: A typical Connect 4 game in TI-Basic
Post by: _player1537 on March 13, 2010, 05:32:08 pm
OK, here goes.  I would like to point out that checking the board doesn't fully work yet, but it shouldn't be too hard to fix.  I might get around to fixing it, just don't run it with checking enabled.  The AI does work as expected though.  Sorry if my code is hard to understand, I'll explain it if you want.

Edit: This really does need an explanation...
Prgm CheckBrd starts at a certain spot and checks in the direction you specify (look in connect AI where it has the list then runs the program) it keeps going that direction until it meets a different tile, counting as it goes.  When it reaches a different tile it goes back to the starting spot and keeps counting in the opposite direction.  I just realized that I could implement your method for horizontal and vertical checking.  Anyways, there you go ;)


CheckBrd:
Code: [Select]
:{Ans(1),Ans(2),Ans(3),Ans(4),Ans(5),Ans(6),Ans(7),1
:Repeat Ans(7)=2 or Ans(6)≥4
:If max(Ans(1)+Ans(3)={1,2,3,4,5,6}) and max(Ans(2)+Ans(4)={1,2,3,4,5,6,7})
:Then
:If [A](Ans(1)+Ans(3),Ans(2)+Ans(4))=Ans(5)
:Then
:{Ans(1)+Ans(3),Ans(2)+Ans(4),Ans(3),Ans(4),Ans(5),Ans(6)+1,Ans(7),Ans(8
:Else
:{C,A,‾Ans(3),‾Ans(4),Ans(5),Ans(6),Ans(7)+1,Ans(8
:End
:Else
:{C,A,‾Ans(3),‾Ans(4),Ans(5),Ans(6),Ans(7)+1,Ans(8
:
:End
:If Ans(6)≥Ans(8
:Then
:For(E,A+.1C,‾10
:End
:{Ans(1),Ans(2),Ans(3),Ans(4),Ans(5),Ans(6),Ans(7),Ans(6
:End
:
:End

ConnectAI:
Code: [Select]
:For(A,1,7
:Matr►List[A],A,L1
:sum(L1≠0)+E→E
:End
:If E<5
:Goto AA
:0→E
:For(A,1,7
:0→B
:Repeat [A](Ans,A) or Ans=7
:Ans+1
:End
:Ans-1→C
:{C,A,1,0,P+1,1,0
:prgmCHECKBRD
:{C,A,‾1,1,Ans(5),1,0
:prgmCHECKBRD
:{C,A,0,1,Ans(5),1,0
:prgmCHECKBRD
:{C,A,1,1,Ans(5),1,0
:prgmCHECKBRD
:End
:real(E→E
:If E≠0
:Then
:If fPart(M)=.5
:not(P→P
:P+1→[A](10fPart(E),iPart(E
:iPart(M→M
:Else
:If fPart(M)=.5
:Return
:not(P→P
:M+.5→M
:prgmCONECTAI
:If fPart(M)=0
:Return
:M-.5→M
:not(P→P
:Lbl AA
:Repeat [A](1,Ans)=0
:randInt(1,7
:End
:Ans→B
:0
:Repeat Ans=7 or [A](Ans,B)
:Ans+1
:End
:P+1→[A](Ans-1,B
:Return
:End

Connect5:
Code: [Select]
:
:0
:Menu("MODE?","NO AI/NO CHECK",0,"NO AI/CHECK",1,"EASY AI/CHECK",2
:Lbl 2
:Ans+1
:Lbl 1
:Ans+1
:Lbl 0
:Ans→M
:DelVar [A]
:{7,7→dim([A]
:0→P
:prgmDRAWBOAR
:Repeat K=45
:Output(1,1,P
:getKey→K
:If K=24
:R-1→R
:If K=26
:R+1→R
:If R>7
:1→R
:If R<1
:7→R
:Output(2,1,"                "
:Output(2,2R,"V
:If K=21
:Then
:If not([A](1,R
:Then
:0
:Repeat [A](Ans,R) or Ans=7
:Ans+1
:End
:Ans-1→C
:P+1→[A](Ans,R
:prgmDRAWBOAR
:
:If M=1 or M=2
:Then
:0→E
:R→A
:{C,A,1,0,P+1,0,0
:prgmCHECKBRD
:{C,A,‾1,1,Ans(5),0,0
:prgmCHECKBRD
:{C,A,0,1,Ans(5),0,0
:prgmCHECKBRD
:{C,A,1,1,Ans(5),0,0
:prgmCHECKBRD
:If E>0
:Then
:Output(1,1,"YOU WIN!!!
:Return
:End
:End
:
:
:not(P→P
:
:If M=2:Then
:Output(1,1,"THINKING...
:prgmCONECTAI
:not(P→P
:prgmDRAWBOAR
:Output(1,1,"           "
:End
:
:End
:
:End
:End
:Return

DrawBoar:
Code: [Select]
:ClrHome
:Output(3,1,"1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"
:Output(1,1,"DRAWING...
:For(B,1,7
:For(C,1,6
:Output(C+2,2B,sub(" 0O",[A](C,B)+1,1
:End
:End
:Output(1,1,"                "
:
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 13, 2010, 07:01:10 pm
Uh... If you wouldn't mind, could you explain what some of the variables are? And especially what the elements of the list that CheckBrd needs are?

I really am terrible at reading other people's code v_v
Title: Re: A typical Connect 4 game in TI-Basic
Post by: ztrumpet on March 13, 2010, 09:44:29 pm
That looks cool. :D  I was wondering, why does it say "Connect 5"? Is it a typo? :)

It looks pretty good.  Great job _player! ;D
Title: Re: A typical Connect 4 game in TI-Basic
Post by: _player1537 on March 13, 2010, 09:50:47 pm
no problem, I'm gonna have to study it too, but I think I remember it...

Variable A is the column that we are checking, starting at one ending at seven.
Variable C uppermost spot that something can be placed, such as if you have a column with 4 holes filled, C will be the hole above the            .   highest blackened in spot
C and A are the first two list elements.
the 3rd element is the direction in the Y direction, such as if it is 1 it will be going Up first, 0 it won't go up at all, -1 it will go down first
the 4th element is the X direction
the 5th element is the piece it is looking for, such as if it is 1 it will be searching for every piece that is a 1
the 6th element is the number of pieces that are in a row, it starts at one because when it is checking for pieces there will always be one, piece, the one you place down
the 7th is... I really don't remember, it might have been something I threw in for testing

E the place where there is an instant win/lose
M is the Mode you are in.  I used it for one more thing which I'll try to explain.  It would first check for an instant win/lose for the AI, then if there was no instant win/lose it would check for the opponent too... actually it was probably something else because I don't see why I would do that... sorry I'll keep thinking for that
Matrix A is the matrix the board is stored in


I think that is it, sorry for the very messy post, but I hope that helped clarify for some people if not just tell me and I'll try to explain it better :)


Edit: its called connect5 because I made connect4 at first and then wanted to try something different without messing up all my code, so I copied it to a new one called connect 5     Thank you, I thought it was kinda redundant :P
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 13, 2010, 10:37:00 pm
Thanks, now I understand much more of it!
I think I'm going to update my Connect 4 program with a modified version of your method to check the board for wins.

Also, am I right in saying that your board is stored sideways? As in, the bottom row in my version is [A](7,x) but in yours it's [A](1,x)? I might be able to shave off a few more bytes by switching to this convention...

Yay for insight ;D
Title: Re: A typical Connect 4 game in TI-Basic
Post by: _player1537 on March 13, 2010, 10:55:44 pm
actually, I think it is stored where the 6th row from the top is the bottom row, the 7th is just incase

idk, Matrices have always confused me, at least the part where you take a specific chunk out of it ([a](3,5))
Title: Re: A typical Connect 4 game in TI-Basic
Post by: Radical Pi on March 13, 2010, 11:05:41 pm
I just remember that matrices are (row,column) and that's enough for me.

And that explains why your board was 7x7... I was wondering about that as well.