Velena (Four-in-a-row)

User projects written in or related to FreeBASIC.
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Velena (Four-in-a-row)

Post by Roland Chastain »

Hello gentlemen !

I would like to present to you my Four-in-a-row game.

Image

The interesting point (I believe) is the simple way the interface communicates with the engine. The engine is a console application. It receives a string as parameter, which is the history of the game (a sequence of characters from "1" to "7"). The program returns its move, using the same convention, and closes.

So, if someone would to develop his own engine, without wasting time to make an interface, he could easily reuse that one. The package contains also code to make an engine play against another a given number of games.

Here is an example. It's an engine that plays random (but legal) moves. I use it to test the strength of my main engine.

Code: Select all

#INCLUDE "engine.bas"

DIM g AS tGrid
DIM e AS tEngine

g.Empty

RANDOMIZE

IF g.Fill(COMMAND(1)) THEN ' The engine initializes its internal grid from the string received as parameter
  PRINT STR(e.Move1(g)) ' It returns its move...
ELSE
  PRINT "0" ' or it returns 0 if the string was unvalid.
END IF
Thanks to dodicat for his cairo DLLs and examples.

Update 2018

The latest version of the game uses the Velena engine by Giuliano Bertoletti.
Last edited by Roland Chastain on May 06, 2018 16:07, edited 3 times in total.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Another Four-in-a-row

Post by TJF »

Hello Roland, nice concept!

You can easily exchange the game engine. And you can exchange the GUI code as well. And make it cross-platform ...

Since you used cairo for drawing it's easy to build a GTK+ GUI around that code. Find an (old-schooled) example in the Scribble source for GTK+-2. It gets more simple when using GTK+-3, since this version has inbuild cairo features.

And this application is a right-sized example to learn about I18N (= internationalization, in a professional way). Find a working example in .../examples/GUI/GTK+/FB_Calc/ (includes FB source code and all utility files, for en/de translations in this case, GladeToBac was used to support the *.pot file creation).
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Another Four-in-a-row

Post by BasicCoder2 »

Hi Roland,

A very professional implementation of the game and show case for FreeBasic.

Sound?

When I run it Windows 8 gives a warning that it is an unknown publisher.

I have a touch screen and tried pressing the buttons with my finger instead of using the mouse but without success?

Touch screen input makes programs suitable for running on a tablet and your implementation.

John
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Another Four-in-a-row

Post by Roland Chastain »

@TJF

I began to look at GTK, and I could compile some examples, helped by the indications that you gave here and there in the forum.

@BasicCoder2

Thank you for your support and observations, John.

My next project is to rewrite my chess program following the same method. I believe this is the key to progress in chess programming : I mean to have under the hand a ready-to-use interface. The string of numbers could be replaced, for example, by a string using the Forsyth-Edwards notation. It would be much easier to use than the protocols like XBoard or UCI (on my part, I am still unable to use them). And it would allow an effective collaboration between FB programmers, and even more, since with that method the engine can be written in any language !
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Another Four-in-a-row

Post by BasicCoder2 »

Hi Roland,

Still intend working on your chess program. For me playing with the chess program was learning how they did it and writing one would have been more about showing myself I understood how they did it.

My programming style is much different to yours :)

As a hobby programmer I see it more of an exercise in puzzle solving.

This is more like I might have tackled the Four In A Row game using the fb graphics to roll my own GUI.

I haven't tested it enough to iron out all the bugs but it sort of works. The only AI however is to block a potential four in a row or make a four in a row for a win. Otherwise its moves are random without any strategy or analysis of the game state.

Code: Select all

screenres 406,480,32

color rgb(124,252,0),rgb(72,61,139)   'lime green ink, purple paper
cls   'executes colors

'GLOBAL VARIABLES
dim shared as integer mx,my,mb    'mouse variables
dim shared as integer board(7,6)
dim shared as integer selection,player,winPosition,win
dim shared as string  key

sub clearBoard()
    for j as integer = 0 to 5
        for i as integer = 0 to 6
            board(i,j)= 0
        next i
    next j
end sub

const TLX = 10  'displacement on screen
const TLY = 100

type vector
    x as integer
    y as integer
end type

dim shared as vector moves(7)
for i as integer = 0 to 6
    moves(i).x = i
    moves(i).y = 5
next i

sub drawBoard()
    for j as integer = 0 to 5
        for i as integer = 0 to 6
            if board(i,j)=0 then
                circle (i*48+48+TLX,j*48+48+TLY),18,rgb(106,90,205),,,,f
            end if
            if board(i,j)=1 then
                circle (i*48+48+TLX,j*48+48+TLY),18,rgb(255,69,0),,,,f
            end if
            if board(i,j)=-1 then
                circle (i*48+48+TLX,j*48+48+TLY),18,rgb(255,204,0),,,,f
            end if
        next i
    next j
    
    'draw ribbon top/bottom
    line (0,0)-(405,49),rgb(44,76,76),bf
    line (0,430)-(405,479),rgb(44,76,76),bf
    
    'draw select buttons
    for i as integer = 0 to 6
        line (i*48+TLX+30,336+TLY)-(i*48+19+30+TLX+18,336+18+TLY),rgb(57,89,89),bf
    next i
    
    draw string (TLX+40,442)," A     B     C     D     E     F     G"
    
    'draw label
    line (40,22)-(364,50),rgb(57,89,89),bf

    if player = 1 then
        draw string (50,34),"           White to Move            "
    end if
    if player = -1 then
        draw string (50,34),"           Black to Move            "
    end if
    
    
end sub

function findWin(player as integer) as integer
    dim as integer win          'flag four in a row found
    dim as integer pieceCount   'count pieces in row
    pieceCount = 0
    win = 0
    
    for i as integer = 0 to 6
        for k as integer = 0 to 2

            pieceCount = 0            
            for j as integer = k to k+3
                if board(i,j)=player then
                    pieceCount = pieceCount + 1
                end if
            next j
            
            if pieceCount = 4 then
                win = 1
            end if
            
        next k
    next i
    
    for j as integer = 0 to 5
        for k as integer = 0 to 3
            
            pieceCount = 0
            for i as integer = k to k+3
                if board(i,j)=player then
                    pieceCount = pieceCount + 1
                end if
            next i
            
            if pieceCount = 4 then
                win = 1
            end if
            
        next k
    next j
    
    
    for j as integer = 3 to 5
        for k as integer = 0 to 3
            
            pieceCount = 0            
            for i as integer = 0 to 3
                if board(i+k,j-i)=player then
                    pieceCount = pieceCount + 1
                end if
            next i
            
            if pieceCount = 4 then
                win = 1
            end if
            
        next k
    next j
    
    for j as integer = 0 to 2
        for k as integer = 0 to 3
            
            pieceCount = 0
            for i as integer = 0 to 3
                if board(i+k,j+i)=player then
                    pieceCount = pieceCount + 1
                end if
            next i
            
            if pieceCount = 4 then
                win = 1
            end if
            
        next k
    next j
    
    return win
    
end function


sub playerMove()
    
    selection = -1
    
    while selection = -1
        getmouse mx,my,,mb
        while mb<>1
            getmouse mx,my,,mb
        wend
    
        if mx>40 and mx<367 and my>435 and my<454 then
            selection = ((mx-40)\48)
        end if
        
        while mb=1
            getmouse mx,my,,mb
        wend
        
        
    wend
    
    'if move exists make move and swap players
    if moves(selection).y <>-1 then
        'animated drop
        for y as integer = 0 to moves(selection).y
            board(moves(selection).x,y)=player
            drawBoard()
            sleep 100
            board(moves(selection).x,y)=0
            drawBoard()
            sleep 10
        next y
        
        board(moves(selection).x,moves(selection).y)=player  'insert player piece
        moves(selection).y = moves(selection).y-1
        
        'winning move?
        win = findWin(player)
        
    end if

end sub

sub computerMove()
    dim as integer block   'flag block move
    selection = -1         'no move found
    
    'try each valid move for win
    for i as integer = 0 to 6
        
        if moves(i).y<>-1 then
            'make move
            board(moves(i).x,moves(i).y)=player
            win = findWin(player)  'result in win?
            'score move
            if win = 1 then
                selection = i
            end if
            'undo move
            board(moves(i).x,moves(i).y)=0
        end if

    next i
    
    if selection = -1 then
        'try each valid move for block
        for i as integer = 0 to 6        
            if moves(i).y<>-1 then
                'make move
                board(moves(i).x,moves(i).y)= -player
                block = findWin(-player)  'result in block?
                'score move
                if block = 1 then
                    selection = i
                end if
                'undo move
                board(moves(i).x,moves(i).y)=0
            end if        
        next i
    end if
    
    'if no move found make a random move
    if selection = -1 then  
        selection = int(Rnd(1)*7)
    end if
    
    'make move
    'animated drop
    for y as integer = 0 to moves(selection).y
        board(moves(selection).x,y)=player
        drawBoard()
        sleep 100
        board(moves(selection).x,y)=0
        drawBoard()
        sleep 10
    next y
    
    board(moves(selection).x,moves(selection).y)=player
    moves(selection).y = moves(selection).y-1
    win = findWin(player) 'was that a winning move?
    
end sub

clearBoard()
drawBoard()

randomize timer

player = 1
do
    
    player = -player  'swap players
    drawBoard()
    if winPosition = 0 then
        if player = 1 then
            playerMove()
        else
           computerMove()
        end if
    end if
    drawBoard()
    
loop until key=chr(27) or win = 1

'draw label
line (40,22)-(364,50),rgb(57,89,89),bf
if player = 1 then
    draw string (50,34),"            ORANGE WON                "
end if
if player = -1 then
    draw string (50,34),"            YELLOW WON                "
end if

sleep
Last edited by BasicCoder2 on Oct 13, 2013 9:10, edited 1 time in total.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Another Four-in-a-row

Post by D.J.Peters »

:-)

Code: Select all

randomize timer
player = 1
do
   
    player = -player  'swap players
    drawBoard()
    if winPosition = 0 then
        if player = 1 then
            computerMove()
        else
           computerMove()
        end if
    end if
    drawBoard()
   
loop until key=chr(27) or win = 1

'draw label
line (40,22)-(364,50),rgb(57,89,89),bf
if player = 1 then
    draw string (50,34),"            ORANGE WON                "
end if
if player = -1 then
    draw string (50,34),"            YELLOW WON                "
end if

sleep
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: Another Four-in-a-row

Post by VANYA »

Roland Chastain wrote:It would be much easier to use than the protocols like XBoard or UCI (on my part, I am still unable to use them).
Hi Roland!

That's where I put the work on connecting chess engine on UCI protocol:

http://free-basic.ru/chess_fruit.html
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Another Four-in-a-row

Post by Roland Chastain »

VANYA wrote: Hi Roland!

That's where I put the work on connecting chess engine on UCI protocol:

http://free-basic.ru/chess_fruit.html
Great! I didn't remember that you have made that. I will look at it. Thank you, VANYA!
Last edited by Roland Chastain on Apr 12, 2015 5:31, edited 1 time in total.
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Another Four-in-a-row

Post by Roland Chastain »

Hello!

There is a new version.The main difference is that you can choose between two opponents, the simple engine that I had made for the first version (just changed to a dynamic library) and Velena, a program which plays connect-four perfectly (also changed to a dynamic library).

The original source code of the engine is here:
Velena Engine Source Code

The DLL source code is here (it is compiled with MinGW-GCC):
<link removed>

And the new version of the game is still here:
Four-in-a-row
Last edited by Roland Chastain on May 06, 2018 11:33, edited 2 times in total.
VANYA
Posts: 1834
Joined: Oct 24, 2010 15:16
Location: Ярославль
Contact:

Re: Another Four-in-a-row

Post by VANYA »

Roland Chastain wrote:Hello!

There is a new version.The main difference is that you can choose between two opponents, the simple engine that I had made for the first version (just changed to a dynamic library) and Velena, a program which plays connect-four perfectly (also changed to a dynamic library).

The original source code of the engine is here:
Velena Engine Source Code

The DLL source code is here (it is compiled with MinGW-GCC):
Dynamic Library Source Code

And the new version of the game is still here:
Four-in-a-row
Hi Roland! The game is an excellent!
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Another Four-in-a-row

Post by Roland Chastain »

@VANYA

Thank you. Glad that you like it.
FB_Numpty
Posts: 33
Joined: Jan 28, 2014 19:22

Re: Another Four-in-a-row

Post by FB_Numpty »

Hi Roland

Many thanks - this is an excellent piece of work - love the gui and it is great to be able to use Velena again.

I played a cheeky couple of games with my own console based engine:

Code: Select all

****** L I N X 1.0 ******

  1   2   3   4   5   6   7
  ------------------------- 
  O   O   -   O   X   X   X 
 ==========================
  X   X   X   X   X   O   O 
 ==========================
  O   X   O   O   O   X   X 
 ==========================
  X   O   X   X   X   O   O 
 ==========================
  O   X   X   O   O   X   X 
 ==========================
  O   O   O   X   X   O   O 
 ==========================

---------------------------

D1 d2 D3 d4 D5 b1 B2 b3 B4 f1 F2 f3 F4 f5 B5 d6 F6 b6 E1 e2 E3 e4 E5 c1 E6 g1 C2 a1 C3 a2 A3 a4 A5 a6 G2 g3 G4 g5 G6 c4 C5  1-0 

White: Linx (Hard)
Black: Velena
The game against Toy Engine (below) showed a bug - if you play through the game, after Linx wins Toy Engine carries on and plays the next white move and claims a win in C5 (ie column 3)! ( seems to be a bug related to game end detection)

Code: Select all


  ****** L I N X 1.0 ******

  1   2   3   4   5   6   7
  ------------------------- 
  X   O   -   X   X   O   - 
 ==========================
  O   O   -   O   X   X   - 
 ==========================
  X   X   O   O   O   O   - 
 ==========================
  X   O   X   X   O   X   - 
 ==========================
  O   X   O   O   X   O   O 
 ==========================
  X   O   X   X   O   X   X 
 ==========================

---------------------------

D1 b1 B2 b3 B4 d2 D3 d4 F1 e1 E2 e3 C1 e4 E5 f2 G1 d5 D6 b5 F3 c2 E6 b6 A1 a2 A3 f4 A4 a5 F5 f6 A6 g2 C3 c4  0-1 

White: Toy Engine
Black: Linx (Average)
I'm still working on my program but might see if I can hook it up to the gui - if you can give me an tips or advice.

Thanks again for the excellent implementation!
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Another Four-in-a-row

Post by Roland Chastain »

@FB_Numpty

Thank you for that very interesting contribution.

The bug that you reported is fixed (please download the new files here).

Your engine looks great! I downloaded it here and will study it.

It will be easy to hook your engine up to the GUI, whether as a command-line executable or as a DLL (if ever you like that idea). I would be glad to help.

For your information, here is the protocol used by Velena. Velena is called with one argument, a string beginning with "a", "b", or "c" (weak, normal, strong) and ending with "0". In the middle, the sequence of moves already played, e.g. "44442" (equivalent of "D1 d2 D3 d4 D5 b1"). The return value is the column as an integer from 1 to 7, or a negative error code.
FB_Numpty
Posts: 33
Joined: Jan 28, 2014 19:22

Re: Another Four-in-a-row

Post by FB_Numpty »

Roland Chastain wrote:@FB_Numpty
The bug that you reported is fixed (please download the new files here).
Great, thanks for fixing so quickly - downloaded!
Your engine looks great! I downloaded it here and will study it.
Thanks, though this is a very old version from FB 0.15 - and the eval is buggy. It isn't the version that played the games I posted - I should really take it down. If you want something more recent I can email you the latest development version which is stronger and has bit more functionality (eg save game option)
It will be easy to hook your engine up to the GUI, whether as a command-line executable or as a DLL (if ever you like that idea). I would be glad to help.

For your information, here is the protocol used by Velena. Velena is called with one argument, a string beginning with "a", "b", or "c" (weak, normal, strong) and ending with "0". In the middle, the sequence of moves already played, e.g. "44442" (equivalent of "D1 d2 D3 d4 D5 b1"). The return value is the column as an integer from 1 to 7, or a negative error code.
Yes, would be very grateful for your help with this - thank you! - I will need it.
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Another Four-in-a-row

Post by Roland Chastain »

FB_Numpty wrote:If you want something more recent I can email you the latest development version which is stronger and has bit more functionality (eg save game option)
Yes, I would like to see it.
Post Reply