Skip to content

Commit

Permalink
init proj
Browse files Browse the repository at this point in the history
  • Loading branch information
misakamm committed Jul 15, 2015
1 parent 301d8f0 commit 3c6ebb0
Show file tree
Hide file tree
Showing 56 changed files with 13,102 additions and 675 deletions.
676 changes: 1 addition & 675 deletions LICENSE

Large diffs are not rendered by default.

168 changes: 168 additions & 0 deletions dllai/ai.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include "ai.h"

namespace AI {
int Evaluate(const GameField& field, int att, int clear, int depth, int player) {
int score = 0;
int field_w = field.width(), field_h = field.height();
int min_y[32] = {0};
struct factor {
int hole, h_change, y_factor, h_variance, att, noattclear;
} ai_factor_l[3] = {
{-50, -5, -10, -10, 40, -30},
{-50, -5, -10, -10, 30, -35},
{-50, -5, -10, -10, 20, -35},
};
factor ai_factor;
if ( depth > 2 ) ai_factor = ai_factor_l[2];
else ai_factor = ai_factor_l[depth];

// get all columns height
{
int beg_y = 0;
while ( field.row[beg_y] == 0 ) ++beg_y;
for ( int x = 0; x < field_w; ++x) {
for ( int y = beg_y, ey = field_h + 1; y <= ey; ++y) {
if ( field.row[y] & ( 1 << x ) ) {
min_y[x] = y;
break;
}
}
}
}
min_y[field_w] = min_y[field_w-2];
// find holes
{
int hole_score = 0;
for ( int x = 0; x < field_w; ++x) {
for ( int y = min_y[x] + 1; y <= field_h; ++y) {
if ( ( field.row[y] & ( 1 << x ) ) == 0) {
hole_score += ai_factor.hole;
}
}
}
score += hole_score;
}
// height change
{
int last = min_y[1];
for ( int x = 0; x <= field_w; last = min_y[x], ++x) {
int v = min_y[x] - last;
int absv = abs(v);
score += absv * ai_factor.h_change;
}
}
// variance
{
int h_variance_score = 0;
int avg = 0;
{
int sum = 0;
int sample_cnt = 0;
for ( int x = 0; x < field_w; ++x) {
avg += min_y[x];
}
{
double h = field_h - (double)avg / field_w;
score += int(ai_factor.y_factor * h * h / field_h);
}
for ( int x = 0; x < field_w; ++x) {
int t = avg - min_y[x] * field_w;
if ( abs(t) > field_h * field_w / 4 ) {
if ( t > 0 ) t = field_h * field_w / 4;
else t = -(field_h * field_w / 4);
}
sum += t * t;
++sample_cnt;
}
if ( sample_cnt > 0 ) {
h_variance_score = sum * ai_factor.h_variance / (sample_cnt * 100);
}
score += h_variance_score;
}
}
// clear and attack
if ( clear > 0 )
{
if ( depth > 0 ) {
score += int( att * ai_factor.att * ((double)att / clear - 0.7) );
} else {
score += att * ai_factor.att;
}
if ( att == 0 ) {
score += clear * ai_factor.noattclear;
}
}
return score;
}
int pasteClearAttack(GameField& field, int gemnum, int x, int y, int spin, signed char wallkick_spin, int &att) {
wallkick_spin = field.WallKickValue(gemnum, x, y, spin, wallkick_spin);
field.paste(x, y, getGem(gemnum, spin));
int clear = field.clearLines( wallkick_spin );
att = field.getAttack( clear, wallkick_spin );
return clear;
}
MovingSimple AISearch(const GameField& field, Gem cur, bool curCanHold, int x, int y, const std::vector<Gem>& next
, bool canhold, int upcomeAtt, int level, int player
, int maxdepth, int* pscore, int lastatt, int lastclear, int depth) {

std::vector<MovingSimple> movs;
if ( pscore ) *pscore = SCORE_LOSE;
GenMoving(field, movs, cur, x, y, false);
if ( movs.empty() ) {
return MovingSimple();
}
if ( maxdepth > level ) maxdepth = level;

MovingSimple best;
int maxScore = SCORE_LOSE;
for (size_t i = 0; i < movs.size() ; ++i) {
GameField newfield = field;
int clear, att;
clear = pasteClearAttack(newfield, cur.num, movs[i].x, movs[i].y, movs[i].spin, movs[i].wallkick_spin, att);
int score = 0;
if ( maxdepth > 0 && next.size() > 0) {
std::vector<Gem> newnext( next.begin() + 1, next.end() );
AISearch(newfield, next[0], canhold, gem_beg_x, gem_beg_y, newnext, canhold, upcomeAtt, level, player, maxdepth - 1, &score, lastatt + att, lastclear + clear, depth + 1);
} else {
score += Evaluate(newfield, lastatt + att, lastclear + clear, depth, player);
}
if ( score > maxScore ) {
maxScore = score;
best = movs[i];
}
}
int hold_num = field.m_hold;
if ( field.m_hold == 0 && ! next.empty()) {
hold_num = next[0].num;
}
if ( canhold && curCanHold && hold_num ) {
GenMoving(field, movs, AI::getGem(hold_num, 0), gem_beg_x, gem_beg_y, true);
if ( ! movs.empty() ) {
for (size_t i = 0; i < movs.size() ; ++i) {
GameField newfield = field;
int clear, att;
clear = pasteClearAttack(newfield, hold_num, movs[i].x, movs[i].y, movs[i].spin, movs[i].wallkick_spin, att);
int score = 0;
newfield.m_hold = cur.num;
if ( maxdepth > 0 && (field.m_hold != 0 && next.size() > 0 || next.size() > 1) ) {
if ( field.m_hold == 0 ) {
std::vector<Gem> newnext( next.begin() + 2, next.end() );
AISearch(newfield, next[1], canhold, gem_beg_x, gem_beg_y, newnext, canhold, upcomeAtt, level, player, maxdepth - 1, &score, lastatt + att, lastclear + clear, depth + 1);
} else {
std::vector<Gem> newnext( next.begin() + 1, next.end() );
AISearch(newfield, next[0], canhold, gem_beg_x, gem_beg_y, newnext, canhold, upcomeAtt, level, player, maxdepth - 1, &score, lastatt + att, lastclear + clear, depth + 1);
}
} else {
score += Evaluate(newfield, lastatt + att, lastclear + clear, depth, player);
}
if ( score > maxScore ) {
maxScore = score;
best = movs[i];
}
}
}
}
if ( pscore ) *pscore = maxScore;
return best;
}
}
158 changes: 158 additions & 0 deletions dllai/ai.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
#pragma once

#include "gamefield.h"
#include <vector>

#define AI_MAX_DEPTH 2

namespace AI {
struct Moving
{
enum {
MOV_NULL,
MOV_L,
MOV_R,
MOV_LL,
MOV_RR,
MOV_D,
MOV_DD,
MOV_LSPIN,
MOV_RSPIN,
MOV_DROP,
MOV_HOLD,
MOV_SPIN2,
};
std::vector<int> movs;
int x, y;
int score;
signed char spin;
signed char wallkick_spin;
Moving () { wallkick_spin = 0; movs.reserve (16); }
Moving ( const Moving & m ) {
movs = m.movs;
x = m.x;
y = m.y;
spin = m.spin;
score = m.score;
wallkick_spin = m.wallkick_spin;
}
Moving ( const Moving & m, int _spin ) {
movs.reserve (16);
movs = m.movs;
spin = (signed char)_spin;
}
bool operator < (const Moving& _m) const {
return score > _m.score;
}
bool operator == (const Moving& _m) const {
if ( x != _m.x || y != _m.y ) return false;
if ( spin != _m.spin ) return false;
if ( wallkick_spin != _m.wallkick_spin ) return false;
return true;
}
};
struct MovingSimple
{
enum {
MOV_NULL,
MOV_L,
MOV_R,
MOV_LL,
MOV_RR,
MOV_D,
MOV_DD,
MOV_LSPIN,
MOV_RSPIN,
MOV_DROP,
MOV_HOLD,
MOV_SPIN2,
};
enum {
INVALID_POS = -64,
};
int x, y;
int lastmove;
signed char spin;
signed char wallkick_spin;
bool hold;
MovingSimple () { x = INVALID_POS; wallkick_spin = 0; lastmove = MovingSimple::MOV_NULL; }
MovingSimple ( const Moving & m ) {
x = m.x;
y = m.y;
spin = m.spin;
wallkick_spin = m.wallkick_spin;
if (m.movs.empty()) hold = false;
else hold = (m.movs[0] == MovingSimple::MOV_HOLD);
if (m.movs.empty()) lastmove = MovingSimple::MOV_NULL;
else lastmove = m.movs.back();
}
MovingSimple ( const MovingSimple & m ) {
x = m.x;
y = m.y;
spin = m.spin;
wallkick_spin = m.wallkick_spin;
hold = m.hold;
lastmove = m.lastmove;
}
MovingSimple ( const MovingSimple & m, int _spin ) {
lastmove = m.lastmove;
hold = m.hold;
spin = (signed char)_spin;
}
bool operator == (const MovingSimple& _m) const {
if ( x != _m.x || y != _m.y ) return false;
if ( spin != _m.spin ) return false;
if ( lastmove != _m.lastmove ) return false;
if ( hold != _m.hold ) return false;
if ( wallkick_spin != _m.wallkick_spin ) return false;
return true;
}
};
template <class T>
struct MovList
{
std::vector<T> queue;
//T queue[1024];
int beg, end;
MovList() {
beg = end = 0;
}
MovList( size_t size ) {
beg = end = 0;
//queue.resize( size );
queue.reserve( size );
}
void clear() {
beg = end = 0;
queue.clear();
}
size_t size() const {
return end - beg;
}
T& back() {
return queue[end-1];
}
void push(const T& mov) {
queue.push_back(mov);
//queue[end] = mov;
++end;
}
bool empty () const {
return beg == end;
}
void pop(T& mov) {
mov = queue[beg++];
}
};
enum AIScore {
SCORE_LOSE = -100000000,
};
void setComboList( std::vector<int> combolist );
int getComboAttack( int combo );
void GenMoving(const GameField& field, std::vector<MovingSimple> & movs, Gem cur, int x, int y, bool hold);
void FindPathMoving(const GameField& field, std::vector<Moving> & movs, Gem cur, int x, int y, bool hold);
MovingSimple AISearch(const GameField& field, Gem cur, bool curCanHold, int x, int y, const std::vector<Gem>& next
, bool canHold, int upcomeAtt, int level, int player
, int maxdepth = AI_MAX_DEPTH, int* score = NULL, int lastatt = 0, int lastclear = 0, int depth = 0);
void setSpin180( bool enable );
}
Loading

0 comments on commit 3c6ebb0

Please sign in to comment.