|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 9268 (0x2434)
Types: TextFile
Names: »mark.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Life/mark.c«
#ifdef SCCS
static char *sccsid = "@(#)mark.c 1.7 2/2/85";
static char *cpyrid = "@(#)Copyright (C) 1985 by D Bell";
#endif
#include "life.h"
struct loc { /* structure to hold row and column pairs */
long l_row;
long l_col;
};
char rowwalk[9] = {-1,0,0,1,1,0,0,-1,0}; /* row deltas to walk a cell */
char colwalk[9] = {-1,1,1,0,0,-1,-1,0,1}; /* col deltas to walk a cell */
/*
* Mark the object at a given location as specified. Returns nonzero if
* no object exists there. An object for this purpose is considered as a
* king-wise connected set of live cells.
*/
markobject(obj, row, col, mark)
register struct object *obj; /* object to mark up */
{
register struct cell *cp; /* object being marked */
cp = findcell(obj, row, col);
if (cp == NULL) return(1);
cp->c_marks |= mark;
markloop(obj, row, col, mark);
return(0);
}
/* Recursive subroutine called from markobject */
markloop(obj, row, col, mark)
struct object *obj; /* object begin marked */
register int row; /* current row */
register int col; /* current column */
register int mark; /* marking value */
{
register struct cell *cp; /* current cell */
register struct loc *rp; /* pointer into list table */
int i; /* to iterate over directions */
struct loc rclist[8]; /* row and column list */
while (1) {
if (stop) return;
rp = rclist;
for (i = 0; i < 8; i++) { /* find neighbors */
row += rowwalk[i];
col += colwalk[i];
cp = findcell(obj, row, col);
if (cp == NULL) continue;
if (cp->c_marks & mark) continue;
cp->c_marks |= mark;
rp->l_row = row;
rp->l_col = col;
rp++;
}
if (--rp != rclist) { /* recurse if more than one */
for (; rp >= rclist; rp--) {
markloop(obj, rp->l_row, rp->l_col, mark);
}
return;
}
row = rp->l_row; /* else follow single cell */
col = rp->l_col;
}
}
/* Mark a whole object as specified. */
setmarks(obj, mark)
struct object *obj; /* object to mark */
register int mark; /* mark to be applied */
{
register struct row *rp; /* row pointer */
register struct cell *cp; /* cell pointer */
mark |= MARK_ANY;
for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
cp->c_marks |= mark;
}
}
}
/*
* Copy the marks from one type to another for an object. Returns nonzero
* if there were no cells with the given mark.
*/
copymarks(obj, srcmark, destmark)
struct object *obj; /* object to mark */
register int srcmark; /* mark to be found */
register int destmark; /* mark to be set */
{
register struct row *rp; /* row pointer */
register struct cell *cp; /* cell pointer */
int error;
error = 1;
for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
if ((cp->c_marks & srcmark) == 0) continue;
cp->c_marks |= destmark;
error = 0;
}
}
return(error);
}
/* Clear marks for a whole object as specified. */
clearmarks(obj, mark)
struct object *obj; /* object to mark */
register int mark; /* mark to be cleared */
{
register struct row *rp; /* row pointer */
register struct cell *cp; /* cell pointer */
mark = ~mark;
mark |= MARK_ANY;
for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
cp->c_marks &= mark;
}
}
}
/*
* Mark the cells in a specified rectangular region as desired.
* Returns the number of cells which were marked.
*/
markregion(obj, mark, minrow, maxrow, mincol, maxcol)
struct object *obj; /* object to mark */
register int mark; /* value to mark with */
long minrow, maxrow, mincol, maxcol; /* range to mark */
{
register struct row *rp; /* current row */
register struct cell *cp; /* current cell */
register long count; /* count of cells */
count = 0;
for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
if (rp->r_row < minrow) continue;
if (rp->r_row > maxrow) break;
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
if (cp->c_col < mincol) continue;
if (cp->c_col > maxcol) break;
cp->c_marks |= mark;
count++;
}
}
return(count);
}
/*
* Find the range of all marked cells for an object. Returns nonzero if
* no cells were marked.
*/
markminmax(obj, mark, minrow, maxrow, mincol, maxcol)
struct object *obj; /* object to search */
register int mark; /* mark to search for */
long *minrow, *maxrow, *mincol, *maxcol; /* results */
{
register struct row *rp; /* current row */
register struct cell *cp; /* current cell */
register int row; /* current row */
long minr, maxr, minc, maxc; /* temp variables */
minr = INFINITY;
maxr = -INFINITY;
minc = INFINITY;
maxc = -INFINITY;
for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
row = rp->r_row;
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
if ((cp->c_marks & mark) == 0) continue;
if (row < minr) minr = row;
if (row > maxr) maxr = row;
if (cp->c_col < minc) minc = cp->c_col;
if (cp->c_col > maxc) maxc = cp->c_col;
}
}
if (minr > maxr) return(1);
*minrow = minr;
*maxrow = maxr;
*mincol = minc;
*maxcol = maxc;
return(0);
}
/* Count the number of marked cells in an object */
countmarks(obj, mark)
struct object *obj; /* object to check */
register int mark; /* mark to be counted */
{
register struct row *rp; /* row pointer */
register struct cell *cp; /* cell pointer */
register long count; /* number of cells */
count = 0;
for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
if (cp->c_marks & mark) count++;
}
}
return(count);
}
/*
* Move marked cells to another object. If the destination object is NULL
* the cells are just deleted. The previous cells of the destination object
* are deleted.
*/
movemarkedobject(sobj, dobj, mark)
register struct object *sobj; /* source object */
struct object *dobj; /* destination object */
{
register struct row *rp; /* row pointer */
register struct cell *cp; /* current cell pointer */
register struct cell *pcp; /* previous cell pointer */
register struct cell *ncp; /* next cell pointer */
if (sobj == dobj) error("Moving object to itself");
if (dobj) {
zeroobject(dobj);
dobj->o_currow = sobj->o_currow;
dobj->o_curcol = sobj->o_curcol;
}
for (rp = sobj->o_firstrow; rp != termrow; rp = rp->r_next) {
pcp = NULL;
cp = rp->r_firstcell;
while (cp != termcell) {
if ((cp->c_marks & mark) == 0) {
pcp = cp;
cp = cp->c_next;
continue;
}
if (dobj) addcell(dobj, rp->r_row, cp->c_col);
ncp = cp->c_next;
if (pcp == NULL)
rp->r_firstcell = ncp;
else
pcp->c_next = ncp;
if (ncp == termcell) rp->r_lastcell = pcp;
cp->c_next = freecells;
freecells = cp;
cp = ncp;
rp->r_count--;
sobj->o_count--;
}
}
}
/*
* Copy marked cells to another object. The previous cells of the destination
* object are deleted. The source object is unaffected.
*/
copymarkedobject(sobj, dobj, mark)
register struct object *sobj; /* source object */
register struct object *dobj; /* destination object */
register int mark; /* mark value */
{
register struct row *rp; /* row pointer */
register struct cell *cp; /* current cell */
if (sobj == dobj) error("Copying object to itself");
zeroobject(dobj);
dobj->o_currow = sobj->o_currow;
dobj->o_curcol = sobj->o_curcol;
for (rp = sobj->o_firstrow; rp != termrow; rp = rp->r_next) {
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
if ((cp->c_marks & mark) == 0) continue;
addcell(dobj, rp->r_row, cp->c_col);
}
}
}
/*
* Rotate the marked cells in the given object around the current cursor
* location. This deletes the marked cells, and reinserts them after
* their position has been rotated by 90 degrees clockwise.
*/
rotatemarkedobject(obj, mark)
register struct object *obj; /* current object */
{
register struct row *rp; /* current row */
register struct cell *cp; /* current cell */
register int row, col; /* current row and column */
if (obj == tempobject) error("Using temp object");
movemarkedobject(obj, tempobject, mark);
for (rp = tempobject->o_firstrow; rp != termrow; rp = rp->r_next) {
row = rp->r_row - obj->o_currow;
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
col = cp->c_col - obj->o_curcol;
addcell(obj, obj->o_currow + col, obj->o_curcol - row);
}
}
}
/*
* Flip the marked cells in the given object around the column of the current
* cursor location. This deletes the marked cells, and reinserts them after
* their position has been flipped around the vertical axis.
*/
flipmarkedobject(obj, mark)
register struct object *obj; /* current object */
{
register struct row *rp; /* current row */
register struct cell *cp; /* current cell */
register int row, col; /* current row and column */
if (obj == tempobject) error("Using temp object");
movemarkedobject(obj, tempobject, mark);
for (rp = tempobject->o_firstrow; rp != termrow; rp = rp->r_next) {
row = rp->r_row;
for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
col = cp->c_col - obj->o_curcol;
addcell(obj, row, obj->o_curcol - col);
}
}
}