Created
May 22, 2010 21:50
-
-
Save raptium/410393 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Tank.h" | |
#include <string.h> | |
#include <cstdio> | |
#include <cstdlib> | |
#include <climits> | |
#include <cmath> | |
namespace net { | |
namespace raptium { | |
// Operator Overloading for sturct Points | |
bool operator== (Point a, Point b) { | |
return (a.col == b.col && a.row == b.row); | |
} | |
Point operator-(Point a, Point b) { | |
Point p; | |
p.row = a.row - b.row; | |
p.col = a.col - b.col; | |
return p; | |
} | |
Point operator+(Point a, Point b) { | |
Point p; | |
p.row = a.row + b.row; | |
p.col = a.col + b.col; | |
return p; | |
} | |
Point operator*(Point a, int b) { | |
Point p; | |
p.row = a.row * b; | |
p.col = a.col * b; | |
return p; | |
} | |
class Tank { | |
protected: | |
int **_costs; | |
short _id; | |
DataForAI _data; | |
Point offset[4]; | |
void nextStep(Point start); | |
void init(); | |
public: | |
Point position; | |
Tank(); | |
Tank(DataForAI data); | |
~Tank(); | |
void update(DataForAI data); | |
void print(); | |
static OrderType nextDirection(Point start, Point end); | |
bool detectCollision(Point next); | |
CellType detectCellType(Point p); | |
Point findNextPoint(Point end); | |
Point destination; | |
Point next; | |
int cost; | |
virtual Point findTarget(); | |
virtual Point findDestination(); | |
virtual Order makeOrder(); | |
}; | |
class TankPioneer : Tank { | |
public: | |
Point findTarget(); | |
//Order makeOrder(); | |
}; | |
class TankSniper : Tank { | |
public: | |
Order makeOrder(); | |
}; | |
class StupidAI { | |
void solveCollision(); | |
public: | |
StupidAI(); | |
~StupidAI(); | |
InitiateInfo getInitInfo(); | |
Order makeOrder(DataForAI data); | |
Tank *tanks[5]; | |
static bool isValidPoint(Point p); | |
}; | |
} | |
} | |
using namespace net::raptium; | |
static StupidAI *AI; | |
Tank::Tank() { | |
init(); | |
} | |
Tank::Tank(DataForAI data) { | |
init(); | |
update(data); | |
} | |
void Tank::init() { | |
// init offset array | |
offset[0].col = 0; | |
offset[0].row = -1; | |
offset[1].col = 0; | |
offset[1].row = +1; | |
offset[2].col = -1; | |
offset[2].row = 0; | |
offset[3].col = +1; | |
offset[3].row = 0; | |
this->_costs = NULL; | |
} | |
void Tank::update(DataForAI data) { | |
_data = data; | |
_id = data.myID % 5; | |
if(_costs == NULL) { | |
_costs = new int *[MAP_HEIGHT + 2]; | |
for(int i = 0;i < MAP_HEIGHT + 2;i++) { | |
_costs[i] = new int[MAP_WIDTH + 2]; | |
} | |
} | |
for(int i = 0;i < MAP_HEIGHT + 2;i++) { | |
for(int j = 0;j < MAP_WIDTH + 2;j++) { | |
switch(data.map[i][j].type) { | |
case STONE: | |
_costs[i][j] = -1; | |
break; | |
default: | |
_costs[i][j] = INT_MAX; | |
} | |
} | |
} | |
Point tank_pos; | |
tank_pos.col = data.tank[data.myID].col; | |
tank_pos.row = data.tank[data.myID].row; | |
position = tank_pos; | |
_costs[tank_pos.row][tank_pos.col] = 0; | |
nextStep(tank_pos); | |
} | |
Tank::~Tank() { | |
for(int i = 0;i < MAP_HEIGHT + 2;i++) { | |
delete this->_costs[i]; | |
} | |
delete this->_costs; | |
} | |
void Tank::nextStep(Point start) { | |
Point next; | |
int cost; | |
for(int i = 0;i < 4;i++) { | |
next.col = start.col + offset[i].col; | |
next.row = start.row + offset[i].row; | |
if(!StupidAI::isValidPoint(next)) | |
continue; | |
if(_costs[next.row][next.col] >= 0) { | |
cost = _costs[start.row][start.col] + 1; | |
switch(_data.map[next.row][next.col].type) { | |
case BREAKBRICK: | |
cost += 1; | |
break; | |
case BRICK: | |
cost += 2; | |
break; | |
} | |
if(cost < _costs[next.row][next.col]) { | |
_costs[next.row][next.col] = cost; | |
nextStep(next); | |
} | |
} | |
} | |
} | |
Point Tank::findNextPoint(Point end) { | |
Point next; | |
for(int i = 0;i < 4;i++) { | |
next.col = end.col + offset[i].col; | |
next.row = end.row + offset[i].row; | |
if(!StupidAI::isValidPoint(next)) | |
continue; | |
if(_costs[next.row][next.col] == 0) | |
return end; | |
if(_costs[next.row][next.col] > 0 && _costs[next.row][next.col] < _costs[end.row][end.col]) | |
return findNextPoint(next); | |
} | |
return end; | |
} | |
void Tank::print() { | |
for(int i = 0;i < MAP_HEIGHT + 2;i++) { | |
for(int j = 0;j < MAP_WIDTH + 2;j++) { | |
printf("%3d", _costs[i][j]); | |
} | |
printf("\n"); | |
} | |
} | |
OrderType Tank::nextDirection(Point start, Point end) { | |
int dx = end.row - start.row; | |
int dy = end.col - start.col; | |
if(dx == -1) | |
return GOUP; | |
if(dx == 1) | |
return GODOWN; | |
if(dy == -1) | |
return GOLEFT; | |
if(dy == 1) | |
return GORIGHT; | |
return STOP; | |
} | |
Point Tank::findDestination() { | |
Point p; | |
Point sourceP; | |
Point minP; | |
int found; | |
int minCost; | |
int count; | |
minCost = INT_MAX; | |
minP.col = 0; | |
minP.row = 0; | |
cost = INT_MAX; | |
for(int i = 0;i < 13;i++) { | |
count = 0; | |
sourceP = _data.source[i]; | |
if (sourceP.row <=0) | |
continue; | |
// already own | |
SourceType sType = _data.map[sourceP.row][sourceP.col].isHereSource; | |
if(sType == BlueSource && _data.myFlag == BLUE) | |
continue; | |
if(sType == RedSource && _data.myFlag == RED) | |
continue; | |
// check if teammate's destination | |
for(int j = 0;j < 5;j++) { | |
if(sourceP == AI->tanks[j]->destination && j != _id) { | |
if(AI->tanks[j]->cost < _costs[sourceP.row][sourceP.col]) | |
count++; | |
} | |
} | |
if(count > 0 && !(destination == sourceP)) | |
continue; | |
if(_costs[sourceP.row][sourceP.col] < minCost) { | |
minCost = _costs[sourceP.row][sourceP.col]; | |
minP = sourceP; | |
cost = minCost; | |
} | |
} | |
return minP; | |
} | |
bool Tank::detectCollision(Point next){ | |
int tank_id = _data.map[next.row][next.col].whoIsHere; | |
if ( tank_id != -1){ | |
if ( _data.tank[tank_id].flag == _data.myFlag){ | |
if(AI->tanks[tank_id % 5]->next == position) | |
return true; | |
} | |
} | |
return false; | |
}; | |
CellType Tank:: detectCellType(Point p) { | |
return _data.map[p.row][p.col].type; | |
} | |
Point Tank::findTarget(){ | |
short range = _data.tank[_data.myID].range; | |
Point p; | |
for (int dx = -range;dx <= range;dx++){ | |
for(int dy = -range;dy <= range;dy++) { | |
if(abs(dx) + abs(dy) > range) | |
continue; | |
p.row = position.row + dx; | |
p.col = position.col + dy; | |
//printf("(%d, %d) =>Fire (%d, %d).\n", position.row, position.col, p.row, p.col); | |
if(!StupidAI::isValidPoint(p)) | |
continue; | |
if (_data.map[p.row][p.col].whoIsHere != -1){ | |
short tank_id = _data.map[p.row][p.col].whoIsHere; | |
if (_data.tank[tank_id].flag != _data.myFlag) | |
return p; | |
} | |
if (this->detectCellType(p) == BREAKBRICK || this->detectCellType(p) == BRICK) { | |
for(int i = 0;i < 5;i++) { | |
if(p == AI->tanks[i]->next) { | |
return p; | |
} | |
} | |
} | |
} | |
} | |
p.row = 0; | |
p.col = 0; | |
return p; | |
} | |
Order Tank::makeOrder() { | |
Order order; | |
Point tmpPoint; | |
tmpPoint.col = 0; | |
tmpPoint.row = 0; | |
Point target = this->findTarget(); | |
if (target.row){ | |
order.type = FIRE; | |
order.row = target.row; | |
order.col = target.col; | |
return order; | |
} | |
Point dest = this->findDestination(); | |
Point next; | |
if(dest.col) { | |
next = this->findNextPoint(dest); | |
order.type = Tank::nextDirection(position, next); | |
destination = dest; | |
next = next; | |
} else { | |
order.type = STOP; | |
destination = tmpPoint; | |
next = tmpPoint; | |
} | |
return order; | |
} | |
bool StupidAI::isValidPoint(Point p) { | |
if(p.col <= 0 || p.col >= MAP_WIDTH + 1) | |
return false; | |
if(p.row <= 0 || p.row >= MAP_HEIGHT + 1) | |
return false; | |
return true; | |
} | |
StupidAI::StupidAI() { | |
tanks[0] = (Tank *)new TankPioneer(); | |
tanks[1] = (Tank *)new Tank(); | |
tanks[2] = (Tank *)new TankSniper(); | |
tanks[3] = (Tank *)new TankSniper(); | |
tanks[4] = (Tank *)new Tank(); | |
} | |
StupidAI::~StupidAI() { | |
for(int i = 0;i < 5;i++) { | |
delete tanks[i]; | |
} | |
} | |
InitiateInfo StupidAI::getInitInfo() { | |
InitiateInfo Info; | |
Info.tank[0] = Pioneer; | |
Info.tank[1] = Striker; | |
Info.tank[2] = Sniper; | |
Info.tank[3] = Sniper; | |
Info.tank[4] = Striker; | |
strcpy(Info.aiName, "Stupid AI"); | |
return Info; | |
} | |
Order StupidAI::makeOrder(DataForAI data) { | |
int id = data.myID % 5; | |
tanks[id]->update(data); | |
Tank *tank = tanks[id]; | |
Order order = tank->makeOrder(); | |
// solve collision | |
Point next = tank->next; | |
if(StupidAI::isValidPoint(next)){ | |
if (tank->detectCollision(next)){ | |
short dx = next.row - tank->position.row; | |
short dy = next.col - tank->position.col; | |
next.row = tank->position.row + dy; | |
next.col = tank->position.col + dx; | |
if (tank->detectCellType(next) == STONE){ | |
next.row = tank->position.row - dy; | |
next.col = tank->position.col - dx; | |
} | |
} | |
tank->next = next; | |
order.type = Tank::nextDirection(tank->position, next); | |
} | |
return order; | |
} | |
Point TankPioneer::findTarget(){ | |
short range = 1; | |
Point p; | |
for (int dx = -1;dx <= 1;dx++){ | |
for (int dy = -1;dy <= 1;dy++){ | |
p.row = position.row + dx; | |
p.col = position.col + dy; | |
if(abs(dx) + abs(dy) > 1) | |
continue; | |
//printf("Fire (%d, %d).\n", p.row, p.col); | |
if(!StupidAI::isValidPoint(p)) | |
continue; | |
if (_data.map[p.row][p.col].whoIsHere != -1){ | |
short tank_id = _data.map[p.row][p.col].whoIsHere; | |
if (_data.tank[tank_id].flag != _data.myFlag) { | |
if(_data.tank[tank_id].life >= _data.tank[_data.myID].life) { | |
return p; | |
} | |
} | |
} | |
if (this->detectCellType(p) == BREAKBRICK || this->detectCellType(p) == BRICK) { | |
for(int i = 0;i < 5;i++) { | |
if(p == AI->tanks[i]->next) { | |
return p; | |
} | |
} | |
} | |
} | |
} | |
p.row = 0; | |
p.col = 0; | |
return p; | |
} | |
/* | |
Order TankPioneer::makeOrder() { | |
Order order; | |
Point tmpPoint; | |
tmpPoint.col = 0; | |
tmpPoint.row = 0; | |
// Pioneer never shots tanks | |
Point dest = this->findDestination(); | |
Point next; | |
if(dest.col) { | |
next = this->findNextPoint(dest); | |
order.type = Tank::nextDirection(position, next); | |
destination = dest; | |
next = next; | |
} else { | |
order.type = STOP; | |
destination = tmpPoint; | |
next = tmpPoint; | |
} | |
if (this->detectCellType(next) == BRICK || this->detectCellType(next) == BREAKBRICK) { | |
order.type = FIRE; | |
order.col = next.col; | |
order.row = next.row; | |
next = position; | |
} | |
return order; | |
} | |
*/ | |
Order TankSniper::makeOrder() { | |
Order order; | |
Point tmpPoint; | |
tmpPoint.col = 0; | |
tmpPoint.row = 0; | |
// Sniper shots tanks | |
Point target = this->findTarget(); | |
if (target.row){ | |
order.type = FIRE; | |
order.row = target.row; | |
order.col = target.col; | |
return order; | |
} | |
Point dest = this->findDestination(); | |
Point next; | |
if(dest.col) { | |
next = this->findNextPoint(dest); | |
order.type = Tank::nextDirection(position, next); | |
destination = dest; | |
next = next; | |
} else { | |
order.type = STOP; | |
destination = tmpPoint; | |
next = tmpPoint; | |
} | |
if (this->detectCellType(next) == BRICK || this->detectCellType(next) == BREAKBRICK) { | |
order.type = FIRE; | |
order.col = next.col; | |
order.row = next.row; | |
next = position; | |
} | |
return order; | |
} | |
extern "C" InitiateInfo chooseType() | |
{ | |
AI = new StupidAI(); | |
return AI->getInitInfo(); | |
} | |
extern "C" Order makeOrder(DataForAI data) | |
{ | |
return AI->makeOrder(data); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
include "Tank.h"
include <string.h>
include
include
include
include
namespace net {
namespace raptium {
}
using namespace net::raptium;
static StupidAI *AI;
Tank::Tank() {
init();
}
Tank::Tank(DataForAI data) {
init();
update(data);
}
void Tank::init() {
}
void Tank::update(DataForAI data) {
_data = data;
_id = data.myID % 5;
}
Tank::~Tank() {
for(int i = 0;i < MAP_HEIGHT + 2;i++) {
delete this->_costs[i];
}
delete this->_costs;
}
void Tank::nextStep(Point start) {
Point next;
int cost;
}
Point Tank::findNextPoint(Point end) {
Point next;
}
void Tank::print() {
for(int i = 0;i < MAP_HEIGHT + 2;i++) {
for(int j = 0;j < MAP_WIDTH + 2;j++) {
printf("%3d", _costs[i][j]);
}
printf("\n");
}
}
OrderType Tank::nextDirection(Point start, Point end) {
int dx = end.row - start.row;
int dy = end.col - start.col;
if(dx == -1)
return GOUP;
if(dx == 1)
return GODOWN;
if(dy == -1)
return GOLEFT;
if(dy == 1)
return GORIGHT;
return STOP;
}
Point Tank::findDestination() {
Point p;
Point sourceP;
Point minP;
int found;
int minCost;
int count;
}
bool Tank::detectCollision(Point next){
int tank_id = _data.map[next.row][next.col].whoIsHere;
if ( tank_id != -1){
if ( _data.tank[tank_id].flag == _data.myFlag){
if(AI->tanks[tank_id % 5]->next == position)
return true;
}
}
return false;
};
CellType Tank:: detectCellType(Point p) {
return _data.map[p.row][p.col].type;
}
Point Tank::findTarget(){
short range = _data.tank[_data.myID].range;
Point p;
for (int dx = -range;dx <= range;dx++){
for(int dy = -range;dy <= range;dy++) {
}
Order Tank::makeOrder() {
Order order;
}
bool StupidAI::isValidPoint(Point p) {
if(p.col <= 0 || p.col >= MAP_WIDTH + 1)
return false;
if(p.row <= 0 || p.row >= MAP_HEIGHT + 1)
return false;
return true;
}
StupidAI::StupidAI() {
tanks[0] = (Tank *)new TankPioneer();
tanks[1] = (Tank *)new Tank();
tanks[2] = (Tank *)new TankSniper();
tanks[3] = (Tank *)new TankSniper();
tanks[4] = (Tank *)new Tank();
}
StupidAI::~StupidAI() {
for(int i = 0;i < 5;i++) {
delete tanks[i];
}
}
InitiateInfo StupidAI::getInitInfo() {
InitiateInfo Info;
Info.tank[0] = Pioneer;
Info.tank[1] = Striker;
Info.tank[2] = Sniper;
Info.tank[3] = Sniper;
Info.tank[4] = Striker;
strcpy(Info.aiName, "Stupid AI");
return Info;
}
Order StupidAI::makeOrder(DataForAI data) {
}
Point TankPioneer::findTarget(){
short range = 1;
Point p;
}
/*
Order TankPioneer::makeOrder() {
Order order;
}
*/
Order TankSniper::makeOrder() {
Order order;
}
extern "C" InitiateInfo chooseType()
{
AI = new StupidAI();
return AI->getInitInfo();
}
extern "C" Order makeOrder(DataForAI data)
{
return AI->makeOrder(data);
}