Connect 4 - That's right...it has claws

Cornell Project | Expansion Board Interface | Command Encoding
Cornell Project | MIT Handler | EECS 270 Lab
Manufacturer's Spec | HITACHI Spec | Umich Helpful Hints
subglobal4 link | subglobal4 link | subglobal4 link | subglobal4 link | subglobal4 link | subglobal4 link | subglobal4 link
subglobal5 link | subglobal5 link | subglobal5 link | subglobal5 link | subglobal5 link | subglobal5 link | subglobal5 link
subglobal6 link | subglobal6 link | subglobal6 link | subglobal6 link | subglobal6 link | subglobal6 link | subglobal6 link
subglobal7 link | subglobal7 link | subglobal7 link | subglobal7 link | subglobal7 link | subglobal7 link | subglobal7 link
subglobal8 link | subglobal8 link | subglobal8 link | subglobal8 link | subglobal8 link | subglobal8 link | subglobal8 link

Two Player Interactive Connect 4 by Neil Zieses & Andrew Cramer

The software component of the project began as a way of internally storing the connect 4 board in memory, replicating the information that was seen on the LCD display. To accomplish this, we created a two-dimensional array that was initially declared to 0. As pieces from each player were dropped, we needed to store the location of the piece as representative of whos piece it was. We stored -1 for player 1 and 1 for player 2. This method of storage made the next piece of development easier.

We realized that we needed an algorithm that would perpetually check the game board and see if any possible winning set of locations was equal to -4 or 4(indicating that all four spots were occupied by pieces from the same player). This proved easy for the column and rows, since a loop through the board would allow us to check for winning combinations. However, for the diagonals, we decided it would be easier to hardcode the locations that needed to be checked.

While continuously checking the board would lead to the desired result if a player won, it didn't allow us to check if the game was a tie. To correct this, we created a function that would check the number of empty spots on the board after each turn. If at any time, the spots left equaled 0, and the algorithm to determine a winner failed, the game knew it was a tie and displayed on the screen that a tie had occured.

Once the internal structure of the game was written, we had to decide where we wanted our ASM code to stop and our C code to begin. This became easy, since the writing of the graphics to the display was dependant on a loop that could be written in C, but interfacing with the LCD had to be done in assembly. Most of our ASM functions set up the pointers to the correct memory locations on the LCD and then went into a C loop where it is continually written one byte at a time from a C array.

We began interacting with the screen in an ASM function. At the highest level, it was basically a series of resets and status checks that were required to initialize the screen and its internal memory, and also formally turn the screen on. We also had to perform the status checks before writing to the screen at every step. The majority of our screen interactions, however, were done in C.

Since the movement of graphics on the screen depended on turning specific bits on and off on the LCD, we determined it would be easier to represent the entire memory array of the screen as an array in C, and then subsequently rewrite each byte to the LCD at each iteration of the program. To build these arrays in C, we made a separate instance for each column and the claws. At each turn, we would move the specific pixels within each of these arrays and then build the larger graphics array out of them. The difficulty of going from the pixel representations to the bytre represetations was sovled with the use of a C function we wrote that would collect 6 bits at a time from each of the column and/or claw arrays and evaluate them into an integer value that could be placed in the graphics array. We would then conclude by refreshing the entire screen at once.

Now that the entire graphics system worked, we were faced with coding for timers, interrupts and the controllers. Choosing to use the MPC823 timers was an obvious choice, since we needed to count down until the next piece was available to be dropped. Using the processor ensured consistent timing and was more efficient than developing our own hardware to do the task. Using the processor's timers was also more desirable than using a software timer that was based upon counting to a certain value and then looping. In software, incrementing that value was dependent upon how often interrupts occured, and as such we would have been unable to determine a consistent reference value to indicate that a second had passed.

Our interrupts are clearly defined in our hardware section, occuring from the timers and the controllers. The controller interrupt was generated on the falling edge of a ~60 Hz clock. When this occured, an interrupt was generated in IRQ1. The first time this interrupt occured after the program started, the data read back was anlyzed to determine the ype of controller in each port. This data defined where subsequent reads came from throughout the game. We ended up modifying some of our software to only allow this interrupt to occur at every 5th instance to allow for faster gameplay. We also ended up with a vote scheme that required a button be pressed for three out of five cycles before registering it as pressed. The data was sent to a C function to be analyzed and the proper action was then performed, whether it was dropping a piece, resetting the game, or changing the speed of a claw. Each time a piece was dropped, it called a function that enabled a timer, timer 1 for player 1 and timer 2 for player 2. It also changed one of two global variables (one for each player) indicating the amount of time left to 10.

The timers were pre-programmed in the driver to be enabled to count to a value that approximated a half-second. As a result, when a piece was dropped, one bit had to be written to enable a timer to begin counting. At every intance that the reference value was reached, the global variable indicating the amount of time left was decremented, and after this the variable was compared to zero. A value of zero caused the timer to be disabled and the player to be once again enabled to drop a piece.

Contact Us | ©2006 Crames & Zieses Inc.