@Abi79, you've gotten to pick the last few. I'm letting Blood-piggy choose. (Besides, he was first.) If no-one steps up after this one, then you're in the queue.
Cell Life
A Google search for
John Conway's Game of life will provide more information on this than you ever wanted to know. (
Wiki is also a good source)
Without taking up too much space, John Conway came up with a game that seems simple but in the end has proven to be the playground for the intelectual. The game is played on a grid, like a checker board. Markers are placed on the board. Then every "generation" the pieces live, die, or are born according to a simple set of rules:
- A marker dies of lonelyness if it only has one or no neighbors.
- A marker dies of overcrowing if it has neighbors on 5 or more sides.
- Markers with two or three neighbors survive to the next generation.
- A marker is born if an empty spot has exactly 3 neighbors.
In this program an attempt was made as giving ownership to the pieces so that two, three or four player games could be realized. So the last rule was modified thus
- A marker is born when if an empty spot has exactly 3 neighbors. If at least two neighbors are the same type then the marker will be of that type. If no two neighbors are the same then a hybred is created.
In this game markers are called "cells" to give it an organic feel. To add an even more competitive edge to it, every generation players get to place one marker on the board to sway the game in their favor. The game is only won (at this time) with a 100% purging of the enemy cels. Thus games could potentially go on for a long time.
Here's a screenshot of a small three player game in action:
Code:
**12345
1..@X.1
2**OOX2
3*..X.3
4...*.4
5.....5
**12345
Press ENTER to advance the generation:
Here's a large 4 player game (1 players already been elimitedy by now) in action:
Code:
************111111111122222
**1234567890123456789012345
1........***..............1
2.........................2
3.......*..*..............3
4........*..*.............4
5.........**..............5
6.........................6
7.........................7
8.........................8
9............*............9
10..........XOX*...........10
11........XX...X...........11
12..........X..XX..........12
13........OX..XX...........13
14........O..XX............14
15..........XX.............15
16.........@...............16
17..........*O.............17
18..........*O.............18
**1234567890123456789012345
************111111111122222
Press ENTER to advance the generation:
I chose both screen shots because a hybred (@) had entered into the game.
Winning this game is a challange. Every turn the players rotate through who goes first. Going first is not an advantage because it's all to easy for your opponent to turn a birth into an overcrowing after they've seen what you're doing. However, this was the only way to insure that the game is played fair since, in this form, having everyone choose their move unseen isn't possible. Both methods have their advantages.
You can set the game for 4 computer players and just watch it go. This in and of itself is not uninteresting to see. But if you can master predicting the next generation just feel your brain grow.
Silly me, I haven't given you the code yet!
Code:
/* Cell Life
* by Joseph Larson
* based on a 2 player BASIC game by Bryan Wyvill
* as found in 'BASIC Computer Games' edited by David H Ahl (c) 1978
* which game was derived from John Conway's Game of Life
* as found in Scientific America, October 1970
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define F(a,b) for (a = 0; a < (b); a++)
#define DIG v * tp(5) + w * tp(4) + x * tp(3) + y * 100 + z * 10
#define TURN ((c + f + g) % players)
#define MAX_W 26
#define MAX_H 19
#define PIECES 3
int bd[MAX_W][MAX_H], dis[8][2], pop[5], surv[5][55], hyb[10];
int height, width, players;
char tokens[6] = ".OX*#@";
void intro (void) {
**printf ("Cell Life\n---------\n\n"
**"The rules of this game are based on Conway's Game of Life. Tokens are\n"
**"placed on the board, then with every generation a token will live, die, or\n"
**"be born based on these rules :"
**" o A token with 2 or 3 neighbors survives.\n"
**" o A token with more or less than 2 or 3 neighbors dies from lonelyness or\n"
**"** overpopulation.\n"
**" o An empty space with exactly 3 neighbors gives birth to a new token.\n\n"
**"When giving birth the player with the majority of the 3 neighbors of an\n"
**"empty cell gets the new cell. If no one has the majority (in the case of\n"
**"a 3 way tie) the cell becomes a hybred that no one controls.\n"
**"Remember to count the number of neighbors same as in minesweeper. In other\n"
**"words a cell can have up to 8 neighbors.\n\n"
**"The first three moves (Generation 0) are when you place your initial\n"
**"pieces.\n\n"
**"Remember to pay close attention to who's turn it is as every turn a\n"
**"different player gets to go first.\n\n"
**"Good Luck.\n\n");
}
int tp (int x) {return ((x == 0) ? 1 : 10 * tp (x - 1)); }
void init (void) {
**int p, v, w, x, y, z, c, i, sum;
**srand (time (NULL));
**F(p, 5) {
****i**= 0;
****F(v, 4) F(w, 4) F(x, 4) F(y, 4) F(z, 4) {
******sum = v + w + x + y + z;
******if (sum == 3 || sum == 2) surv[p][i++] = (p + 1) + DIG;
******else if (sum == 1)
********surv[p][i++] = DIG + 2 * tp(p + 1);
****}
**}
**i = 0;
**F(v, 2) F(w, 2) F(x, 2) F(y, 2) F(z, 2) {
****sum = v + w + x + y + z;
****if (sum == 3) hyb[i++] = DIG;
**}
**i = 0;
**F (x, 3) F (y, 3) if (!(x == y && y == 1)) {
****dis[i][0] = x - 1; dis[i++][1] = y - 1;
**}
}
void print_bd (void) {
**int x, y;
**printf ("**"); /* 2 spaces */
**F (x, width) putchar (" 12"[x / 10]);
**putchar ('\n');
**F (y, (height + 2))
****F (x, (width + 2))
******(!y || y > height) ? (!x) ? printf ("**") /* 2 spaces */
******: putchar ((x > width) ? '\n' : '0' + (x % 10))
******: (!x) ? printf ("%2d", y) : (x > width) ? printf ("%-2d\n", y)
******: putchar (tokens [bd[x][y] % 10]);
**printf ("**"); /* 2 spaces */
**F (x, width) putchar (" 1234"[x / 10]); putchar ('\n');
}
int survives (int x) {
**int k, p;
**F (p, 5) F(k, 55) if (surv[p][k] == x) return p + 1;
**F (k, 10) if (hyb[k] == x) return 5;
**return 0;
}
void generation (void) {
**int x, y, k, p;
**F (x, width + 1) F (y, height + 1) if (p = (bd[x][y] % 10))
****F (k, 8) bd[x + dis[k][0]][y + dis[k][1]] += tp (p);
**F (k, 5) pop[k] = 0;
**F (x, width + 2) F (y, height + 2)
****if (!y || y > height || !x || x > width) bd[x][y] = 0;
****else {
******bd[x][y] = survives (bd[x][y]);
******if (bd[x][y]) pop[bd[x][y] - 1]++;
****}
}
void getxy (int *x, int *y) {
**printf ("<X,Y>: ");
**scanf ("%d %*c %d", x, y);
**while (*x > width || *x < 1 || *y > height || *y < 1) {
****printf ("Invalad location. Retry. x,y : ");
****scanf ("%d %*c %d", x, y);
**}
}
void compyturn (int p, int g) {
**int x, y, c, d, bestx, besty, r, bestr, k;
**int bdc[MAX_W][MAX_H], popc[5];
**if (g <= PIECES) if (g == 1) {
****bestx = rand() % (width - 1) + 1;
****besty = rand() % (width - 1) + 1;
**} else {
****F (x, width) F (y, width) if (bd[x][y] == (p + 1)) {bestx = x; besty = y;}
****r = 0;
****do {
******k = rand () % 8;
******if (bd[bestx + dis[k][0]][besty + dis[k][1]]) k = -1;
******else if ((bestx + dis[k][0]) > width || (bestx + dis[k][0]) < 1) k = -1;
******else if ((besty + dis[k][1]) > height || (besty + dis[k][1]) < 1) k = -1;
****** r |= 1 << k;
****} while (k < 0 && r < 255);
****if (k < 0) {
******bestx = rand() % (width - 1) + 1; besty = rand() % (width - 1) + 1;
****} else { bestx += dis[k][0]; besty += dis[k][1]; }
**} else {
****F (c, height + 1) F (d, width + 1) bdc[c][d] = bd[c][d];
****F (k, 5) popc[k] = pop[k];
****bestx = rand() % (width - 1) + 1;
****besty = rand() % (width - 1) + 1;
****bestr = -99;
****F (y, height - 1) F (x, width - 1) if (!bd[x + 1][y + 1]) {
******bd[x + 1][y + 1] = p + 1;
******generation ();
******r = 0;
******F (k, 5) if (k == p) r += pop[k]; else r -= pop[k];
******if (r > bestr) {bestr = r; bestx = x + 1; besty = y + 1;}
******F (c, height + 1) F (d, width + 1) bd[c][d] = bdc[c][d];
******F (k, 5) pop[k] = popc[k];
****}
**}
**bd[bestx][besty] = p + 1;
**printf ("Computer Player %d (%c) : %d, %d\n", p + 1, tokens[p + 1], bestx, besty);
}
int winner (void) {
**int c, w = 0;
**F (c, players) if (pop[c]) if (w) return 0; else w = c + 1;
**return (w) ? w : 5;
}
int getint (int low, int high) {
**int t;
**scanf ("%d", &t);
**while (t < low || t > high) {
****printf ("Invalad. Choose a number between %d and %d : ", low, high);
****scanf ("%d", &t);
**}
**return t;
}
void play (void) {
**int c, d, f, x, y, comp[4], g = 0;
**printf ("How many players? (2 - 4) ");
**players = getint (2, 4);
**F(c, players) {
****printf ("Player %d, (1) human or (2) computer? : ", c + 1);
****comp[c] = getint (1, 2) - 1;
**}
**printf ("(1) Small or (2) large game? ");
**c = getint(1, 2);
**width = (--c) ? MAX_W - 1 : 5;
**height = (c) ? MAX_H - 1 : 5;
**f = rand() % players;
**printf ("Each player gets %d pieces to play.\n", PIECES);
**F (c, players) pop[c] = 1;
**do {
****g++;
****F (c, players) {
******if (pop[TURN]) {
********print_bd ();
********if (!comp[TURN]) {
**********printf ("Generation %d, player %d (%c) ", (g < PIECES) ? 0 : g - PIECES
************, TURN + 1, tokens[TURN + 1]);
**********getxy (&x, &y);
**********if (bd[x][y]) printf ("Occupied. Turn discarded.\n");
**********else bd[x][y] = TURN + 1;
********} else compyturn (TURN, g);
******}
****}
****if (g >= PIECES) {
******print_bd ();
******printf ("\nPress ENTER to advance the generation:\n");
******getchar (); getchar ();
******generation ();
****}
**} while ((g < 0) || !(d = winner ()));
**print_bd();
**printf ((d == 5) ? "\n\nTotal extinction." :
****(d == 4) ? "\n\nHybred takeover!" : "\n\nPlayer %d wins!", d);
}
int main (void){
**intro ();
**init ();
**play ();
**getchar ();
**exit (0);
}
This particular code bears less resemblance to the BASIC game that inspired it. I've taken many liberties with it, but for those who are interested you can see the original
here. The BASIC game is surprisingly compact, but at the same time not as robust as this program.
This is a game that would probably be better suited to something more graphical. In this form it's a bit hard to play. But then again, if you're the sort of person for whom Conway's Game of Life holds your interest something like console graphics is no turn off.
Abi put in a vote for Battleship next, and since i love my regurar reader (wish I could put an 's' there) that'll probably be next, but feel free to queue up your preference :
- Battleship (like the board game vs the computer)
- Reverse (order a list of number by turning them around)
- Black Box (find molecules in the inky depths)
- Acey Deucy (a card game of highs, lows, and middles)
- Flash Cards (with pretty output, practice your math)
- Pickup Piles (1000 games in one, set the rules and play)
- Hangman (guess the word before you dangle)
- Rotate (like those sliding block puzzles but that you rotate pieces)