diff -u gtklife-4.0/Makefile gtklife-4.0-battle/Makefile
--- gtklife-4.0/Makefile	2004-08-18 22:12:17.000000000 -0600
+++ gtklife-4.0-battle/Makefile	2004-12-19 22:38:43.148578976 -0700
@@ -10,14 +10,18 @@
 DOCDIR=$(PREFIX)/doc/gtklife
 
 # Optimization and debug flags
-CFLAGS=-O3 -mpentiumpro -Wall # -g
+CFLAGS=-O3 -mcpu=athlon -Wall -g
 
 ########## No user-serviceable parts below ##########
 
 CPPFLAGS=`gtk-config --cflags` -DDATADIR=\"$(DATADIR)\" -DDOCDIR=\"$(DOCDIR)\"
 LDFLAGS=`gtk-config --libs`
 
-OBJS=gtklife.o life.o loadsave.o ewmh.o util.o icons.o ul_lookup.o ur_lookup.o ll_lookup.o lr_lookup.o
+OBJS=gtklife.o life.o loadsave.o ewmh.o util.o icons.o \
+	conway_ul_lookup.o conway_ur_lookup.o \
+	conway_ll_lookup.o conway_lr_lookup.o \
+	takeover_ul_lookup.o takeover_ur_lookup.o \
+	takeover_ll_lookup.o takeover_lr_lookup.o
 CL_OBJS=create_lookup.o util.o
 
 # Targets
@@ -42,18 +46,27 @@
 	$(CC) -o create_lookup $(CL_OBJS)
 
 clean:
-	rm -f gtklife create_lookup [ul][lr]_lookup.c *.o
+	rm -f gtklife create_lookup *.o
+	rm -f conway_[ul][lr]_lookup.c takeover_[ul][lr]_lookup.c
 
 # Generated source files
 
-ul_lookup.c: create_lookup
-	./create_lookup ul
-ur_lookup.c: create_lookup
-	./create_lookup ur
-ll_lookup.c: create_lookup
-	./create_lookup ll
-lr_lookup.c: create_lookup
-	./create_lookup lr
+conway_ul_lookup.c: create_lookup
+	./create_lookup conway ul
+conway_ur_lookup.c: create_lookup
+	./create_lookup conway ur
+conway_ll_lookup.c: create_lookup
+	./create_lookup conway ll
+conway_lr_lookup.c: create_lookup
+	./create_lookup conway lr
+takeover_ul_lookup.c: create_lookup
+	./create_lookup takeover ul
+takeover_ur_lookup.c: create_lookup
+	./create_lookup takeover ur
+takeover_ll_lookup.c: create_lookup
+	./create_lookup takeover ll
+takeover_lr_lookup.c: create_lookup
+	./create_lookup takeover lr
 
 # Dependencies
 
diff -u gtklife-4.0/create_lookup.c gtklife-4.0-battle/create_lookup.c
--- gtklife-4.0/create_lookup.c	2003-07-21 23:29:23.000000000 -0600
+++ gtklife-4.0-battle/create_lookup.c	2004-12-19 17:14:33.364395608 -0700
@@ -1,9 +1,12 @@
-/* create_lookup: Output contents of a lookup table for a 4x4 block in Conway's Life.
- * Usage: create_lookup <template name>, where <template name> is ul, ur, ll, or lr,
- * specifying which corner this lookup is for and thus how the bits are arranged.
- * The 2x2 lookup result will be placed in the appropriate bits for each corner
- * (ul: 0,1,4,5, ur: 2,3,6,7, ll: 8,9,12,13, lr: 10,11,14,15). Therefore the lookup
- * tables for ll and lr will have 16 bit entries. All extra bits are set to 0.
+/* create_lookup: Output contents of a lookup table for a 4x4 block in
+ * Conway's Life.  Usage: create_lookup <rule> <quadrant>, where
+ * <rule> is the name of a rule set ("conway" and "takeover" are supported)
+ * and <quadrant> is ul, ur, ll, or lr, specifying which corner
+ * this lookup is for and thus how the bits are arranged.  The 2x2
+ * lookup result will be placed in the appropriate bits for each
+ * corner (ul: 0,1,4,5, ur: 2,3,6,7, ll: 8,9,12,13, lr:
+ * 10,11,14,15). Therefore the lookup tables for ll and lr will have
+ * 16 bit entries. All extra bits are set to 0.
  */
 
 #include <stdio.h>
@@ -39,25 +42,53 @@
     }
 };
 
+int conway_rule(int cell_state, int neighbors) {
+    if (!cell_state && neighbors == 3)
+        return 1;
+    else if (cell_state && neighbors != 2 && neighbors != 3)
+        return 0;
+    else
+        return cell_state;
+}
+
+int takeover_rule(int cell_state, int neighbors) {
+    if (neighbors == 2 || neighbors == 3)
+        return 1;
+    else
+        return 0;
+}
+
 int main(int argc, char* argv[])
 {
     int i;
+    rule_func rule;
 
     set_prog_name(PROG);
-    if (argc != 2)
+    if (argc != 3)
         usage_abort();
     for (i=0; i < NUM_TEMPLATES; i++) {
-        if (STR_EQUAL(argv[1], templates[i].name))
+        if (STR_EQUAL(argv[2], templates[i].quadrant))
             break;
     }
-    if (i == NUM_TEMPLATES)
+    if (i == NUM_TEMPLATES) {
         usage_abort();
-    process(argv[1], &templates[i]);
+        return 1;
+    }
+    if (STR_EQUAL(argv[1], "conway"))
+        rule = conway_rule;
+    else if (STR_EQUAL(argv[1], "takeover"))
+        rule = takeover_rule;
+    else {
+        usage_abort();
+        return 1;
+    }
+    process(argv[2], &templates[i], argv[1], rule);
 
     return 0;
 }
 
-void process(const char* name, template_type* template)
+void process(const char* quadrant, template_type* template,
+             const char *rule_name, rule_func rule)
 {
     FILE*        f;
     int          shiftage;
@@ -81,12 +112,12 @@
     field_len = strlen(temp);
     num_cols = 75 / (field_len + 2);
 
-    sprintf(temp, "%s_lookup.c", name);
+    sprintf(temp, "%s_%s_lookup.c", rule_name, quadrant);
     f = fopen(temp, "w");
     if (!f)
         sys_error_abort("can't open %s for writing", temp);
     fprintf(f, "#include \"util.h\"\n\n");
-    fprintf(f, "%s %s_lookup[0x10000] = {\n", result_type, name);
+    fprintf(f, "%s %s_%s_lookup[0x10000] = {\n", result_type, rule_name, quadrant);
 
     col = 0;
     for (i=0; i < 0x10000; i++) {
@@ -103,10 +134,7 @@
             for (k=1; k <= 2; k++) {
                 neighbors = cage[j-1][k] + cage[j+1][k] + cage[j][k-1] + cage[j][k+1] +
                     cage[j-1][k-1] + cage[j-1][k+1] + cage[j+1][k-1] + cage[j+1][k+1];
-                if (!cage[j][k] && neighbors == 3)
-                    ncage[j][k] = 1;
-                else if (cage[j][k] && neighbors != 2 && neighbors != 3)
-                    ncage[j][k] = 0;
+                ncage[j][k] = rule(cage[j][k], neighbors);
             }
         }
         result = (ncage[1][1]) + (ncage[1][2] << 1) + (ncage[2][1] << 4) +
@@ -132,6 +160,6 @@
 
 void usage_abort(void)
 {
-    fprintf(stderr, "Usage: create_lookup <ul|ur|ll|lr>\n");
+    fprintf(stderr, "Usage: create_lookup <conway|takeover> <ul|ur|ll|lr>\n");
     exit(1);
 }
diff -u gtklife-4.0/create_lookup.h gtklife-4.0-battle/create_lookup.h
--- gtklife-4.0/create_lookup.h	2003-07-21 23:29:23.000000000 -0600
+++ gtklife-4.0-battle/create_lookup.h	2004-12-19 17:14:33.365395456 -0700
@@ -6,12 +6,15 @@
 enum {NW, NE, SW, SE, NUM_TEMPLATES};
 
 typedef struct template_struct {
-    const char*  name;
+    const char*  quadrant;
     int          shiftage;
     int          bits[4][4];
 } template_type;
 
-void process(const char* name, template_type* template);
+typedef int (*rule_func)(int, int);
+
+void process(const char* quadrant, template_type* template,
+             const char *rule_name, rule_func rule);
 void usage_abort(void);
 
 #endif
diff -u gtklife-4.0/gtklife.c gtklife-4.0-battle/gtklife.c
--- gtklife-4.0/gtklife.c	2004-08-24 23:11:32.000000000 -0600
+++ gtklife-4.0-battle/gtklife.c	2004-12-19 23:20:45.273157760 -0700
@@ -28,7 +28,7 @@
 
 char* file_format_names[NUM_FORMATS] = {"GLF (GtkLife)", "RLE", "Life 1.05", "Life 1.06", "XLife"};
 char* default_file_extensions[]      = {"glf", "rle", "lif", "l", NULL};
-char* color_names[NUM_COLORS]        = {"background", "live cells", "grid", "selection"};
+char* color_names[NUM_COLORS]        = {"background", "team 0 cells", "grid", "selection", "team 1 cells"};
 
 static command_type  component_toggle_commands[NUM_COMPONENTS] = {
     CMD_VIEW_SHOW_TOOLBAR,
@@ -118,14 +118,17 @@
 
     { "/_Edit",                 0,               0,  0,                         "<Branch>"       },
     { "/Edit/tearoff",          0,               0,  0,                         "<Tearoff>"      },
+    { "/Edit/Draw Team _0",             "A",    H,  CMD_EDIT_TEAM0,              0                },
+    { "/Edit/Draw Team _1",            "B",    H,  CMD_EDIT_TEAM1,             0                },
+    { "/Edit/sep1",             0,               0,  0,                         "<Separator>"    },
     { "/Edit/_Cut",             "<control>X",    H,  CMD_EDIT_CUT,              0                },
     { "/Edit/C_opy",            "<control>C",    H,  CMD_EDIT_COPY,             0                },
     { "/Edit/C_lear",           "<control>D",    H,  CMD_EDIT_CLEAR,            0                },
     { "/Edit/_Paste",           "<control>V",    H,  CMD_EDIT_PASTE,            0                },
     { "/Edit/_Move",            "M",             H,  CMD_EDIT_MOVE,             0                },
-    { "/Edit/sep1",             0,               0,  0,                         "<Separator>"    },
-    { "/Edit/C_ancel Paste",    "<control>G",    H,  CMD_EDIT_CANCEL_PASTE,     0                },
     { "/Edit/sep2",             0,               0,  0,                         "<Separator>"    },
+    { "/Edit/C_ancel Paste",    "<control>G",    H,  CMD_EDIT_CANCEL_PASTE,     0                },
+    { "/Edit/sep3",             0,               0,  0,                         "<Separator>"    },
     { "/Edit/Pre_ferences...",  "P",             H,  CMD_EDIT_PREFERENCES,      0                },
 
     { "/_Run",                  0,               0,  0,                         "<Branch>"       },
@@ -190,6 +193,8 @@
     position_page_sw,
     position_page_se,
 
+    edit_team0,
+    edit_team1,
     edit_cut,
     edit_copy,
     edit_clear,
@@ -231,6 +236,11 @@
 
     {-1,NULL,NULL},
 
+    { CMD_EDIT_TEAM0,    "Draw Team 0",                           team0_icon         },
+    { CMD_EDIT_TEAM1,    "Draw Team 1",                           team1_icon         },
+
+    {-1,NULL,NULL},
+
     { CMD_EDIT_CUT,         "Cut",                           cut_icon         },
     { CMD_EDIT_COPY,        "Copy",                          copy_icon        },
     { CMD_EDIT_PASTE,       "Paste",                         paste_icon       },
@@ -268,7 +278,7 @@
     DEFAULT_ZOOM,
     {DEFAULT_SHOW_TOOLBAR, DEFAULT_SHOW_SIDEBAR, DEFAULT_SHOW_SCROLLBARS, DEFAULT_SHOW_STATUSBAR},
     DEFAULT_FULLSCREEN,
-    {DEFAULT_BG_COLOR, DEFAULT_CELL_COLOR, DEFAULT_GRID_COLOR, DEFAULT_SELECT_COLOR},
+    {DEFAULT_BG_COLOR, DEFAULT_TEAM0_COLOR, DEFAULT_GRID_COLOR, DEFAULT_SELECT_COLOR, DEFAULT_TEAM1_COLOR},
     DEFAULT_SPEED,
     DEFAULT_SPEED_SLIDER_MIN,
     DEFAULT_SPEED_SLIDER_MAX,
@@ -304,6 +314,8 @@
     tracking_mouse_type  tracking_mouse;
     point       hover_point;
     point       last_drawn;
+    int drawing_team;
+    boolean     setting_team;
     rect        selection;
     uint64      selection_start_time;
     cage_type*  copy_buffer;
@@ -370,6 +382,8 @@
     GtkWidget*   status_message_label;
     GtkWidget*   tick_label;
     GtkWidget*   population_label;
+    GtkWidget*   team0_population_label;
+    GtkWidget*   team1_population_label;
     command_widgets_type   command_widgets[NUM_COMMANDS];
 } gui;
 
@@ -577,6 +591,8 @@
 
     state.selection = state.copy_rect = state.paste_box = null_rect;
     state.hover_point = state.last_drawn = null_point;
+    state.drawing_team = 0;
+    state.setting_team = FALSE;
 }
 
 /* Read and apply saved user keybindings
@@ -1182,9 +1198,44 @@
     position_scroll_generic(1, 1, SCROLL_PAGE);
 }
 
+void edit_set_team(int team)
+{
+   GtkToggleButton *t0, *t1;
+
+   if (state.setting_team) {
+       /* Ignore toggle events initiated within this function */
+       return;
+   }
+   state.setting_team = TRUE;
+   t0 = GTK_TOGGLE_BUTTON(gui.command_widgets[CMD_EDIT_TEAM0].toolbar_button);
+   t1 = GTK_TOGGLE_BUTTON(gui.command_widgets[CMD_EDIT_TEAM1].toolbar_button);
+   state.drawing_team = team;
+   draw_default_team = team;
+   gtk_toggle_button_set_active(t0, team == 0);
+   gtk_toggle_button_set_active(t1, team == 1);
+   state.setting_team = FALSE;
+
+    if (!rects_identical(&state.selection, &null_rect)) {
+        /* Change the team within the selection */
+        selection_copy_clear(FALSE, FALSE, team);
+        full_canvas_redraw();
+        update_population_label();
+    }
+}
+
+void edit_team0(void)
+{
+    edit_set_team(0);
+}
+
+void edit_team1(void)
+{
+    edit_set_team(1);
+}
+
 void edit_cut(void)
 {
-    selection_copy_clear(TRUE, TRUE);
+    selection_copy_clear(TRUE, TRUE, -1);
     deactivate_selection(FALSE);
     full_canvas_redraw();
     update_population_label();
@@ -1192,13 +1243,13 @@
 
 void edit_copy(void)
 {
-    selection_copy_clear(TRUE, FALSE);
+    selection_copy_clear(TRUE, FALSE, -1);
     deactivate_selection(TRUE);
 }
 
 void edit_clear(void)
 {
-    selection_copy_clear(FALSE, TRUE);
+    selection_copy_clear(FALSE, TRUE, -1);
     deactivate_selection(FALSE);
     full_canvas_redraw();
     update_population_label();
@@ -1213,7 +1264,7 @@
         return;
 
     if (SELECTION_ACTIVE())
-        selection_copy_clear(TRUE, FALSE);
+        selection_copy_clear(TRUE, FALSE, -1);
     state.tracking_mouse = PASTING;
     set_command_sensitivity(CMD_EDIT_CANCEL_PASTE, TRUE);
     set_status_message((state.moving ? MOVING_MESSAGE : PASTING_MESSAGE), FALSE);
@@ -1413,7 +1464,6 @@
     gtk_box_pack_start(GTK_BOX(hbox), info->default_fullscreen_toggle, FALSE, FALSE, 0);
     label = gtk_label_new("Start in fullscreen mode");
     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3);
-    LEFT_ALIGN(hbox);
     gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0);
 
     /* Add "General" view prefs */
@@ -1435,9 +1485,12 @@
         if (i == BG_COLOR_INDEX) {
             title_text    = "Choose Background Color";
             default_value = DEFAULT_BG_COLOR;
-        } else if (i == CELL_COLOR_INDEX) {
-            title_text  = "Choose Cell Color";
-            default_value = DEFAULT_CELL_COLOR;
+        } else if (i == TEAM0_COLOR_INDEX) {
+            title_text  = "Choose Team 0 Cell Color";
+            default_value = DEFAULT_TEAM0_COLOR;
+        } else if (i == TEAM1_COLOR_INDEX) {
+            title_text  = "Choose Team 1 Cell Color";
+            default_value = DEFAULT_TEAM1_COLOR;
         } else if (i == GRID_COLOR_INDEX) {
             title_text  = "Choose Grid Color";
             default_value = DEFAULT_GRID_COLOR;
@@ -1714,6 +1767,7 @@
     gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new(TITLE " Version " VERSION), FALSE, FALSE, 0);
     gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("Suzanne Skinner"), FALSE, FALSE, 0);
     gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("Copyright 2004"), FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("Battle patch by Shane Hathaway"), FALSE, FALSE, 0);
     gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("GNU General Public License"), FALSE, FALSE,
                        0);
     CENTER_ALIGN(vbox);
@@ -1906,7 +1960,7 @@
     if (!edit_paste_verify_target(pt))
         return;
     if (state.moving)
-        selection_copy_clear(FALSE, TRUE);
+        selection_copy_clear(FALSE, TRUE, -1);
     edit_paste_perform(pt);
     deactivate_selection(FALSE);
     deactivate_paste(FALSE);
@@ -1922,7 +1976,7 @@
         return;
 
     if (SELECTION_ACTIVE())
-        selection_copy_clear(TRUE, FALSE);
+        selection_copy_clear(TRUE, FALSE, -1);
     else if (rects_identical(&state.copy_rect, &null_rect))
         return;
     if (!edit_paste_verify_target(pt))
@@ -1961,25 +2015,25 @@
         for (yoff=0; yoff < 4; yoff++) {
             for (xoff=0; xoff < 4; xoff++) {
                 if (c->bnw[0] & (1 << (yoff*4 + xoff)))
-                    draw_cell(xstart+xoff, ystart+yoff, DRAW_SET);
+                    draw_cell(xstart+xoff, ystart+yoff, DRAW_SET, state.drawing_team);
             }
         }
         for (yoff=0; yoff < 4; yoff++) {
             for (xoff=0; xoff < 4; xoff++) {
                 if (c->bne[0] & (1 << (yoff*4 + xoff)))
-                    draw_cell(xstart+4+xoff, ystart+yoff, DRAW_SET);
+                    draw_cell(xstart+4+xoff, ystart+yoff, DRAW_SET, state.drawing_team);
             }
         }
         for (yoff=0; yoff < 4; yoff++) {
             for (xoff=0; xoff < 4; xoff++) {
                 if (c->bsw[0] & (1 << (yoff*4 + xoff)))
-                    draw_cell(xstart+xoff, ystart+4+yoff, DRAW_SET);
+                    draw_cell(xstart+xoff, ystart+4+yoff, DRAW_SET, state.drawing_team);
             }
         }
         for (yoff=0; yoff < 4; yoff++) {
             for (xoff=0; xoff < 4; xoff++) {
                 if (c->bse[0] & (1 << (yoff*4 + xoff)))
-                    draw_cell(xstart+4+xoff, ystart+4+yoff, DRAW_SET);
+                    draw_cell(xstart+4+xoff, ystart+4+yoff, DRAW_SET, state.drawing_team);
             }
         }
     }
@@ -2157,6 +2211,7 @@
     vbox = gtk_vbox_new(FALSE, 0);
     init_menubar(vbox);
     init_toolbar(vbox);
+    edit_team0();  /* Ensure the team 0 toggle button is pressed */
     init_sensitivities();
     hbox = gtk_hbox_new(FALSE, 0);
     init_sidebar(hbox);
@@ -2316,6 +2371,7 @@
     toolbar_button*  button;
     int32            num_buttons;
     int32            i;
+    GtkToolbarChildType child_type;
 
     /* Create the button bar */
     toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
@@ -2329,16 +2385,26 @@
         else {
             icon = load_pixmap_from_rgba_array(button->icon, ICON_WIDTH, ICON_HEIGHT,
                                                &(gui.window->style->bg[GTK_STATE_NORMAL]));
+            if (button->cmd == CMD_EDIT_TEAM0 || button->cmd == CMD_EDIT_TEAM1) {
+                /* Create a toggle button */
+                child_type = GTK_TOOLBAR_CHILD_TOGGLEBUTTON;
+            }
+            else
+                child_type = GTK_TOOLBAR_CHILD_BUTTON;
             gui.command_widgets[button->cmd].toolbar_button =
-                gtk_toolbar_append_item(GTK_TOOLBAR(toolbar), NULL, button->description, NULL,
-                                        icon, handle_toolbar_click,
-                                        gui.command_widgets[button->cmd].menu_item);
-            if (button->icon == start_icon)
-                gui.start_pixmap = icon;
+                gtk_toolbar_append_element(GTK_TOOLBAR(toolbar), child_type,
+                                           NULL, NULL, button->description, NULL,
+                                           icon, handle_toolbar_click,
+                                           gui.command_widgets[button->cmd].menu_item);
         }
     }
+    gui.start_pixmap = load_pixmap_from_rgba_array(start_icon, ICON_WIDTH, ICON_HEIGHT,
+                                                  &(gui.window->style->bg[GTK_STATE_NORMAL]));
     gui.stop_pixmap = load_pixmap_from_rgba_array(stop_icon, ICON_WIDTH, ICON_HEIGHT,
                                                   &(gui.window->style->bg[GTK_STATE_NORMAL]));
+    /* Keep a reference to the start/stop pixmaps */
+    gtk_widget_ref(gui.start_pixmap);
+    gtk_widget_ref(gui.stop_pixmap);
 
     /* Frame the button bar */
     toolbar_frame = gtk_frame_new(NULL);
@@ -2555,10 +2621,20 @@
  */
 void init_population_display(GtkWidget* containing_box)
 {
-    gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("Population:  "), FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("Population: "), FALSE, FALSE, 0);
     gui.population_label = gtk_label_new("0");
     gtk_box_pack_start(GTK_BOX(containing_box), gui.population_label, FALSE, FALSE, 0);
     gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("  "), FALSE, FALSE, 0);
+
+    gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("Team0: "), FALSE, FALSE, 0);
+    gui.team0_population_label = gtk_label_new("0");
+    gtk_box_pack_start(GTK_BOX(containing_box), gui.team0_population_label, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("  "), FALSE, FALSE, 0);
+
+    gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("Team1: "), FALSE, FALSE, 0);
+    gui.team1_population_label = gtk_label_new("0");
+    gtk_box_pack_start(GTK_BOX(containing_box), gui.team1_population_label, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(containing_box), gtk_label_new("  "), FALSE, FALSE, 0);
 }
 
 /*** Event Handlers ***/
@@ -3468,13 +3544,13 @@
         x = c->x * CAGE_SIZE;
         y = c->y * CAGE_SIZE;
         if (c->bnw[parity])
-            draw_life_block(c->bnw[parity], x, y, TRUE);
+            draw_life_block(c->bnw[parity], c->bnw[parity + 2], x, y, TRUE);
         if (c->bne[parity])
-            draw_life_block(c->bne[parity], x + BLOCK_SIZE, y, TRUE);
+            draw_life_block(c->bne[parity], c->bne[parity + 2], x + BLOCK_SIZE, y, TRUE);
         if (c->bsw[parity])
-            draw_life_block(c->bsw[parity], x, y + BLOCK_SIZE, TRUE);
+            draw_life_block(c->bsw[parity], c->bsw[parity + 2], x, y + BLOCK_SIZE, TRUE);
         if (c->bse[parity])
-            draw_life_block(c->bse[parity], x + BLOCK_SIZE, y + BLOCK_SIZE, TRUE);
+            draw_life_block(c->bse[parity], c->bse[parity + 2], x + BLOCK_SIZE, y + BLOCK_SIZE, TRUE);
     }
 
     draw_grid_and_boxes();
@@ -3560,7 +3636,7 @@
  * (dstate.update.start.x, etc.) to include this block. This function may be called by the
  * backend.
  */
-void draw_life_block(uint16 block, int32 xstart, int32 ystart, boolean full_update)
+void draw_life_block(uint16 block, uint16 team1, int32 xstart, int32 ystart, boolean full_update)
 {
     int32     xend, yend;
     int32     minx, miny, maxx, maxy;
@@ -3615,9 +3691,17 @@
     if (dstate.zoom > 1) {
         for (y=miny; y <= maxy; y++, start_bit += BLOCK_SIZE) {
             for (x=minx, bit=start_bit; x <= maxx; x++, bit++) {
-                color = ((block & (1 << bit)) ? CELL_COLOR_INDEX : BG_COLOR_INDEX);
-                if (full_update && color == BG_COLOR_INDEX)
-                    continue;
+                if (block & (1 << bit)) {
+                    if (team1 & (1 << bit))
+                        color = TEAM1_COLOR_INDEX;
+                    else
+                        color = TEAM0_COLOR_INDEX;
+                }
+                else {
+                    if (full_update)
+                        continue;
+                    color = BG_COLOR_INDEX;
+                }
                 realx = x * grid_block_size;
                 realy = y * grid_block_size;
                 if (DRAW_GRID(dstate.zoom)) {
@@ -3634,7 +3718,15 @@
         spos = dstate.life_pixmap + miny * dstate.canvas_size.width + minx;
         for (y=miny; y <= maxy; y++, spos += dstate.canvas_size.width, start_bit += BLOCK_SIZE) {
             for (x=minx, bit=start_bit, pos=spos; x <= maxx; x++, pos++, bit++) {
-                color = ((block & (1 << bit)) ? CELL_COLOR_INDEX : BG_COLOR_INDEX);
+                if (block & (1 << bit)) {
+                    if (team1 & (1 << bit))
+                        color = TEAM1_COLOR_INDEX;
+                    else
+                        color = TEAM0_COLOR_INDEX;
+                }
+                else {
+                    color = BG_COLOR_INDEX;
+                }
                 *pos = color;
             }
         }
@@ -3671,10 +3763,15 @@
     if (state.tracking_mouse == DRAWING) {
         if (cur_color == color)
             return;
-    } else
-        color = ((cur_color == CELL_COLOR_INDEX) ? BG_COLOR_INDEX : CELL_COLOR_INDEX);
+    } else {
+        if (cur_color == BG_COLOR_INDEX)
+            color = (state.drawing_team ? TEAM1_COLOR_INDEX : TEAM0_COLOR_INDEX);
+        else
+            color = BG_COLOR_INDEX;
+    }
 
-    draw_cell(npt.x, npt.y, (color == BG_COLOR_INDEX ? DRAW_UNSET : DRAW_SET));
+    draw_cell(npt.x, npt.y, (color == BG_COLOR_INDEX ? DRAW_UNSET : DRAW_SET),
+              state.drawing_team);
     if (dstate.zoom == 1)
         dstate.life_pixmap[spt.y*dstate.canvas_size.width + spt.x] = color;
     else {
@@ -4052,6 +4149,12 @@
 
     sprintf(str, "%u", population);
     gtk_label_set_text(GTK_LABEL(gui.population_label), str);
+
+    sprintf(str, "%u", population - team1_population);
+    gtk_label_set_text(GTK_LABEL(gui.team0_population_label), str);
+
+    sprintf(str, "%u", team1_population);
+    gtk_label_set_text(GTK_LABEL(gui.team1_population_label), str);
 }
 
 /* Regenerate the list of patterns for the sidebar. */
@@ -4656,8 +4759,9 @@
     }
 }
 
-/* Clear and/or copy the current selection. */
-void selection_copy_clear(boolean copy, boolean clear)
+/* Perform an operation on the current selection:
+    copy, clear, or set team. */
+void selection_copy_clear(boolean copy, boolean clear, int team)
 {
     static uint16 left_col_masks[8]   = {0xFFFF, 0xEEEE, 0xCCCC, 0x8888, 0, 0, 0, 0};
     static uint16 right_col_masks[8]  = {0xFFFF, 0x7777, 0x3333, 0x1111, 0, 0, 0, 0};
@@ -4724,6 +4828,8 @@
             }
             if (clear)
                 mask_cage(c, ~nw_mask, ~ne_mask, ~sw_mask, ~se_mask);
+            if (team == 0 || team == 1)
+                change_team(c, team, nw_mask, ne_mask, sw_mask, se_mask);
         }
     }
 }
@@ -4835,7 +4941,9 @@
 void start_stop(void)
 {
     const char*  new_text;
-    GtkWidget*   new_icon;
+    GtkWidget *new_icon, *old_icon;
+    GList *list;
+    GtkContainer *start_button;
 
     state.pattern_running = !state.pattern_running;
     if (state.pattern_running) {
@@ -4850,9 +4958,19 @@
         new_icon = gui.start_pixmap;
     }
 
+    start_button = GTK_CONTAINER(gui.command_widgets[CMD_RUN_START_STOP
+                                 ].toolbar_button);
+    /* Remove existing icon from start button */
+    list = gtk_container_children(start_button);
+    if (list) {
+        old_icon = GTK_WIDGET(list->data);
+        g_list_free(list);
+        /* Remove old icon from the button */
+        gtk_container_remove(start_button, old_icon);
+    }
+
     gtk_label_set_text(GTK_LABEL(gui.start_stop_menu_label), new_text);
-    gtk_container_add(GTK_CONTAINER(gui.command_widgets[CMD_RUN_START_STOP].toolbar_button),
-                      new_icon);
+    gtk_container_add(start_button, new_icon);
     gtk_widget_show(new_icon);
 }
 
@@ -4909,9 +5027,13 @@
  */
 void alpha_blend(uint8* rgb1, const uint8* rgb2, int32 opacity)
 {
-    *rgb1 = ((int32)(*rgb1++) * (255 - opacity) + (int32)(*rgb2++) * opacity) / 255;
-    *rgb1 = ((int32)(*rgb1++) * (255 - opacity) + (int32)(*rgb2++) * opacity) / 255;
-    *rgb1 = ((int32)(*rgb1++) * (255 - opacity) + (int32)(*rgb2++) * opacity) / 255;
+    *rgb1 = ((int32)(*rgb1) * (255 - opacity) + (int32)(*rgb2) * opacity) / 255;
+    rgb1++;
+    rgb2++;
+    *rgb1 = ((int32)(*rgb1) * (255 - opacity) + (int32)(*rgb2) * opacity) / 255;
+    rgb1++;
+    rgb2++;
+    *rgb1 = ((int32)(*rgb1) * (255 - opacity) + (int32)(*rgb2) * opacity) / 255;
 }
 
 /* Return a dynamically allocated copy of the given path, with a trailing slash appended unless
diff -u gtklife-4.0/gtklife.h gtklife-4.0-battle/gtklife.h
--- gtklife-4.0/gtklife.h	2004-08-24 17:21:20.000000000 -0600
+++ gtklife-4.0-battle/gtklife.h	2004-12-19 20:41:59.386312680 -0700
@@ -9,7 +9,7 @@
 /* Defines */
 
 #define PROG      "gtklife"
-#define TITLE     "GtkLife"
+#define TITLE     "GtkLifeBattle"
 #define USER_DIR  ".gtklife"
 #define VERSION   "4.0"
 
@@ -47,9 +47,10 @@
 #define DEFAULT_SHOW_STATUSBAR    TRUE
 #define DEFAULT_FULLSCREEN        FALSE
 #define DEFAULT_BG_COLOR          0xC0C0C0
-#define DEFAULT_CELL_COLOR        0x000080
+#define DEFAULT_TEAM0_COLOR        0x000080
 #define DEFAULT_GRID_COLOR        0x808080
 #define DEFAULT_SELECT_COLOR      0xFF0000
+#define DEFAULT_TEAM1_COLOR        0x800000
 #define DEFAULT_SPEED             20
 #define DEFAULT_SPEED_SLIDER_MIN  1
 #define DEFAULT_SPEED_SLIDER_MAX  200
@@ -59,8 +60,9 @@
 
 /* Enumerations */
 
-enum color_index_enum  {BG_COLOR_INDEX, CELL_COLOR_INDEX, GRID_COLOR_INDEX, SELECT_COLOR_INDEX,
-                        NUM_COLORS};
+enum color_index_enum  {BG_COLOR_INDEX, TEAM0_COLOR_INDEX,
+                        GRID_COLOR_INDEX, SELECT_COLOR_INDEX,
+                        TEAM1_COLOR_INDEX, NUM_COLORS};
 
 typedef enum tracking_mouse_enum {NORMAL, DRAWING, SELECTING, PASTING} tracking_mouse_type;
 
@@ -107,6 +109,8 @@
     CMD_POSITION_PAGE_SW,
     CMD_POSITION_PAGE_SE,
 
+    CMD_EDIT_TEAM0,
+    CMD_EDIT_TEAM1,
     CMD_EDIT_CUT,
     CMD_EDIT_COPY,
     CMD_EDIT_CLEAR,
@@ -335,6 +339,8 @@
 void  position_page_sw(void);
 void  position_page_se(void);
 
+void  edit_team0(void);
+void  edit_team1(void);
 void  edit_cut(void);
 void  edit_copy(void);
 void  edit_clear(void);
@@ -448,7 +454,7 @@
 void  draw_life_pixmap(void);
 void  draw_grid_and_boxes(void);
 void  draw_screen_box(const rect* box);
-void  draw_life_block(uint16 block, int32 xstart, int32 ystart, boolean full_update);
+void  draw_life_block(uint16 block, uint16 team1, int32 xstart, int32 ystart, boolean full_update);
 void  user_draw(const point* pt);
 void  draw_from_to(const point* start, const point* end);
 
@@ -499,7 +505,7 @@
                                 int32* num_patterns);
 void     reset_fps_measure(void);
 void     screen_box_update(rect* oldr, const rect* newr, boolean redraw);
-void     selection_copy_clear(boolean copy, boolean clear);
+void     selection_copy_clear(boolean copy, boolean clear, int team);
 boolean  set_collection_dir(const char* path, boolean have_gui);
 void     set_current_dir_from_file(const char* filepath);
 void     set_pattern_title(pattern_file* file);
diff -u gtklife-4.0/icons.c gtklife-4.0-battle/icons.c
--- gtklife-4.0/icons.c	2004-04-25 16:00:48.000000000 -0600
+++ gtklife-4.0-battle/icons.c	2004-12-19 17:10:08.442332808 -0700
@@ -1536,3 +1536,148 @@
   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
   "\0\0\37\0\0\0\37\0\0\0\37\0\0\0\0\0\0\0\0";
+
+uint8 team0_icon[] =
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\377\0\0\0"
+  "\377\0\0\0\132\0\0\0\12\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\377\371\342\34\377\357\251\56\377"
+  "\0\0\0\377\0\0\0\36\0\0\0\12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\372\343\35\377\364\244\45\377\122\106\47"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\372\343\33\377\364\244\47\377\141\124\56\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\370\333\33\377\361\242\46\377\125\105\52\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\30\0\0\0\11\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\367\325\34\377\360\240\43\377\126\105\51\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\367\325\32\377\353\247\60\377\133\117\54\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\366\317\31\377\354\231\43\377\131\115\52\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\364\310\31\377\351\222\42\377\122\110\53\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\316\233\131\377\126\114\51\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\106\72\23"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\0\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\36\0\0"
+  "\0\13\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\13\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\13\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\13\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\13\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0"
+  "\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\13\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\36\0\0\0\13\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\35\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\30\0\0\0\11\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0\4";
+
+
+uint8 team1_icon[] =
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\377\0\0\0"
+  "\377\0\0\0\132\0\0\0\12\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\377\371\342\34\377\357\251\56\377"
+  "\0\0\0\377\0\0\0\36\0\0\0\12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\377\372\343\35\377\364\244\45\377\122\106\47"
+  "\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\377\372\343\33\377\364\244\47\377\141\124\56\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\370\333\33\377\361\242\46\377\125\105\52\377\0\0\0\377"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\30\0\0\0\11\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\367\325\34\377\360\240\43\377\126\105\51\377\0\0\0\377\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\367\325\32\377\353\247\60\377\133\117\54\377\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\377\366\317\31\377\354\231\43\377\131\115\52\377\0\0\0\377\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\364\310\31\377\351\222\42\377\122\110\53\377\0\0\0\377\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\316\233\131\377\126\114\51\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\106\72\23"
+  "\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377"
+  "\0\0\0\0\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13"
+  "\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0\377\0\0\0\377\0"
+  "\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\377\0"
+  "\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\377\0\0"
+  "\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0"
+  "\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0"
+  "\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\377\0\0\0\0\0\0\0\377"
+  "\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\377\0\0\0\377\0\0\0\36\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\35\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\30\0\0\0\11\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+  "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0\4";
diff -u gtklife-4.0/icons.h gtklife-4.0-battle/icons.h
--- gtklife-4.0/icons.h	2004-04-25 16:00:52.000000000 -0600
+++ gtklife-4.0-battle/icons.h	2004-12-19 17:10:08.443331656 -0700
@@ -11,6 +11,8 @@
 extern uint8  copy_icon[];
 extern uint8  cut_icon[];
 extern uint8  description_icon[];
+extern uint8  team0_icon[];
+extern uint8  team1_icon[];
 extern uint8  error_icon[];
 extern uint8  new_icon[];
 extern uint8  open_icon[];
diff -u gtklife-4.0/life.c gtklife-4.0-battle/life.c
--- gtklife-4.0/life.c	2004-08-24 00:37:11.000000000 -0600
+++ gtklife-4.0-battle/life.c	2004-12-19 19:41:26.077659552 -0700
@@ -37,6 +37,7 @@
 uint32      tick;
 boolean     parity;      /* on an odd (1) or even (0) tick? */
 uint32      population;
+uint32      team1_population;
 uint32      num_cages;
 
 /* pattern_description is an array of length desc_num_lines, where each array entry is a single
@@ -44,6 +45,7 @@
  * description. */
 char**      pattern_description;
 int32       desc_num_lines;
+int           draw_default_team;
 
 /*** Private Globals ***/
 
@@ -55,7 +57,8 @@
 
 static cage_type*  dead_cages;               /* singly-linked list */
 static cage_type*  cage_hash[XY_HASH_SIZE];  /* for finding new neighbors */
-static uint32      sleeping_population, predictable_population[2];
+static uint32      sleeping_population, predictable_population[4];
+static uint32      team1_sleeping_population;
 
 /* The frontend tells us about the viewport dimensions, so that we know which cells should
  * be drawn onscreen. */
@@ -80,7 +83,7 @@
 static void        update_onscreen_flag(cage_type* cage);
 
 /* Defined in the GUI code */
-void draw_life_block(uint16 block, int32 xstart, int32 ystart, boolean full_update);
+void draw_life_block(uint16 block, uint16 team1, int32 xstart, int32 ystart, boolean full_update);
 
 /*** Public Functions ***/
 
@@ -89,6 +92,8 @@
  */
 void clear_world(void)
 {
+    int i;
+
     /* Clear all cage lists */
     clear_cage_list(&active_cages);
     clear_cage_list(&sleeping_cages);
@@ -102,7 +107,10 @@
 
     /* Set ticks and population to 0 */
     tick = parity = population = sleeping_population = 0;
-    predictable_population[0] = predictable_population[1] = 0;
+    team1_population = 0;
+    team1_sleeping_population = 0;
+    for (i = 0; i < 4; i++)
+        predictable_population[i] = 0;
 
     /* Clear the description */
     clear_description();
@@ -124,12 +132,12 @@
 
 /* Set, unset, or toggle the cell at the given XY coordinates.
  */
-void draw_cell(int32 x, int32 y, draw_method_type draw_method)
+void draw_cell(int32 x, int32 y, draw_method_type draw_method, int team)
 {
     cage_type*  cage;
     int32       cagex, cagey;
     int32       xoffset, yoffset;
-    uint16*     block;
+    uint16     *block, *team1_block;
     uint16      bitmask;
 
     /* Check if coordinates are out of bounds */
@@ -166,19 +174,46 @@
         else
             block = &(cage->bse[parity]);
     }
+    team1_block = &(block[2]);
     yoffset %= 4;
     xoffset %= 4;
 
-    /* Set or unset the appropriate bit */
+    if (team < 0)
+        team = draw_default_team;
+
+    /* Set or unset the appropriate bits.  Update population counts. */
     bitmask = 1 << (yoffset*4 + xoffset);
     if (draw_method == DRAW_SET) {
         if (!(*block & bitmask)) {
+            /* A new cell */
+            if (team) {
+                *team1_block |= bitmask;
+                team1_population++;
+            }
+            else {
+                *team1_block &= ~bitmask;
+            }
             *block |= bitmask;
             population++;
         }
+        else if (team && !(*team1_block & bitmask)) {
+            /* Switch cell to team 1 */
+            *team1_block |= bitmask;
+            team1_population++;
+        }
+        else if (!team && (*team1_block & bitmask)) {
+            /* Switch cell to team 0 */
+            *team1_block &= ~bitmask;
+            team1_population--;
+        }
     }
     else {
         if (*block & bitmask) {
+            if (*team1_block & bitmask) {
+                /* Removing a cell from team 1 */
+                team1_population--;
+                *team1_block &= ~bitmask;
+            }
             *block &= ~bitmask;
             population--;
         }
@@ -401,14 +436,37 @@
     return pos;
 }
 
-/* Apply the given bitmasks to the four corners of the cage to reduce its contents, zeroing any
- * cells that are not 1 in the mask.
+/* Apply the given bitmasks to the four corners of the cage to reduce
+ * its contents, zeroing any cells that are not 1 in the mask.
  */
 void mask_cage(cage_type* cage, uint16 nw_mask, uint16 ne_mask, uint16 sw_mask, uint16 se_mask)
 {
     uint16  nw, ne, sw, se;
     uint32  old_pop, new_pop;
 
+    /* Update population of team 1 */
+    nw = cage->bnw[parity] & cage->bnw[parity + 2];
+    ne = cage->bne[parity] & cage->bne[parity + 2];
+    sw = cage->bsw[parity] & cage->bsw[parity + 2];
+    se = cage->bse[parity] & cage->bse[parity + 2];
+    old_pop = POPULATION_COUNT(nw, ne, sw, se);
+    nw &= nw_mask;
+    ne &= ne_mask;
+    sw &= sw_mask;
+    se &= se_mask;
+    new_pop = POPULATION_COUNT(nw, ne, sw, se);
+
+    if (old_pop != new_pop) {
+        rattle_cage(cage, TRUE);
+        rattle_neighbors(cage);
+        cage->bnw[parity + 2] = nw;
+        cage->bne[parity + 2] = ne;
+        cage->bsw[parity + 2] = sw;
+        cage->bse[parity + 2] = se;
+        team1_population -= old_pop - new_pop;
+    }
+
+    /* Update population of both teams */
     nw = cage->bnw[parity];
     ne = cage->bne[parity];
     sw = cage->bsw[parity];
@@ -431,6 +489,189 @@
     }
 }
 
+/* Change the team for part of a cage */
+void change_team(cage_type* cage, int team,
+              uint16 nw_sel, uint16 ne_sel,
+              uint16 sw_sel, uint16 se_sel) {
+    uint16  nw, ne, sw, se;
+    uint32  old_pop, new_pop;
+
+    nw = cage->bnw[parity] & cage->bnw[parity + 2];
+    ne = cage->bne[parity] & cage->bne[parity + 2];
+    sw = cage->bsw[parity] & cage->bsw[parity + 2];
+    se = cage->bse[parity] & cage->bse[parity + 2];
+    old_pop = POPULATION_COUNT(nw, ne, sw, se);
+
+    nw = cage->bnw[parity + 2] & ~nw_sel;
+    ne = cage->bne[parity + 2] & ~ne_sel;
+    sw = cage->bsw[parity + 2] & ~sw_sel;
+    se = cage->bse[parity + 2] & ~se_sel;
+    if (team == 1) {
+        nw |= cage->bnw[parity] & nw_sel;
+        ne |= cage->bne[parity] & ne_sel;
+        sw |= cage->bsw[parity] & sw_sel;
+        se |= cage->bse[parity] & se_sel;
+    }
+    new_pop = POPULATION_COUNT(nw, ne, sw, se);
+
+    if (old_pop != new_pop) {
+        rattle_cage(cage, TRUE);
+        rattle_neighbors(cage);
+        cage->bnw[parity + 2] = nw;
+        cage->bne[parity + 2] = ne;
+        cage->bsw[parity + 2] = sw;
+        cage->bse[parity + 2] = se;
+        team1_population -= old_pop - new_pop;
+    }
+}
+
+/* Compute the next generation for one cage */
+static void compute_cage_generation(cage_type* cage, int team,
+                                    lookup_set *lookup,
+                                    uint16* new_nw, uint16* new_ne,
+                                    uint16 *new_sw, uint16 *new_se) {
+    cage_type *c;
+    int i, t, do_team;
+    uint16 team_xor;
+    uint16 nw, ne, sw, se;
+    uint16 neigh_nnw, neigh_nne, neigh_ssw, neigh_sse, neigh_wnw, neigh_wsw,
+        neigh_ene, neigh_ese, neigh_nw, neigh_ne, neigh_sw, neigh_se;
+
+    i = parity;  /* array index for the cell state */
+    t = i + 2;  /* array index for the team 1 block */
+    if (team == 0) {
+        do_team = 1;
+        team_xor = 0xFFFF;
+    }
+    else if (team == 1) {
+        do_team = 1;
+        team_xor = 0;
+    }
+    else {
+        do_team = 0;
+        team_xor = 0;
+    }
+
+    /* Extract the four 4x4 blocks in this cage and the neighboring
+     * 4x4 blocks that we'll need to know about.  If team is 0 or 1,
+     * work on the cells for only one team.
+     */
+
+    nw = cage->bnw[i];
+    ne = cage->bne[i];
+    sw = cage->bsw[i];
+    se = cage->bse[i];
+    if (do_team) {
+        nw &= cage->bnw[t] ^ team_xor;
+        ne &= cage->bne[t] ^ team_xor;
+        sw &= cage->bsw[t] ^ team_xor;
+        se &= cage->bse[t] ^ team_xor;
+    }
+
+    c = cage->north;
+    if (c) {
+        neigh_nnw = c->bsw[i];
+        neigh_nne = c->bse[i];
+        if (do_team) {
+            neigh_nnw &= c->bsw[t] ^ team_xor;
+            neigh_nne &= c->bse[t] ^ team_xor;
+        }
+    } else
+        neigh_nnw = neigh_nne = 0;
+
+    c = cage->south;
+    if (c) {
+        neigh_ssw = c->bnw[i];
+        neigh_sse = c->bne[i];
+        if (do_team) {
+            neigh_ssw &= c->bnw[t] ^ team_xor;
+            neigh_sse &= c->bne[t] ^ team_xor;
+        }
+    } else
+        neigh_ssw = neigh_sse = 0;
+
+    c = cage->west;
+    if (c) {
+        neigh_wnw = c->bne[i];
+        neigh_wsw = c->bse[i];
+        if (do_team) {
+            neigh_wnw &= c->bne[t] ^ team_xor;
+            neigh_wsw &= c->bse[t] ^ team_xor;
+        }
+    } else
+        neigh_wnw = neigh_wsw = 0;
+
+    c = cage->east;
+    if (c) {
+        neigh_ene = c->bnw[i];
+        neigh_ese = c->bsw[i];
+        if (do_team) {
+            neigh_ene &= c->bnw[t] ^ team_xor;
+            neigh_ese &= c->bsw[t] ^ team_xor;
+        }
+    } else
+        neigh_ene = neigh_ese = 0;
+
+    c = cage->nw;
+    if (c) {
+        neigh_nw = c->bse[i];
+        if (do_team)
+            neigh_nw &= c->bse[t] ^ team_xor;
+    }
+    else
+        neigh_nw = 0;
+
+    c = cage->ne;
+    if (c) {
+        neigh_ne = c->bsw[i];
+        if (do_team)
+            neigh_ne &= c->bsw[t] ^ team_xor;
+    }
+    else
+        neigh_ne = 0;
+
+    c = cage->sw;
+    if (c) {
+        neigh_sw = c->bne[i];
+        if (do_team)
+            neigh_sw &= c->bne[t] ^ team_xor;
+    }
+    else
+        neigh_sw = 0;
+
+    c = cage->se;
+    if (c) {
+        neigh_se = c->bnw[i];
+        if (do_team)
+            neigh_se &= c->bnw[t] ^ team_xor;
+    }
+    else
+        neigh_se = 0;
+
+    /* Calculate the new 4x4 blocks for this cage */
+    *new_nw =
+        lookup->ul[(nw & 0x0777) | (neigh_nnw & 0x7000) | (neigh_wnw & 0x0888) | (neigh_nw & 0x8000)]   |
+        lookup->ur[(nw & 0x0EEE) | (neigh_nnw & 0xE000) | (ne & 0x0111)        | (neigh_nne & 0x1000)]  |
+        lookup->ll[(nw & 0x7770) | (sw & 0x0007)        | (neigh_wnw & 0x8880) | (neigh_wsw & 0x0008)]  |
+        lookup->lr[(nw & 0xEEE0) | (sw & 0x000E)        | (ne & 0x1110)        | (se & 0x0001)];
+    *new_ne =
+        lookup->ul[(ne & 0x0777) | (neigh_nne & 0x7000) | (nw & 0x0888)        | (neigh_nnw & 0x8000)]  |
+        lookup->ur[(ne & 0x0EEE) | (neigh_nne & 0xE000) | (neigh_ene & 0x0111) | (neigh_ne & 0x1000)]   |
+        lookup->ll[(ne & 0x7770) | (se & 0x0007)        | (nw & 0x8880)        | (sw & 0x0008)]         |
+        lookup->lr[(ne & 0xEEE0) | (se & 0x000E)        | (neigh_ene & 0x1110) | (neigh_ese & 0x0001)];
+    *new_sw =
+        lookup->ul[(sw & 0x0777) | (nw & 0x7000)        | (neigh_wsw & 0x0888) | (neigh_wnw & 0x8000)]  |
+        lookup->ur[(sw & 0x0EEE) | (nw & 0xE000)        | (se & 0x0111)        | (ne & 0x1000)]         |
+        lookup->ll[(sw & 0x7770) | (neigh_ssw & 0x0007) | (neigh_wsw & 0x8880) | (neigh_sw & 0x0008)]   |
+        lookup->lr[(sw & 0xEEE0) | (neigh_ssw & 0x000E) | (se & 0x1110)        | (neigh_sse & 0x0001)];
+    *new_se =
+        lookup->ul[(se & 0x0777) | (ne & 0x7000)        | (sw & 0x0888)        | (nw & 0x8000)]         |
+        lookup->ur[(se & 0x0EEE) | (ne & 0xE000)        | (neigh_ese & 0x0111) | (neigh_ene & 0x1000)]  |
+        lookup->ll[(se & 0x7770) | (neigh_sse & 0x0007) | (sw & 0x8880)        | (neigh_ssw & 0x0008)]  |
+        lookup->lr[(se & 0xEEE0) | (neigh_sse & 0x000E) | (neigh_ese & 0x1110) | (neigh_se & 0x0001)];
+}
+
+
 /* Calculate the next Life generation. If update_display is true, update the display pixmap via
  * calls to the external function draw_life_block.
  */
@@ -445,20 +686,22 @@
     uint16      nw, ne, sw, se;
     uint16      old_nw, old_ne, old_sw, old_se;
     uint16      new_nw, new_ne, new_sw, new_se;
-    uint16      neigh_nnw, neigh_nne, neigh_ssw, neigh_sse, neigh_wnw, neigh_wsw,
-                neigh_ene, neigh_ese, neigh_nw, neigh_ne, neigh_sw, neigh_se;
+    uint16      team1_nw, team1_ne, team1_sw, team1_se;
+    uint16      tmp_team0_nw, tmp_team0_ne, tmp_team0_sw, tmp_team0_se;
+    uint16      new_team1_nw, new_team1_ne, new_team1_sw, new_team1_se;
+    uint16      old_team1_nw, old_team1_ne, old_team1_sw, old_team1_se;
 
     t1 = parity;
     t2 = !parity;
     population = sleeping_population + predictable_population[t2];
+    team1_population = team1_sleeping_population +
+        predictable_population[t2 + 2];
 
     for (cage=active_cages; cage; cage=next) {
         /* Store next-pointer in case we end up moving this cage to another linked list */
         next = cage->next;
 
-        /* Extract the four 4x4 blocks in this cage, past and present, as well as any neighboring
-         * 4x4 blocks that we'll need to know about.
-         */
+        /* Extract the four present and past 4x4 blocks in this cage. */
         nw = cage->bnw[t1];
         ne = cage->bne[t1];
         sw = cage->bsw[t1];
@@ -467,55 +710,36 @@
         old_ne = cage->bne[t2];
         old_sw = cage->bsw[t2];
         old_se = cage->bse[t2];
-        if (cage->north) {
-            neigh_nnw = cage->north->bsw[t1];
-            neigh_nne = cage->north->bse[t1];
-        } else
-            neigh_nnw = neigh_nne = 0;
-        if (cage->south) {
-            neigh_ssw = cage->south->bnw[t1];
-            neigh_sse = cage->south->bne[t1];
-        } else
-            neigh_ssw = neigh_sse = 0;
-        if (cage->west) {
-            neigh_wnw = cage->west->bne[t1];
-            neigh_wsw = cage->west->bse[t1];
-        } else
-            neigh_wnw = neigh_wsw = 0;
-        if (cage->east) {
-            neigh_ene = cage->east->bnw[t1];
-            neigh_ese = cage->east->bsw[t1];
-        } else
-            neigh_ene = neigh_ese = 0;
-        neigh_nw = ((cage->nw) ? cage->nw->bse[t1] : 0);
-        neigh_ne = ((cage->ne) ? cage->ne->bsw[t1] : 0);
-        neigh_sw = ((cage->sw) ? cage->sw->bne[t1] : 0);
-        neigh_se = ((cage->se) ? cage->se->bnw[t1] : 0);
-
-        /* Calculate the new 4x4 blocks for this cage */
-        new_nw =
-            ul_lookup[(nw & 0x0777) | (neigh_nnw & 0x7000) | (neigh_wnw & 0x0888) | (neigh_nw & 0x8000)]   |
-            ur_lookup[(nw & 0x0EEE) | (neigh_nnw & 0xE000) | (ne & 0x0111)        | (neigh_nne & 0x1000)]  |
-            ll_lookup[(nw & 0x7770) | (sw & 0x0007)        | (neigh_wnw & 0x8880) | (neigh_wsw & 0x0008)]  |
-            lr_lookup[(nw & 0xEEE0) | (sw & 0x000E)        | (ne & 0x1110)        | (se & 0x0001)];
-        new_ne =
-            ul_lookup[(ne & 0x0777) | (neigh_nne & 0x7000) | (nw & 0x0888)        | (neigh_nnw & 0x8000)]  |
-            ur_lookup[(ne & 0x0EEE) | (neigh_nne & 0xE000) | (neigh_ene & 0x0111) | (neigh_ne & 0x1000)]   |
-            ll_lookup[(ne & 0x7770) | (se & 0x0007)        | (nw & 0x8880)        | (sw & 0x0008)]         |
-            lr_lookup[(ne & 0xEEE0) | (se & 0x000E)        | (neigh_ene & 0x1110) | (neigh_ese & 0x0001)];
-        new_sw =
-            ul_lookup[(sw & 0x0777) | (nw & 0x7000)        | (neigh_wsw & 0x0888) | (neigh_wnw & 0x8000)]  |
-            ur_lookup[(sw & 0x0EEE) | (nw & 0xE000)        | (se & 0x0111)        | (ne & 0x1000)]         |
-            ll_lookup[(sw & 0x7770) | (neigh_ssw & 0x0007) | (neigh_wsw & 0x8880) | (neigh_sw & 0x0008)]   |
-            lr_lookup[(sw & 0xEEE0) | (neigh_ssw & 0x000E) | (se & 0x1110)        | (neigh_sse & 0x0001)];
-        new_se =
-            ul_lookup[(se & 0x0777) | (ne & 0x7000)        | (sw & 0x0888)        | (nw & 0x8000)]         |
-            ur_lookup[(se & 0x0EEE) | (ne & 0xE000)        | (neigh_ese & 0x0111) | (neigh_ene & 0x1000)]  |
-            ll_lookup[(se & 0x7770) | (neigh_sse & 0x0007) | (sw & 0x8880)        | (neigh_ssw & 0x0008)]  |
-            lr_lookup[(se & 0xEEE0) | (neigh_sse & 0x000E) | (neigh_ese & 0x1110) | (neigh_se & 0x0001)];
+        team1_nw = cage->bnw[t1 + 2];
+        team1_ne = cage->bne[t1 + 2];
+        team1_sw = cage->bsw[t1 + 2];
+        team1_se = cage->bse[t1 + 2];
+        old_team1_nw = cage->bnw[t2 + 2];
+        old_team1_ne = cage->bne[t2 + 2];
+        old_team1_sw = cage->bsw[t2 + 2];
+        old_team1_se = cage->bse[t2 + 2];
+
+        /* Compute the next generation for this cage */
+        compute_cage_generation(cage, -1, &conway_rules,
+                                &new_nw, &new_ne, &new_sw, &new_se);
+
+        /* Compute the teams for the next generation in this cage */
+        compute_cage_generation(cage, 0, &takeover_rules,
+                                &tmp_team0_nw, &tmp_team0_ne,
+                                &tmp_team0_sw, &tmp_team0_se);
+        compute_cage_generation(cage, 1, &takeover_rules,
+                                &new_team1_nw, &new_team1_ne,
+                                &new_team1_sw, &new_team1_se);
+        new_team1_nw = (team1_nw | new_team1_nw) & ~tmp_team0_nw & new_nw;
+        new_team1_ne = (team1_ne | new_team1_ne) & ~tmp_team0_ne & new_ne;
+        new_team1_sw = (team1_sw | new_team1_sw) & ~tmp_team0_sw & new_sw;
+        new_team1_se = (team1_se | new_team1_se) & ~tmp_team0_se & new_se;
 
-        /* Update population count */
+        /* Update population counts */
         population += POPULATION_COUNT(new_nw, new_ne, new_sw, new_se);
+        team1_population += POPULATION_COUNT(
+                                             new_team1_nw, new_team1_ne,
+                                             new_team1_sw, new_team1_se);
 
         /* Check if the cage is stable or oscillating, and update TURNS_STABLE and
          * TURNS_OSCILLATING accordingly. If it's been stable awhile, move it to sleeping_cages or
@@ -523,7 +747,14 @@
          */
         turns_oscillating = TURNS_OSCILLATING(cage);
         oscillating_to_stable = FALSE;
-        if (new_nw == nw && new_ne == ne && new_sw == sw && new_se == se) {
+        if (new_nw == nw &&
+            new_ne == ne &&
+            new_sw == sw &&
+            new_se == se &&
+            new_team1_nw == team1_nw &&
+            new_team1_ne == team1_ne &&
+            new_team1_sw == team1_sw &&
+            new_team1_se == team1_se) {
             turns_stable = TURNS_STABLE(cage);
             if (turns_stable == MAX_TURNS_STABLE) {
                 if (!new_nw && !new_ne && !new_sw && !new_se)
@@ -546,7 +777,14 @@
         } else {
             RESET_TURNS_STABLE(cage);
             turns_stable = 0;
-            if (new_nw == old_nw && new_ne == old_ne && new_sw == old_sw && new_se == old_se) {
+            if (new_nw == old_nw &&
+                new_ne == old_ne &&
+                new_sw == old_sw &&
+                new_se == old_se &&
+                new_team1_nw == old_team1_nw &&
+                new_team1_ne == old_team1_ne &&
+                new_team1_sw == old_team1_sw &&
+                new_team1_se == old_team1_se) {
                 if (turns_oscillating == MAX_TURNS_OSCILLATING) {
                     predict_cage(cage);
                     continue;   /* no need to redraw (see below), apply new blocks, or rattle */
@@ -565,14 +803,14 @@
         if (!turns_stable && IS_ONSCREEN(cage) && update_display) {
             x = cage->x * CAGE_SIZE;
             y = cage->y * CAGE_SIZE;
-            if (new_nw != nw)
-                draw_life_block(new_nw, x, y, FALSE);
-            if (new_ne != ne)
-                draw_life_block(new_ne, x + BLOCK_SIZE, y, FALSE);
-            if (new_sw != sw)
-                draw_life_block(new_sw, x, y + BLOCK_SIZE, FALSE);
-            if (new_se != se)
-                draw_life_block(new_se, x + BLOCK_SIZE, y + BLOCK_SIZE, FALSE);
+            if (new_nw != nw || new_team1_nw != team1_nw)
+                draw_life_block(new_nw, new_team1_nw, x, y, FALSE);
+            if (new_ne != ne || new_team1_ne != team1_ne)
+                draw_life_block(new_ne, new_team1_ne, x + BLOCK_SIZE, y, FALSE);
+            if (new_sw != sw || new_team1_sw != team1_sw)
+                draw_life_block(new_sw, new_team1_sw, x, y + BLOCK_SIZE, FALSE);
+            if (new_se != se || new_team1_se != team1_se)
+                draw_life_block(new_se, new_team1_se, x + BLOCK_SIZE, y + BLOCK_SIZE, FALSE);
         }
 
         if (turns_oscillating)
@@ -583,6 +821,10 @@
         cage->bne[t2] = new_ne;
         cage->bsw[t2] = new_sw;
         cage->bse[t2] = new_se;
+        cage->bnw[t2 + 2] = new_team1_nw;
+        cage->bne[t2 + 2] = new_team1_ne;
+        cage->bsw[t2 + 2] = new_team1_sw;
+        cage->bse[t2 + 2] = new_team1_se;
 
         /* No need to rattle neighbors if we've been stable for one tick, unless we were
          * previously oscillating */
@@ -687,10 +929,10 @@
         for (cage=predictable_cages_onscreen; cage; cage=cage->next) {
             x = cage->x * CAGE_SIZE;
             y = cage->y * CAGE_SIZE;
-            draw_life_block(cage->bnw[t2], x, y, FALSE);
-            draw_life_block(cage->bne[t2], x + BLOCK_SIZE, y, FALSE);
-            draw_life_block(cage->bsw[t2], x, y + BLOCK_SIZE, FALSE);
-            draw_life_block(cage->bse[t2], x + BLOCK_SIZE, y + BLOCK_SIZE, FALSE);
+            draw_life_block(cage->bnw[t2], cage->bnw[t2 + 2], x, y, FALSE);
+            draw_life_block(cage->bne[t2], cage->bne[t2 + 2], x + BLOCK_SIZE, y, FALSE);
+            draw_life_block(cage->bsw[t2], cage->bsw[t2 + 2], x, y + BLOCK_SIZE, FALSE);
+            draw_life_block(cage->bse[t2], cage->bse[t2 + 2], x + BLOCK_SIZE, y + BLOCK_SIZE, FALSE);
         }
     }
 
@@ -1020,26 +1262,31 @@
 }
 
 /* Flag a cage as predictable and move it to the appropriate list, adding its live cell counts for
- * odd and even ticks to predictable_population[2].
+ * odd and even ticks to predictable_population[4].
  */
 static void predict_cage(cage_type* cage)
 {
+    int i;
+
     SET_PREDICTABLE(cage);
     move_cage(cage, &active_cages,
               (IS_ONSCREEN(cage) ? &predictable_cages_onscreen : &predictable_cages_offscreen));
-    predictable_population[0] += POPULATION_COUNT(cage->bnw[0], cage->bne[0], cage->bsw[0],
-                                                  cage->bse[0]);
-    predictable_population[1] += POPULATION_COUNT(cage->bnw[1], cage->bne[1], cage->bsw[1],
-                                                  cage->bse[1]);
+    for (i = 0; i < 4; i++) {
+        predictable_population[i] += POPULATION_COUNT(
+                                                      cage->bnw[i], cage->bne[i],
+                                                      cage->bsw[i], cage->bse[i]);
+    }
 }
 
 /* If cage_changed is true, set TURNS_STABLE and TURNS_OSCILLATING to 0. Otherwise, just make
  * sure they aren't too close to maxed out. If a cage is sleeping or predictable, also remove said
  * flag and move the cage to the front of active_cages, subtracting its live cell count from
- * sleeping_population or predictable_population[2].
+ * sleeping_population or predictable_population[4].
  */
 static void rattle_cage(cage_type* cage, boolean cage_changed)
 {
+    int i;
+
     if (cage_changed) {
         RESET_TURNS_STABLE(cage);
         RESET_TURNS_OSCILLATING(cage);
@@ -1053,17 +1300,22 @@
     if (IS_ASLEEP(cage)) {
         SET_AWAKE(cage);
         move_cage(cage, &sleeping_cages, &active_cages);
-        sleeping_population -= POPULATION_COUNT(cage->bnw[0], cage->bne[0], cage->bsw[0],
-                                                cage->bse[0]);
+        sleeping_population -= POPULATION_COUNT(
+                                                cage->bnw[0], cage->bne[0],
+                                                cage->bsw[0], cage->bse[0]);
+        team1_sleeping_population -= POPULATION_COUNT(
+                                                      cage->bnw[2], cage->bne[2],
+                                                      cage->bsw[2], cage->bse[2]);
     } else if (IS_PREDICTABLE(cage)) {
         SET_UNPREDICTABLE(cage);
         move_cage(cage,
                   (IS_ONSCREEN(cage) ? &predictable_cages_onscreen : &predictable_cages_offscreen),
                   &active_cages);
-        predictable_population[0] -= POPULATION_COUNT(cage->bnw[0], cage->bne[0], cage->bsw[0],
-                                                      cage->bse[0]);
-        predictable_population[1] -= POPULATION_COUNT(cage->bnw[1], cage->bne[1], cage->bsw[1],
-                                                      cage->bse[1]);
+        for (i = 0; i < 4; i++) {
+            predictable_population[i] -= POPULATION_COUNT(
+                                                          cage->bnw[i], cage->bne[i],
+                                                          cage->bsw[i], cage->bse[i]);
+        }
     }
 }
 
@@ -1137,8 +1389,12 @@
 {
     SET_ASLEEP(cage);
     move_cage(cage, &active_cages, &sleeping_cages);
-    sleeping_population += POPULATION_COUNT(cage->bnw[0], cage->bne[0], cage->bsw[0],
-                                            cage->bse[0]);
+    sleeping_population += POPULATION_COUNT(
+                                            cage->bnw[0], cage->bne[0],
+                                            cage->bsw[0], cage->bse[0]);
+    team1_sleeping_population += POPULATION_COUNT(
+                                            cage->bnw[2], cage->bne[2],
+                                            cage->bsw[2], cage->bse[2]);
 }
 
 /* Set or clear the "onscreen" flag for the given cage, depending on viewport settings.
diff -u gtklife-4.0/life.h gtklife-4.0-battle/life.h
--- gtklife-4.0/life.h	2004-08-23 00:54:20.000000000 -0600
+++ gtklife-4.0-battle/life.h	2004-12-19 19:10:00.456317568 -0700
@@ -96,6 +96,12 @@
 /* An 8x8 cell block, with each 4x4 block (upper left, upper right, lower
  * left, lower right) stored as a uint16, and with pointers to neighbors.
  *
+ * The bnw, bne, bsw, and bse arrays each have 4 elements:
+ *   0: even generation, either team
+ *   1: odd generation, either team
+ *   2: even generation, team 1
+ *   3: odd generation, team 1
+ *
  * Flags:
  *   Bits 0-2: # of ticks since this cage last changed    (TURNS_STABLE)
  *   Bits 3-5: # of ticks this cage has been oscillating  (TURNS_OSCILLATING)
@@ -106,7 +112,7 @@
 typedef struct cage_struct {
     uint32  x, y;    /* start position by blocks */
     uint16  flags;
-    uint16  bnw[2], bne[2], bsw[2], bse[2];    /* element 0 on even generations */
+    uint16  bnw[4], bne[4], bsw[4], bse[4];
     struct cage_struct  *north, *south, *west, *east;
     struct cage_struct  *nw, *ne, *sw, *se;
     struct cage_struct  *next, *prev;
@@ -118,22 +124,26 @@
 extern uint32      tick;
 extern boolean     parity;    /* on an odd (1) or even (0) tick? */
 extern uint32      population;
+extern uint32      team1_population;
 extern uint32      num_cages;
 
 extern char**      pattern_description;
 extern int32       desc_num_lines;
+extern int           draw_default_team;
 
 /*** Public Prototypes ***/
 
 void              clear_world(void);
 void              clear_cage_list(cage_type** start);
-void              draw_cell(int32 x, int32 y, draw_method_type draw_method);
+void              draw_cell(int32 x, int32 y, draw_method_type draw_method, int team);
 boolean           find_active_cell(int32* x, int32* y);
 load_result_type  load_pattern(const char* path, file_format_type* detected_format);
 cage_type*        loop_cages(void);
 cage_type*        loop_cages_onscreen(void);
-void              mask_cage(cage_type* cage, uint16 nw_mask, uint16 ne_mask, uint16 sw_mask,
-                            uint16 se_mask);
+void              mask_cage(cage_type* cage, uint16 nw_mask, uint16 ne_mask,
+                            uint16 sw_mask, uint16 se_mask);
+void change_team(cage_type* cage, int team, uint16 nw_sel, uint16 ne_sel,
+                 uint16 sw_sel, uint16 se_sel);
 void              next_tick(boolean update_display);
 void              reset_ticker(void);
 save_result_type  save_pattern(const char* path, file_format_type format);
diff -u gtklife-4.0/loadsave.c gtklife-4.0-battle/loadsave.c
--- gtklife-4.0/loadsave.c	2004-08-24 02:11:19.000000000 -0600
+++ gtklife-4.0-battle/loadsave.c	2004-12-19 17:13:44.639802872 -0700
@@ -111,7 +111,7 @@
             line = load_component_block(f, x, y);
         } else if (sscanf(line, "%d%d", &x, &y) == 2) {
             /* A block with no header: treat it like an #A block */
-            draw_cell(x + WORLD_SIZE/2, y + WORLD_SIZE/2, DRAW_SET);
+            draw_cell(x + WORLD_SIZE/2, y + WORLD_SIZE/2, DRAW_SET, -1);
             line = load_component_coordinates(f, 0, 0, FALSE);
         } else {
             free(line);
@@ -239,7 +239,7 @@
         if (y < WORLD_SIZE && line[0] != '\0') {
             for (p=line, curx=xoffset; *p; p++, curx++) {
                 if (curx < WORLD_SIZE && *p != '.' && !isspace(*p))
-                    draw_cell(curx, y, DRAW_SET);
+                    draw_cell(curx, y, DRAW_SET, -1);
             }
             y++;
         }
@@ -266,7 +266,7 @@
             if (!until_eof)
                 break;
         } else if (sscanf(line, "%d%d", &x, &y) == 2)
-            draw_cell(x + xoffset, y + yoffset, DRAW_SET);
+            draw_cell(x + xoffset, y + yoffset, DRAW_SET, -1);
         free(line);
     }
 
@@ -320,7 +320,7 @@
             } else {    /* the character for live cells is 'o', but accept other characters too */
                 endx = x + count;
                 while (x < endx)
-                    draw_cell(x++, y, DRAW_SET);
+                    draw_cell(x++, y, DRAW_SET, -1);
                 count = 1;
             }
         }
diff -u gtklife-4.0/lookup.h gtklife-4.0-battle/lookup.h
--- gtklife-4.0/lookup.h	2003-07-21 23:29:41.000000000 -0600
+++ gtklife-4.0-battle/lookup.h	2004-12-19 17:10:08.450323592 -0700
@@ -1,9 +1,34 @@
 #ifndef LOOKUP_H
 #define LOOKUP_H
 
-extern uint8   ul_lookup[0x10000];
-extern uint8   ur_lookup[0x10000];
-extern uint16  ll_lookup[0x10000];
-extern uint16  lr_lookup[0x10000];
+extern uint8   conway_ul_lookup[0x10000];
+extern uint8   conway_ur_lookup[0x10000];
+extern uint16  conway_ll_lookup[0x10000];
+extern uint16  conway_lr_lookup[0x10000];
+extern uint8   takeover_ul_lookup[0x10000];
+extern uint8   takeover_ur_lookup[0x10000];
+extern uint16  takeover_ll_lookup[0x10000];
+extern uint16  takeover_lr_lookup[0x10000];
+
+typedef struct {
+    uint8 *ul;
+    uint8 *ur;
+    uint16 *ll;
+    uint16 *lr;
+} lookup_set;
+
+lookup_set conway_rules = {
+    &conway_ul_lookup[0],
+    &conway_ur_lookup[0],
+    &conway_ll_lookup[0],
+    &conway_lr_lookup[0]
+};
+
+lookup_set takeover_rules = {
+    &takeover_ul_lookup[0],
+    &takeover_ur_lookup[0],
+    &takeover_ll_lookup[0],
+    &takeover_lr_lookup[0]
+};
 
 #endif
