File: losglobal.cc

package info (click to toggle)
crawl 2%3A0.7.1-3
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 30,420 kB
  • ctags: 23,018
  • sloc: cpp: 244,317; ansic: 16,144; perl: 2,214; makefile: 984; python: 488; objc: 250; ruby: 200; sh: 140
file content (93 lines) | stat: -rw-r--r-- 2,545 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "AppHdr.h"

#include "losglobal.h"

#include "coord.h"
#include "coordit.h"
#include "fixedarray.h"
#include "los_def.h"

typedef unsigned char losfield_t;
typedef losfield_t halflos_t[LOS_MAX_RANGE+1][2*LOS_MAX_RANGE+1];
static const int o_half_x = 0;
static const int o_half_y = LOS_MAX_RANGE;
typedef halflos_t globallos_t[GXM][GYM];

static globallos_t globallos;

static losfield_t* _lookup_globallos(const coord_def& p, const coord_def& q)
{
    if (!map_bounds(p) || !map_bounds(q))
        return (NULL);
    coord_def diff = q - p;
    if (diff.rdist() > LOS_MAX_RANGE)
        return (NULL);
    // p < q iff p.x < q.x || p.x == q.x && p.y < q.y
    if (diff < coord_def(0, 0))
        return (&globallos[q.x][q.y][-diff.x + o_half_x][-diff.y + o_half_y]);
    else
        return (&globallos[p.x][p.y][ diff.x + o_half_x][ diff.y + o_half_y]);
}

static void _save_los(los_def* los, los_type l)
{
    const coord_def o = los->get_center();
    for (radius_iterator ri(o, LOS_MAX_RANGE, C_SQUARE); ri; ++ri)
    {
        losfield_t* flags = _lookup_globallos(o, *ri);
        if (!flags)
            continue;
        // XXX: we're assuming that if one type of LOS is updated,
        //      all will be.
        *flags &= ~LOS_FLAG_INVALID;
        if (los->see_cell(*ri))
            *flags |= l;
        else
            *flags &= ~l;
    }
}

// Opacity at p has changed.
void invalidate_los_around(const coord_def& p)
{
    const coord_def tl = p - coord_def(LOS_MAX_RANGE, LOS_MAX_RANGE);
    const coord_def br = p + coord_def(0, LOS_MAX_RANGE);
    // We're wiping out a little more than required here.
    for (rectangle_iterator ri(tl, br); ri; ++ri)
        if (map_bounds(*ri))
            memset(globallos[ri->x][ri->y], LOS_FLAG_INVALID, sizeof(halflos_t));
}

void invalidate_los()
{
    for (rectangle_iterator ri(0); ri; ++ri)
        memset(globallos[ri->x][ri->y], LOS_FLAG_INVALID, sizeof(halflos_t));
}

static void _update_globallos_at(const coord_def& p)
{
    los_def los(p, opc_default);
    los.update();
    _save_los(&los, LOS_DEFAULT);
    los.set_opacity(opc_no_trans);
    los.update();
    _save_los(&los, LOS_NO_TRANS);
}

bool cell_see_cell(const coord_def& p, const coord_def& q, los_type l)
{
    if (l == LOS_ARENA)
        return (true);

    losfield_t* flags = _lookup_globallos(p, q);

    if (!flags)
        return (false); // outside range

    if (*flags & LOS_FLAG_INVALID)
        _update_globallos_at(p);

    ASSERT(!(*flags & LOS_FLAG_INVALID));

    return (*flags & l);
}