Enhance AI
This commit is contained in:
parent
26a0fd884f
commit
26e48fd997
28 changed files with 208 additions and 69 deletions
|
|
@ -6,6 +6,7 @@
|
|||
#include "bitwise.h"
|
||||
#include "../../hardware_access/hardware_access.h"
|
||||
#include "../uart/receive.h"
|
||||
#include "../uart/transmit.h"
|
||||
|
||||
|
||||
// (0.5625 + (0.5625 + 1.6875) / 2) / 1000 / timer interval
|
||||
|
|
@ -36,7 +37,7 @@ static void saveCurrentByte() {
|
|||
uint8_t byte = infra.current;
|
||||
infra.current = 0;
|
||||
infra.bitPosition = 0;
|
||||
|
||||
|
||||
if (byte == INFRA_ADDRESS) {
|
||||
infra.commandState = foundStartingByte;
|
||||
return;
|
||||
|
|
@ -48,6 +49,7 @@ static void saveCurrentByte() {
|
|||
break;
|
||||
case significantByte:
|
||||
infra.onCommandReceived(byte);
|
||||
sendUintOnUartAsync(byte);
|
||||
infra.commandState = waitingForEndOfCommand;
|
||||
break;
|
||||
case waitingForEndOfCommand:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ void startFrameLoop(FrameFunction function, uint8_t frameLengthInMilliseconds) {
|
|||
previousFrameTime = milisecondsSinceFrameStart;
|
||||
|
||||
while (milisecondsSinceFrameStart < frameLengthInMilliseconds) {
|
||||
clearBit(MCUCR, SM1); // idle mode
|
||||
sleep_cpu();
|
||||
}
|
||||
|
||||
|
|
@ -27,6 +28,10 @@ void startFrameLoop(FrameFunction function, uint8_t frameLengthInMilliseconds) {
|
|||
}
|
||||
}
|
||||
|
||||
void powerOff() {
|
||||
setBit(MCUCR, SM1); // power-down mode
|
||||
sleep_cpu();
|
||||
}
|
||||
|
||||
ISR(TIM0_COMPA_vect) {
|
||||
milisecondsSinceFrameStart++;
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ static bool frameFunction(uint8_t previousFrameTime) {
|
|||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
tickObjects(previousFrameTime);
|
||||
handleCommands();
|
||||
handleAI();
|
||||
generateEvents();
|
||||
tickObjects(previousFrameTime);
|
||||
drawFrame();
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,17 @@
|
|||
#include <avr/io.h>
|
||||
|
||||
|
||||
// Setup the drivers, and business layer objects and their relations
|
||||
// It is kind of a very basic dependency injection.
|
||||
void setupConnections();
|
||||
|
||||
// Start drawing frames and ticking objects
|
||||
void startGame();
|
||||
|
||||
// Increase or decrease the contrast (brightness) of the display
|
||||
// by the given value
|
||||
// The contrast can be any number between 0 and 255.
|
||||
// The function automatically clamps the contrast.
|
||||
void changeDisplayContrast(int8_t by);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,12 +10,15 @@
|
|||
#include "../../util/random/random.h"
|
||||
#include "../../driver/display/display.h"
|
||||
|
||||
#define AI_ACTION_COUNT 5
|
||||
|
||||
#define AI_ACTION_COUNT 5
|
||||
|
||||
typedef bool (*Predicate)(Rectangle*, Object*);
|
||||
typedef void (*Execution)(Object*);
|
||||
|
||||
static uint8_t timeSinceLastAction;
|
||||
|
||||
|
||||
typedef struct {
|
||||
Predicate predicate;
|
||||
Execution execution;
|
||||
|
|
@ -70,29 +73,41 @@ static void carefullyMoveSpaceship(Object* astronaut, Vec2 target) {
|
|||
getCenter(getBoundingBox(spaceshipObject))
|
||||
)
|
||||
);
|
||||
moveAstronaut(astronaut, (Vec2){direction.x, 0});
|
||||
moveAstronaut(astronaut, (Vec2){0, direction.y});
|
||||
|
||||
moveAstronaut(astronaut, direction);
|
||||
}
|
||||
}
|
||||
|
||||
static bool shouldShootTurret(
|
||||
__attribute__((unused)) Rectangle* boundingBox,
|
||||
static void makeAiAstronautDoAction(Object* astronaut) {
|
||||
timeSinceLastAction = 0;
|
||||
makeAstronautDoAction(astronaut);
|
||||
}
|
||||
|
||||
static bool shouldControlTurret(
|
||||
__attribute__((unused)) Rectangle* boundingBox,
|
||||
__attribute__((unused)) Object* astronaut
|
||||
) {
|
||||
return getIntersectingObjectOfType(
|
||||
return getCountOf(&Asteroid) > 0;
|
||||
}
|
||||
|
||||
static void executeControlTurret(Object* astronaut) {
|
||||
if (getIntersectingObjectOfType(
|
||||
(Rectangle){
|
||||
add(TURRET_POSITION, spaceshipObject->position),
|
||||
(Vec2){63, 1}
|
||||
},
|
||||
&Asteroid
|
||||
);
|
||||
)) {
|
||||
makeAiAstronautDoAction(astronaut);
|
||||
};
|
||||
}
|
||||
|
||||
static bool shouldControlSpaceship(
|
||||
__attribute__((unused)) Rectangle* boundingBox,
|
||||
__attribute__((unused)) Rectangle* boundingBox,
|
||||
__attribute__((unused)) Object* astronaut
|
||||
) {
|
||||
return getCountOf(&Asteroid) > 0;
|
||||
return getCountOf(&Asteroid) > 0
|
||||
&& spaceshipObject->as.spaceship.healthLoss < MAX_HEALTH / 4 * 3;
|
||||
}
|
||||
|
||||
static void executeControlSpaceship(Object* astronaut) {
|
||||
|
|
@ -134,7 +149,7 @@ static void executeCenterSpaceship(Object* astronaut) {
|
|||
}
|
||||
|
||||
static bool shouldSocialize(
|
||||
__attribute__((unused)) Rectangle* boundingBox,
|
||||
__attribute__((unused)) Rectangle* boundingBox,
|
||||
__attribute__((unused)) Object* astronaut
|
||||
) {
|
||||
return true;
|
||||
|
|
@ -156,14 +171,14 @@ static AIAction actions[AI_ACTION_COUNT] = {
|
|||
},
|
||||
(AIAction) {
|
||||
.predicate = shouldRepairSpaceship,
|
||||
.execution = makeAstronautDoAction,
|
||||
.execution = makeAiAstronautDoAction,
|
||||
.spaceshipPart = spaceshipParts + BEDS_INDEX,
|
||||
.onlyOneAstronautCanDoIt = true,
|
||||
.deltaCenter = {2, 0}
|
||||
},
|
||||
(AIAction) {
|
||||
.predicate = shouldShootTurret,
|
||||
.execution = makeAstronautDoAction,
|
||||
.predicate = shouldControlTurret,
|
||||
.execution = executeControlTurret,
|
||||
.spaceshipPart = spaceshipParts + TURRET_CONTROLLER_INDEX,
|
||||
.onlyOneAstronautCanDoIt = true,
|
||||
.deltaCenter = {-3, 0}
|
||||
|
|
@ -185,6 +200,8 @@ static AIAction actions[AI_ACTION_COUNT] = {
|
|||
};
|
||||
|
||||
void handleAI() {
|
||||
timeSinceLastAction++;
|
||||
|
||||
for (uint8_t j = 0; j < ACTION_COUNT; j++) {
|
||||
actions[j].isSomeoneDoingThis = false;
|
||||
}
|
||||
|
|
@ -202,7 +219,7 @@ void handleAI() {
|
|||
) {
|
||||
if (!areIntersecting(boundingBox, getBoundingBox(objects + i))) {
|
||||
carefullyMoveAstronaut(objects + i, add(getCenter(boundingBox), currentAction->deltaCenter));
|
||||
} else {
|
||||
} else if (timeSinceLastAction > AI_ACTION_INTERVAL) {
|
||||
currentAction->execution(objects + i);
|
||||
}
|
||||
currentAction->isSomeoneDoingThis = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef AI_H
|
||||
#define AI_H
|
||||
|
||||
// Between AI astronauts do actions
|
||||
// there has to be at least this many frames
|
||||
#define AI_ACTION_INTERVAL 15
|
||||
|
||||
// If there are non player controlled astronauts
|
||||
// control them according to some basic rule set
|
||||
void handleAI();
|
||||
|
|
|
|||
|
|
@ -66,8 +66,9 @@ void moveAstronaut(Object* astronaut, Vec2 direction) {
|
|||
setWasDoingAction(astronaut, false);
|
||||
|
||||
if (getIsControllingSpaceship(astronaut)) {
|
||||
moveSpaceship(direction);
|
||||
} else {
|
||||
moveSpaceship((Vec2){direction.x, 0});
|
||||
moveSpaceship((Vec2){0, direction.y});
|
||||
} else {
|
||||
Vec2 proposedPosition = add(astronaut->position, direction);
|
||||
Rectangle proposedBoundingBox = (Rectangle){proposedPosition, getSize(astronaut)};
|
||||
if (isOnboard(proposedBoundingBox)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue