aboutsummaryrefslogtreecommitdiff
path: root/go/game/ai.go
blob: 18e589576c224a71149956ef541c197149c97366 (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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package game

func moveToRandomTile(s *State, u *Unit) {
	moveTargets := u.MoveRangeTiles(s.Map)
	if len(moveTargets) > 0 {
		moveTarget := moveTargets[s.Rand.Intn(len(moveTargets))-1]
		s.MoveUnit(u, moveTarget)
	}
}

func attackAttackableEnemyPerm(s *State, u *Unit) {
	attackablePerms := u.AttackablePermanents(s.Map)
	if len(attackablePerms) > 0 {
		attackablePerm := attackablePerms[s.Rand.Intn(len(attackablePerms))-1]
		s.Fight(u, attackablePerm)
	}
}

//  1. If enemy Unit in attack Range then
//     attack enemy Unit in Range
//  2. While move action available do
//     3a. If enemy unit exists
//     move towards nearest enemy unit until it is in attack range
//     if attack action avail then proceed at 1.
//     3b. Otherwise
//     move to random tile in movement range
func AggressiveAi(s *State, u *Unit) {
	// 1.
	attackAttackableEnemyPerm(s, u)

	// 2.
	if u.AvailMoveActions > 0 {
		enemyUnits := s.EnemyUnits(u.GetController())
		if len(enemyUnits) > 0 { // 3a.
			// TODO: implement path finding
			if u.AvailAttackActions > 0 {
				AggressiveAi(s, u)
			}
		} else { // 3b.
			moveToRandomTile(s, u)
		}
	}
}

// 2.2 Shy
//  1. If not in the attack Range of an enemy Unit then
//     activate full action if available
//  2. If move action available then
//     move to most distant point from all enemy units
//  3. If enemy Unit in attack Range then
//     attack enemy Unit in Range
func ShyAi(s *State, u *Unit) {
	// 1.
	inEnemyAttackRange := false
out:
	for _, enemyUnit := range s.EnemyUnits(u.GetController()) {
		for _, p := range enemyUnit.AttackablePermanents(s.Map) {
			if p == u {
				inEnemyAttackRange = true
				break out
			}
		}
	}
	if !inEnemyAttackRange && u.HasFullAction() {
		u.FullAction()
	}

	// 2.
	// TODO: implement path finding
	// if u.AvailMoveActions > 0 {
	// }

	// 3.
	if u.AvailAttackActions > 0 {
		attackAttackableEnemyPerm(s, u)
	}
}

// 2.3 Wandering X
//  1. If enemy unit in Range X then
//     execute aggressive AI
//  2. If move action available then
//     move to random tile in movement Range
//     proceed at 1.
func WanderingAi(s *State, u *Unit, x int) {
	// 1.
	for _, enemyUnit := range s.EnemyUnits(u.GetController()) {
		if IsPositionInRange(u.GetTile().Position, enemyUnit.GetTile().Position, x) {
			AggressiveAi(s, u)
			break
		}
	}
	// 2.
	if u.AvailMoveActions > 0 {
		moveToRandomTile(s, u)
		WanderingAi(s, u, x)
	}
}

// 2.4 Target-oriented TARGET
// 1. Use full action if possible
// 2a. If a TARGET exists and is reachable
//
//	Move onto or towards nearest TARGET
//	3a. If enemy Unit in attack Range
//	    attack enemy Unit in Range
//
// 2b. Otherwise
//
//	execute wandering 3 AI
func TargetOrientedAi(s *State, u *Unit, t *Position) {
	// 1.
	if u.HasFullAction() {
		u.FullAction()
	}

	if t != nil {
		// TODO: path finding again
		attackAttackableEnemyPerm(s, u)
	} else {
		WanderingAi(s, u, 3)
	}
}