aboutsummaryrefslogtreecommitdiff
path: root/game/ground.cpp
blob: e6055bfc61e030954ab1cff2887cc091d6430ef4 (plain)
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
94
95
96
97
98
99
100
101
102
#include "ground.h"
#include "gst.h"

#include <iostream>
#include <algorithm>

Ground::Ground (int sx, int sy) {
    sizex = sx; sizey = sy;
    tiles = new int[sx*sy];
    for (int i=0; i<sx*sy; i++) tiles[i] = 0;
}

Ground::~Ground () {
    
}

int Ground::at(int x, int y) {
    return x+y*sizex;
}


// areas
std::vector<int> Ground::star (int pos) {
    std::vector<int> fs;
    int x = pos % sizex, y = pos / sizex;
    if (x-1 >= 0) { fs.push_back(at(x-1, y)); }
    if (x+1 < sizex) { fs.push_back(at(x+1, y)); }
    if (y-1 >= 0) { fs.push_back(at(x, y-1)); }
    if (y+1 < sizey) { fs.push_back(at(x, y+1)); }
    return fs;
}

class step { public: 
    step(int pos, int m) : pos(pos), m(m) {};
    bool operator==(step oth) { return pos==oth.pos && m==oth.m; }
    bool operator==(int p) { return pos==p; }
    int pos, m; 
};

std::vector<int> Ground::move_area (Gst &gst, Entity &ent) {
    std::vector<int> moves;
    std::vector<int> visited { at(ent.x, ent.y) };
    std::vector<step> frontier { step { at(ent.x, ent.y), ent.info->move } };
    
    int maxcost = 99;
    if (gst.info_has_ability(ent.info, "Scout")) maxcost = 2;
    
    int iter=0;
    for (; iter<10000; iter++) {
        
        if (frontier.size() == 0) break;
        step maxf {-1, -1};
        for (step t : frontier) {
            if (t.m > maxf.m) {
                maxf.pos = t.pos;
                maxf.m = t.m;
            }
        }
        frontier.erase(std::remove(frontier.begin(), frontier.end(), maxf),
               frontier.end());
        auto forward_star = star(maxf.pos);
        for (int t : forward_star) {
            if (!(std::find(visited.begin(), visited.end(), t) != visited.end())
            && !(std::find(frontier.begin(), frontier.end(), t) != frontier.end())) {
                int movecost = gst.tiles[gst.ground.tiles[t]].move_cost;
                if (movecost > maxcost) movecost = maxcost;
                int walkedm = maxf.m - movecost;
                bool obstructed = false;
                for (Entity &e : gst.entities) {
                    if (e.owner != ent.owner && at(e.x, e.y) == t) {
                        obstructed = true;
                        break;
                    }
                }
                if (walkedm >= 0 && !obstructed) {
                    frontier.emplace_back(t, walkedm);
                    moves.push_back(t);
                }
            }
        }
        visited.push_back(maxf.pos);
    }
    
    std::cout << "iters: " << iter;
    
    return moves;
}

std::vector<int> Ground::attack_targets (Gst &gst, Entity &ent) {
    std::vector<int> attacks;
    int range = gst.get_range(ent);
    bool builds = !gst.info_has_ability(ent.info, "Units Only");
    bool units = !gst.info_has_ability(ent.info, "Buildings Only");
    for (Entity &e : gst.entities) {
        if (!units && e.info->unit == 1) continue;
        if (!builds && e.info->unit == 0) continue;
        if (e.owner != ent.owner && abs(e.x-ent.x)+abs(e.y-ent.y) <= range) {
            attacks.push_back(at(e.x, e.y));
        }
    }
    return attacks;
}