aboutsummaryrefslogtreecommitdiff
path: root/game/ai/generator.h
blob: c6cb2881346b81fcfecfc8e2bfee4481d8619def (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
#ifndef GENERATOR_H
#define GENERATOR_H

#include <iostream>

#include <string>
#include <vector>

#include "../ground.h"
#include "../gst.h"
#include "action.h"
#include "tactic.h"
#include "performer.h"

namespace ai {
    
const int maxiter = 100000;


class generator {
    public:
    generator (Gst &gst) : init(gst) {}
    Gst &init;
    
    std::vector<action> valid_actions (Gst &gst) {
        Ground &gr = gst.inv->ground;
        std::vector<action> acts;
        for (Entity &ent : gst.entities) {
            if (ent.done) continue;
            if (ent.owner != gst.turn) continue;
            
            std::vector<action> ent_acts;
            
            std::vector<int> moves = gr.move_area(gst, ent);
            for (auto move : moves) {
                int mx = move%gr.sizex, my = move/gr.sizex;
                action act { actype::move, ent.x, ent.y, mx, my };
                
                performer perf { gst };
                Gst next { gst };
                next = perf.act(next, act);
                Entity &matk = next.get_at(mx, my);
                std::vector<int> atks = gr.attack_targets(next, matk);
                for (auto atk : atks) {
                    int tx = atk%gr.sizex, ty = atk/gr.sizex;
                    action act_atk { actype::attack, ent.x, ent.y, 
                        mx, my, tx, ty };
                    Entity &mdef = next.get_at(tx, ty);
                    
                    BattleResult res = gst.battle_res(matk, mdef);
                    float heur = (mdef.hp-res.def_hp);
                    heur *= (mdef.info->cost[0] + mdef.info->cost[1]);
                    act_atk.heuristic = heur;
                    ent_acts.push_back(act_atk);
                }
                
                int dist = 999999;
                int pos = gst.get_nearest_enemy(ent, dist);
                float heur = 1.0f/dist;
                act.heuristic = heur;
                ent_acts.push_back(act);
            }
            std::sort(ent_acts.begin(), ent_acts.end(), compare_action);
            for (int i=0; i<3 && i<ent_acts.size(); i++) {
                acts.push_back(ent_acts[i]);
            }
        }
        std::sort(acts.begin(), acts.end(), compare_action);
        return acts;
    }
    
    tactic valid_tactic (int &n) {
        tactic t;
        Gst gst { init };
        for (int i=0; i<ai::maxiter; i++) {
            std::vector<action> acts { valid_actions(gst) };
            if (acts.size() == 0) break;
            performer perf { gst };
            int j = n % (acts.size()); 
            n /= acts.size();
            action &act = acts[j];
            gst = perf.act(gst, act);
            t.acts.push_back(act);
            //std::cout << act.to_string() << std::endl;
        }
        return t;
    }
    
    std::vector<tactic> tactics () {
        std::vector<tactic> ts;
        for (int i=0; i<3; i++) {
            int n = i;
            tactic t = valid_tactic(n);
            if (n > 0) break;
            ts.push_back(t); 
        }
        return ts;
    }
};

}
#endif