
****************************************************************************
**                                                                        **
**                               You Loose                                **
**                                                                        **
**                              Version 1.0                               **
**                                                                        **
**                              By Jan Maes                               **
**                     (jan.maes1@student.kuleuven.ac.be)                 **
**                                                                        **
**                    Copyright (c) 2001 by Jam Productions               **
**                                                                        **
**                 more games at http://surf.to/JamProductions            **
**                                                                        **
****************************************************************************



How to Play ?
-------------

You play against the computer. 
You place red disks, the computer places the yellow disks. 
The aim is to be the first to place four disks in a row (if you 
play with the default options). 
Horizontal, vertical, and diagonal lines are valid. 
Use your mouse to position a disk at the top of the column where you want a disk to go. 

Enjoy! 





The Algorithm  (by Keith Pomakis)
---------------------------------

****************************************************************************
**                                                                        **
**                          Connect-4 Algorithm                           **
**                                                                        **
**                              Version 3.7                               **
**                                                                        **
**                            By Keith Pomakis                            **
**                          (pomakis@pobox.com)                           **
**                                                                        **
**                               May, 2000                                **
**                                                                        **
****************************************************************************

All array indexes are zero-based.

Global variables:

              x = the board width.

              y = the board height.

              n = the number to connect.

       level[2] = the skill level of the computer players, where applicable.

    board[x][y] = the board, where board[i][j] contains the value:
                        0 if player 0 occupies position i,j
                        1 if player 1 occupies position i,j
                        C4_NONE if neither player occupies position i,j.

              z = the number of possible n-in-a-row areas on the board
                  in which a winning connection can be made.  This equals:
                        4*x*y - 3*x*n - 3*y*n + 3*x + 3*y - 4*n + 2*n*n + 2.

                  Each n-in-a-row area on the board in which a winning
                  connection can be made is given a unique number from 0 to
                  z-1.  Each space on the board is told which n-in-a-row
                  areas it is part of.  This is done with the array...
                  
      map[x][y] = an array in which each element is a list specifying, for
                  each corresponding board space, which n-in-a-row areas
                  it is part of.

    stats[2][z] = an array containing statistics of each player.  Statistics
                  for player 0 are contained in stats[0], while statistics
                  for player 1 are contained in stats[1].  stats[a][b] will
                  contain 0 if the n-in-a-row area b is no longer a
                  winning possibility for player a.  Otherwise it will
                  contain 2^p, where p is the number of pieces player a has
                  in this area.

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

Upper-level Algorithm:

    set up map[][] array
    set every element in board[][] to C4_NONE
    set every element in stats[][] to 1
    set player to either 0 or 1

    while game is not over
        col = get_desired_col(player)
        drop_piece(player, col)

        if is_winner(player) or is_tie()
            game is over
        endif

        player = 1 - player
    endwhile

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

get_desired_col(player):
    if player is human
        return number from user interface
    else
        return best_move(player, level[player])
    endif

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

best_move(player, depth):  /* recursive! */
    minimax search of possible future board states, using alpha-beta
    cutoff techniques to limit unnecessary searches.  Look up these
    techniques in any AI book.  The "goodness" of a board state at any
    point in time, from the point of view of the current player, is equal to
    score(player) - score(1-player), where score(p) = sum of stats[p].

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

drop_piece(player, col):
    row = row the token will end up in after falling down the column
    board[col][row] = player
    for each element q in map[col][row]
        stats[player][q] = stats[player][q] * 2
        stats[1-player][q] = 0
    endfor

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

is_winner(player):
    for each element s in stats[player]
        if s = 2^n then return TRUE
    endfor
    return FALSE

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

is_tie():
    if no element of board[][] is C4_NONE
        return TRUE
    else
        return FALSE
    endif

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

sample map[x][y] for x = 7, y = 6, and n = 4:

    +---------+---------+---------+---------+---------+---------+---------+
    |20,26,59 |20,21,29,|20,21,22,|20,21,22,|21,22,23,|22,23,41,|23,44,56 |
    |         |62       |32,65    |23,35,47,|38,50    |53       |         |
  5 |         |         |         |68       |         |         |         |
    |         |         |         |         |         |         |         |
    |         |         |         |         |         |         |         |
    +---------+---------+---------+---------+---------+---------+---------+
    |16,25,26,|16,17,28,|16,17,18,|16,17,18,|17,18,19,|18,19,40,|19,43,44,|
    |58       |29,59,61 |31,32,47,|19,34,35,|37,38,49,|41,52,56 |55       |
  4 |         |         |62,64    |46,50,65,|53,68    |         |         |
    |         |         |         |67       |         |         |         |
    |         |         |         |         |         |         |         |
    +---------+---------+---------+---------+---------+---------+---------+
    |12,24,25,|12,13,27,|12,13,14,|12,13,14,|13,14,15,|14,15,39,|15,42,43,|
    |26,57    |28,29,47,|30,31,32,|15,33,34,|36,37,38,|40,41,51,|44,54    |
  3 |         |58,60    |46,50,59,|35,45,49,|48,52,56,|55,68    |         |
    |         |         |61,63    |53,62,64,|65,67    |         |         |
    |         |         |         |66       |         |         |         |
    +---------+---------+---------+---------+---------+---------+---------+
    |8,24,25, |8,9,27,  |8,9,10,  |8,9,10,  |9,10,11, |10,11,39,|11,42,43,|
    |26,47    |28,29,46,|30,31,32,|11,33,34,|36,37,38,|40,41,54,|44,68    |
  2 |         |50,57    |45,49,53,|35,48,52,|51,55,62,|65,67    |         |
    |         |         |58,60    |56,59,61,|64,66    |         |         |
    |         |         |         |63       |         |         |         |
    +---------+---------+---------+---------+---------+---------+---------+
    |4,24,25, |4,5,27,  |4,5,6,30,|4,5,6,7, |5,6,7,36,|6,7,39,  |7,42,43, |
    |46       |28,45,49 |31,48,52,|33,34,51,|37,54,61,|40,64,66 |67       |
  1 |         |         |57       |55,58,60 |63       |         |         |
    |         |         |         |         |         |         |         |
    |         |         |         |         |         |         |         |
    +---------+---------+---------+---------+---------+---------+---------+
    |0,24,45  |0,1,27,  |0,1,2,30,|0,1,2,3, |1,2,3,36,|2,3,39,63|3,42,66  |
    |         |48       |51       |33,54,57 |60       |         |         |
  0 |         |         |         |         |         |         |         |
    |         |         |         |         |         |         |         |
    |         |         |         |         |         |         |         |
    +---------+---------+---------+---------+---------+---------+---------+

         0         1         2         3         4         5         6

 0 - 23: horizontal wins
24 - 44: vertical wins
45 - 56: forward diagonal wins
57 - 68: backward diagonal wins

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

The sample map that I show above is just to show what the map[x][y]
array should look like for a 7x6 board of Connect-4 (even though it's
usually filled in dynamically using a few iterative loops).  The numbers
in this array are labels on the winnable n-in-a-row areas of the board.
This is useful so that when a piece is dropped into an arbitrary board
position, the algorithm can determine very quickly which n-in-a-row
areas have become more likely destined for a win for the player, and, as
importantly, which n-in-a-row areas are no longer possibilities for the
opposing player.  The numbers in the map[x][y] array are indexes into a
pair of parallel single-dimensional arrays which keep track of how likely
each n-in-a-row area is to be the winning area for each player.  I call
this the stats array.  The "score" of a player is merely the sum of the
stats array of the player.  Subtracting one score from another determines
how well a player is doing relative to the opposing player.  You throw
these numbers into your general run-of-the mill minimax algorithm, throw
in some alpha-beta cutoff logic for efficiency, and that, in a nutshell,
is the secret to my algorithm.



