Beispiel #1
0
        /*
         * Initialize the "vinfo" array
         *
         * Full Octagon (radius 20), Grids=1149
         *
         * Quadrant (south east), Grids=308, Slopes=251
         *
         * Octant (east then south), Grids=161, Slopes=126
         *
         * This function assumes that VINFO_MAX_GRIDS and VINFO_MAX_SLOPES
         * have the correct values, which can be derived by setting them to
         * a number which is too high, running this function, and using the
         * error messages to obtain the correct values.
         */
        public static int vinfo_init()
        {
            int i, g;
            long m;

            int num_grids = 0;

            int queue_head = 0;
            int queue_tail = 0;
            vinfo_type[] queue = new vinfo_type[VINFO_MAX_GRIDS*2];

            //Nick: initialize v_info here, fill it with new stuffs to play with instead of nulls
            for (int n = 0; n < vinfo.Count(); n++){
                vinfo[n] = new vinfo_type();
            }

            /* Make hack */
            vinfo_hack hack = new vinfo_hack();

            /* Analyze grids */
            for (int y = 0; y <= Misc.MAX_SIGHT; ++y)
            {
                //Triangular array? Weird... Triangle is on top right corner
                for (int x = y; x <= Misc.MAX_SIGHT; ++x)
                {
                    /* Skip grids which are out of sight range */
                    if (distance(0, 0, y, x) > Misc.MAX_SIGHT) continue;

                    /* Default slope range */
                    hack.slopes_min[y,x] = 999999999;
                    hack.slopes_max[y,x] = 0;

                    /* Paranoia */
                    if (num_grids >= VINFO_MAX_GRIDS)
                    {
                        Utilities.quit("Too many grids (" + num_grids + " >= " + VINFO_MAX_GRIDS + ")!");
                    }

                    /* Count grids */
                    num_grids++;

                    /* Slope to the top right corner */
                    m = SCALE * (1000L * y - 500) / (1000L * x + 500);

                    /* Handle "legal" slopes */
                    vinfo_init_aux(hack, y, x, m);

                    /* Slope to top left corner */
                    m = SCALE * (1000L * y - 500) / (1000L * x - 500);

                    /* Handle "legal" slopes */
                    vinfo_init_aux(hack, y, x, m);

                    /* Slope to bottom right corner */
                    m = SCALE * (1000L * y + 500) / (1000L * x + 500);

                    /* Handle "legal" slopes */
                    vinfo_init_aux(hack, y, x, m);

                    /* Slope to bottom left corner */
                    m = SCALE * (1000L * y + 500) / (1000L * x - 500);

                    /* Handle "legal" slopes */
                    vinfo_init_aux(hack, y, x, m);
                }
            }

            /* Enforce maximal efficiency */
            if (num_grids < VINFO_MAX_GRIDS)
            {
                Utilities.quit("Too few grids (" + num_grids + " < " + VINFO_MAX_GRIDS + ")!");
            }

            /* Enforce maximal efficiency */
            if (hack.num_slopes < VINFO_MAX_SLOPES)
            {
                Utilities.quit("Too few slopes (" + hack.num_slopes + " < " + VINFO_MAX_SLOPES + ")!");
            }

            Utilities.sort(hack.slopes, cmp_longs);

            /* Enqueue player grid */
            queue[queue_tail++] = vinfo[0];

            /* Process queue */
            while (queue_head < queue_tail)
            {
                int e;

                /* Index */
                e = queue_head++;

                /* Main Grid */
                g = vinfo[e].grid[0];

                /* Location */
                int y = GRID_Y(g);
                int x = GRID_X(g);

                /* Compute grid offsets */
                vinfo[e].grid[0] = (short)GRID(+y,+x);
                vinfo[e].grid[1] = (short)GRID(+x,+y);
                vinfo[e].grid[2] = (short)GRID(+x,-y);
                vinfo[e].grid[3] = (short)GRID(+y,-x);
                vinfo[e].grid[4] = (short)GRID(-y,-x);
                vinfo[e].grid[5] = (short)GRID(-x,-y);
                vinfo[e].grid[6] = (short)GRID(-x,+y);
                vinfo[e].grid[7] = (short)GRID(-y,+x);

                /* Analyze slopes */
                for (i = 0; i < hack.num_slopes; ++i)
                {
                    m = hack.slopes[i];

                    /* Memorize intersection slopes (for non-player-grids) */
                    if ((e > 0) && (hack.slopes_min[y,x] < m) && (m < hack.slopes_max[y,x]))
                    {
                        switch (i / 32)
                        {
                            case 3: vinfo[e].bits_3 |= (uint)(1L << (i % 32)); break;
                            case 2: vinfo[e].bits_2 |= (uint)(1L << (i % 32)); break;
                            case 1: vinfo[e].bits_1 |= (uint)(1L << (i % 32)); break;
                            case 0: vinfo[e].bits_0 |= (uint)(1L << (i % 32)); break;
                        }
                    }
                }

                /* Default */
                vinfo[e].next_0 = vinfo[0];

                /* Grid next child */
                if (distance(0, 0, y, x+1) <= Misc.MAX_SIGHT)
                {
                    g = GRID(y,x+1);

                    if (queue[queue_tail-1].grid[0] != g)
                    {
                        vinfo[queue_tail].grid[0] = (short)g;
                        queue[queue_tail] = vinfo[queue_tail];
                        queue_tail++;
                    }

                    vinfo[e].next_0 = vinfo[queue_tail - 1];
                }

                /* Default */
                vinfo[e].next_1 = vinfo[0];

                /* Grid diag child */
                if (distance(0, 0, y+1, x+1) <= Misc.MAX_SIGHT)
                {
                    g = GRID(y+1,x+1);

                    if (queue[queue_tail-1].grid[0] != g)
                    {
                        vinfo[queue_tail].grid[0] = (short)g;
                        queue[queue_tail] = vinfo[queue_tail];
                        queue_tail++;
                    }

                    vinfo[e].next_1 = vinfo[queue_tail - 1];
                }

                /* Hack -- main diagonal has special children */
                if (y == x) vinfo[e].next_0 = vinfo[e].next_1;

                /* Extra values */
                vinfo[e].y = (byte)y;
                vinfo[e].x = (byte)x;
                vinfo[e].d = (byte)((y > x) ? (y + x/2) : (x + y/2));
                vinfo[e].r = (byte)((y==0) ? x : (x==0) ? y : (y == x) ? y : 0);
            }

            /* Verify maximal bits XXX XXX XXX */
            if (((vinfo[1].bits_3 | vinfo[2].bits_3) != VINFO_BITS_3) ||
                ((vinfo[1].bits_2 | vinfo[2].bits_2) != VINFO_BITS_2) ||
                ((vinfo[1].bits_1 | vinfo[2].bits_1) != VINFO_BITS_1) ||
                ((vinfo[1].bits_0 | vinfo[2].bits_0) != VINFO_BITS_0))
            {
                Utilities.quit("Incorrect bit masks!");
            }

            /* Kill hack */
            //FREE(hack); //lolc

            /* Success */
            return (0);
        }
Beispiel #2
0
        /*
         * Calculate the complete field of view using a new algorithm
         *
         * If "view_g" and "temp_g" were global pointers to arrays of grids, as
         * opposed to actual arrays of grids, then we could be more efficient by
         * using "pointer swapping".
         *
         * Note the following idiom, which is used in the function below.
         * This idiom processes each "octant" of the field of view, in a
         * clockwise manner, starting with the east strip, south side,
         * and for each octant, allows a simple calculation to set "g"
         * equal to the proper grids, relative to "pg", in the octant.
         *
         *   for (o2 = 0; o2 < 8; o2++)
         *   ...
         *         g = pg + p.grid[o2];
         *   ...
         *
         *
         * Normally, vision along the major axes is more likely than vision
         * along the diagonal axes, so we check the bits corresponding to
         * the lines of sight near the major axes first.
         *
         * We use the "temp_g" array (and the "CAVE_TEMP" flag) to keep track of
         * which grids were previously marked "CAVE_SEEN", since only those grids
         * whose "CAVE_SEEN" value changes during this routine must be redrawn.
         *
         * This function is now responsible for maintaining the "CAVE_SEEN"
         * flags as well as the "CAVE_VIEW" flags, which is good, because
         * the only grids which normally need to be memorized and/or redrawn
         * are the ones whose "CAVE_SEEN" flag changes during this routine.
         *
         * Basically, this function divides the "octagon of view" into octants of
         * grids (where grids on the main axes and diagonal axes are "shared" by
         * two octants), and processes each octant one at a time, processing each
         * octant one grid at a time, processing only those grids which "might" be
         * viewable, and setting the "CAVE_VIEW" flag for each grid for which there
         * is an (unobstructed) line of sight from the center of the player grid to
         * any internal point in the grid (and collecting these "CAVE_VIEW" grids
         * into the "view_g" array), and setting the "CAVE_SEEN" flag for the grid
         * if, in addition, the grid is "illuminated" in some way.
         *
         * This function relies on a theorem (suggested and proven by Mat Hostetter)
         * which states that in each octant of a field of view, a given grid will
         * be "intersected" by one or more unobstructed "lines of sight" from the
         * center of the player grid if and only if it is "intersected" by at least
         * one such unobstructed "line of sight" which passes directly through some
         * corner of some grid in the octant which is not shared by any other octant.
         * The proof is based on the fact that there are at least three significant
         * lines of sight involving any non-shared grid in any octant, one which
         * intersects the grid and passes though the corner of the grid closest to
         * the player, and two which "brush" the grid, passing through the "outer"
         * corners of the grid, and that any line of sight which intersects a grid
         * without passing through the corner of a grid in the octant can be "slid"
         * slowly towards the corner of the grid closest to the player, until it
         * either reaches it or until it brushes the corner of another grid which
         * is closer to the player, and in either case, the existanc of a suitable
         * line of sight is thus demonstrated.
         *
         * It turns out that in each octant of the radius 20 "octagon of view",
         * there are 161 grids (with 128 not shared by any other octant), and there
         * are exactly 126 distinct "lines of sight" passing from the center of the
         * player grid through any corner of any non-shared grid in the octant.  To
         * determine if a grid is "viewable" by the player, therefore, you need to
         * simply show that one of these 126 lines of sight intersects the grid but
         * does not intersect any wall grid closer to the player.  So we simply use
         * a bit vector with 126 bits to represent the set of interesting lines of
         * sight which have not yet been obstructed by wall grids, and then we scan
         * all the grids in the octant, moving outwards from the player grid.  For
         * each grid, if any of the lines of sight which intersect that grid have not
         * yet been obstructed, then the grid is viewable.  Furthermore, if the grid
         * is a wall grid, then all of the lines of sight which intersect the grid
         * should be marked as obstructed for future reference.  Also, we only need
         * to check those grids for whom at least one of the "parents" was a viewable
         * non-wall grid, where the parents include the two grids touching the grid
         * but closer to the player grid (one adjacent, and one diagonal).  For the
         * bit vector, we simply use 4 32-bit integers.  All of the static values
         * which are needed by this function are stored in the large "vinfo" array
         * (above), which is machine generated by another program.  XXX XXX XXX
         *
         * Hack -- The queue must be able to hold more than VINFO_MAX_GRIDS grids
         * because the grids at the edge of the field of view use "grid zero" as
         * their children, and the queue must be able to hold several of these
         * special grids.  Because the actual number of required grids is bizarre,
         * we simply allocate twice as many as we would normally need.  XXX XXX XXX
         */
        public static void update_view()
        {
            int py = Misc.p_ptr.py;
            int px = Misc.p_ptr.px;

            int pg = GRID(py,px);

            int i, j, k, g, o2;

            int radius;

            int fast_view_n = view_n;
            ushort[] fast_view_g = view_g;

            int fast_temp_n = 0;
            ushort[] fast_temp_g = Misc.temp_g;

            /* XXX: also moronic. Optimizers exist. */
            //byte *fast_cave_info = &cave.info[0][0];
            //lolz, Nick: I am omitting this

            short info;

            /*** Step 0 -- Begin ***/

            /* Save the old "view" grids for later */
            for (i = 0; i < fast_view_n; i++)
            {
                /* Grid */
                g = fast_view_g[i];

                int x = GRID_X(g);
                int y = GRID_Y(g);

                /* Get grid info */
                //info = fast_cave_info[g];
                info = cave.info[y][x];

                /* Save "CAVE_SEEN" grids */
                if ((info & (CAVE_SEEN)) != 0)
                {
                    /* Set "CAVE_TEMP" flag */
                    info |= (CAVE_TEMP);

                    //NICK This is a hack, if we have seen it, we mark it...
                    info |= (CAVE_MARK);

                    /* Save grid for later */
                    fast_temp_g[fast_temp_n++] = (ushort)g;
                }

                /* Clear "CAVE_VIEW" and "CAVE_SEEN" flags */
                info &= ~(CAVE_VIEW | CAVE_SEEN);

                /* Clear "CAVE_LIGHT" flag */
                /* info &= ~(CAVE_LIGHT); */

                /* Save cave info */
                //fast_cave_info[g] = info;
                cave.info[y][x] = info;
            }

            /* Reset the "view" array */
            fast_view_n = 0;

            /* Extract "radius" value */
            radius = Misc.p_ptr.cur_light;

            /* Handle real light */
            if (radius > 0) ++radius;

            /* Scan monster list and add monster lights */
            for (k = 1; k < Misc.z_info.m_max; k++)
            {
                /* Check the k'th monster */
                Monster.Monster m_ptr = cave_monster(cave, k);
                if(m_ptr == null)
                    continue; //TODO: See why there were null monsters in the cave?
                Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx];

                /* Access the location */
                int fx = m_ptr.fx;
                int fy = m_ptr.fy;

                bool in_los = los(Misc.p_ptr.py, Misc.p_ptr.px, fy, fx);

                /* Skip dead monsters */
                if (m_ptr.r_idx == 0) continue;

                /* Skip monsters not carrying light */
                if (!r_ptr.flags.has(Monster_Flag.HAS_LIGHT.value)) continue;

                /* Light a 3x3 box centered on the monster */
                for (i = -1; i <= 1; i++)
                {
                    for (j = -1; j <= 1; j++)
                    {
                        int sy = fy + i;
                        int sx = fx + j;

                        /* If the monster isn't visible we can only light open tiles */
                        if (!in_los && !cave_floor_bold(sy, sx))
                            continue;

                        /* If the tile is too far away we won't light it */
                        if (distance(Misc.p_ptr.py, Misc.p_ptr.px, sy, sx) > Misc.MAX_SIGHT)
                            continue;

                        /* If the tile itself isn't in LOS, don't light it */
                        if (!los(Misc.p_ptr.py, Misc.p_ptr.px, sy, sx))
                            continue;

                        g = GRID(sy, sx);

                        /* Mark the square lit and seen */
                        //fast_cave_info[g] |= (CAVE_VIEW | CAVE_SEEN);
                        cave.info[sy][sx] |= (CAVE_VIEW | CAVE_SEEN);

                        /* Save in array */
                        fast_view_g[fast_view_n++] = (ushort)g;
                    }
                }
            }

            /*** Step 1 -- player grid ***/

            /* Player grid */
            g = pg;

            /* Get grid info */
            //info = fast_cave_info[g];
            int tx = GRID_X(g);
            int ty = GRID_Y(g);

            info = cave.info[ty][tx];

            /* Assume viewable */
            info |= (CAVE_VIEW);

            /* Torch-lit grid */
            if (0 < radius)
            {
                /* Mark as "CAVE_SEEN" */
                info |= (CAVE_SEEN);

                /* Mark as "CAVE_LIGHT" */
                /* info |= (CAVE_LIGHT); */
            }

            /* Perma-lit grid */
            else if ((info & (CAVE_GLOW)) != 0)
            {
                /* Mark as "CAVE_SEEN" */
                info |= (CAVE_SEEN);
            }

            /* Save cave info */
            //fast_cave_info[g] = info;
            cave.info[GRID_Y(g)][GRID_X(g)] = info;

            /* Save in array */
            fast_view_g[fast_view_n++] = (ushort)g;

            /*** Step 2 -- octants ***/

            /* Scan each octant */
            for (o2 = 0; o2 < 8; o2++)
            {
                vinfo_type p;

                /* Last added */
                vinfo_type last = vinfo[0];

                /* Grid queue */
                int queue_head = 0;
                int queue_tail = 0;
                vinfo_type[] queue = new vinfo_type[VINFO_MAX_GRIDS*2];
                for(int q = 0; q < queue.Length; q++) {
                    queue[q] = new vinfo_type(); //Gotta do this to avoid null references...
                }

                /* Slope bit vector */
                uint bits0 = (uint)VINFO_BITS_0;
                uint bits1 = (uint)VINFO_BITS_1;
                uint bits2 = (uint)VINFO_BITS_2;
                uint bits3 = (uint)VINFO_BITS_3;

                /* Reset queue */
                queue_head = queue_tail = 0;

                /* Initial grids */
                queue[queue_tail++] = vinfo[1];
                queue[queue_tail++] = vinfo[2];

                /* Process queue */
                while (queue_head < queue_tail)
                {
                    /* Dequeue next grid */
                    p = queue[queue_head++];

                    /* Check bits */
                    if ((bits0 & (p.bits_0)) != 0 ||
                        (bits1 & (p.bits_1)) != 0 ||
                        (bits2 & (p.bits_2)) != 0 ||
                        (bits3 & (p.bits_3)) != 0)
                    {
                        /* Extract grid value XXX XXX XXX */
                        g = pg + p.grid[o2];

                        /* Get grid info */
                        //info = fast_cave_info[g];
                        info = cave.info[GRID_Y(g)][GRID_X(g)];

                        /* Handle wall */
                        if ((info & (CAVE_WALL)) != 0)
                        {
                            /* Clear bits */
                            bits0 &= ~(p.bits_0);
                            bits1 &= ~(p.bits_1);
                            bits2 &= ~(p.bits_2);
                            bits3 &= ~(p.bits_3);

                            /* Newly viewable wall */
                            if ((info & (CAVE_VIEW)) == 0)
                            {
                                /* Mark as viewable */
                                info |= (CAVE_VIEW);

                                /* Torch-lit grids */
                                if (p.d < radius)
                                {
                                    /* Mark as "CAVE_SEEN" */
                                    info |= (CAVE_SEEN);

                                    /* Mark as "CAVE_LIGHT" */
                                    /* info |= (CAVE_LIGHT); */
                                }

                                /* Perma-lit grids */
                                else if ((info & (CAVE_GLOW)) != 0)
                                {
                                    int y = GRID_Y(g);
                                    int x = GRID_X(g);

                                    /* Hack -- move towards player */
                                    int yy = (y < py) ? (y + 1) : (y > py) ? (y - 1) : y;
                                    int xx = (x < px) ? (x + 1) : (x > px) ? (x - 1) : x;

                                    /* Check for "simple" illumination */
                                    if ((cave.info[yy][xx] & (CAVE_GLOW)) != 0)
                                    {
                                        /* Mark as seen */
                                        info |= (CAVE_SEEN);
                                    }
                                }

                                /* Save cave info */
                                //fast_cave_info[g] = info;
                                cave.info[GRID_Y(g)][GRID_X(g)] = info;

                                /* Save in array */
                                fast_view_g[fast_view_n++] = (ushort)g;
                            }
                        }

                        /* Handle non-wall */
                        else
                        {
                            /* Enqueue child */
                            if (last != p.next_0)
                            {
                                queue[queue_tail++] = last = p.next_0;
                            }

                            /* Enqueue child */
                            if (last != p.next_1)
                            {
                                queue[queue_tail++] = last = p.next_1;
                            }

                            /* Newly viewable non-wall */
                            if ((info & (CAVE_VIEW)) == 0)
                            {
                                /* Mark as "viewable" */
                                info |= (CAVE_VIEW);

                                /* Torch-lit grids */
                                if (p.d < radius)
                                {
                                    /* Mark as "CAVE_SEEN" */
                                    info |= (CAVE_SEEN);

                                    /* Mark as "CAVE_LIGHT" */
                                    /* info |= (CAVE_LIGHT); */
                                }

                                /* Perma-lit grids */
                                else if ((info & (CAVE_GLOW)) != 0)
                                {
                                    /* Mark as "CAVE_SEEN" */
                                    info |= (CAVE_SEEN);
                                }

                                /* Save cave info */
                                //fast_cave_info[g] = info;
                                cave.info[GRID_Y(g)][GRID_X(g)] = info;

                                /* Save in array */
                                fast_view_g[fast_view_n++] = (ushort)g;
                            }
                        }
                    }
                }
            }

            /*** Step 3 -- Complete the algorithm ***/

            /* Handle blindness */
            if (Misc.p_ptr.timed[(int)Timed_Effect.BLIND] != 0)
            {
                /* Process "new" grids */
                for (i = 0; i < fast_view_n; i++)
                {
                    /* Grid */
                    g = fast_view_g[i];

                    /* Grid cannot be "CAVE_SEEN" */
                    //fast_cave_info[g] &= ~(CAVE_SEEN);
                    cave.info[GRID_Y(g)][GRID_X(g)] &= ~(CAVE_SEEN);
                }
            }

            /* Process "new" grids */
            for (i = 0; i < fast_view_n; i++)
            {
                /* Grid */
                g = fast_view_g[i];

                /* Get grid info */
                //info = fast_cave_info[g];
                info = cave.info[GRID_Y(g)][GRID_X(g)];

                /* Was not "CAVE_SEEN", is now "CAVE_SEEN" */
                if (((info & (CAVE_SEEN)) != 0) && ((info & (CAVE_TEMP)) == 0))
                {
                    int y, x;

                    /* Location */
                    y = GRID_Y(g);
                    x = GRID_X(g);

                    /* Handle feeling squares */
                    if ((cave.info2[y][x] & CAVE2_FEEL) != 0)
                    {
                        cave.feeling_squares++;

                        /* Erase the square so you can't 'resee' it */
                        cave.info2[y][x] &= ~(CAVE2_FEEL);

                        /* Display feeling if necessary */
                        if (cave.feeling_squares == FEELING1)
                            Command.display_feeling(true);

                    }

                    cave_note_spot(cave, y, x);
                    cave_light_spot(cave, y, x);
                }
            }

            /* Process "old" grids */
            for (i = 0; i < fast_temp_n; i++)
            {
                /* Grid */
                g = fast_temp_g[i];

                /* Get grid info */
                //info = fast_cave_info[g];
                info = cave.info[GRID_Y(g)][GRID_X(g)];

                /* Clear "CAVE_TEMP" flag */
                info &= ~(CAVE_TEMP);

                /* Save cave info */
                //fast_cave_info[g] = info;
                cave.info[GRID_Y(g)][GRID_X(g)] = info;

                /* Was "CAVE_SEEN", is now not "CAVE_SEEN" */
                if ((info & (CAVE_SEEN)) == 0)
                {
                    int y, x;

                    /* Location */
                    y = GRID_Y(g);
                    x = GRID_X(g);

                    /* Redraw */
                    cave_light_spot(cave, y, x);
                }
            }

            /* Save 'view_n' */
            view_n = fast_view_n;

            //Nick: We might want to save these too? If wonky, comment out below
            view_g = fast_view_g;
            Misc.temp_g = fast_temp_g;
        }