00001 #include "moveengine.h"
00002
00003 #include <qtimer.h>
00004 #include <stdlib.h>
00005
00006 MoveEngine::MoveEngine()
00007 : QObject()
00008 {
00009 int offset=7;
00010 int a=0;
00011 int xfill[]={210,185,170,155,140,125,110,85,70,55,40,25,10,10,25,40,55,70,85,110,125,140,155,170,185,210};
00012 for(a=0;a<26;a++)
00013 {
00014 x_coord[a]=xfill[a];
00015 }
00016
00017 int yfill[]={10,25,40,55,70,10+offset,25+offset,40+offset,55+offset,25,40,55, 25+offset,40+offset,40};
00018 int zfill[]={1,1,1,1,1,2,2,2,2,3,3,3,4,4,5};
00019 for(a=0;a<15;a++)
00020 {
00021 yup_coord[a]=yfill[a];
00022 ylow_coord[a]=185-(yfill[a]);
00023 z_coord[a]=zfill[a];
00024 }
00025 for(a=0;a<5;a++)
00026 {
00027 if(a<3)
00028 {
00029 x_fin1[a]=65+a*15;
00030 x_fin2[a]=155-a*15;
00031 }
00032 y_fin[a]=225-a*5;
00033 }
00034 z_fin=1;
00035
00036 reset();
00037 }
00038
00039 MoveEngine::~MoveEngine()
00040 {}
00041
00042 void MoveEngine::position(Pieces& pieces,bool non_qte)
00043 {
00044 int player1_counter=0;
00045 int player2_counter=0;
00046
00047
00048 int offset=(non_qte) ? 5 : 0;
00049
00050 for(int a=0;a<28;a++)
00051 {
00052 for(int b=0;b<abs(population[a].total);b++)
00053 {
00054 if(population[a].total>0)
00055 {
00056 pieces.player1[player1_counter].x=x_coord[a]-offset;
00057 if(a>=0 && a<13)
00058 {
00059 pieces.player1[player1_counter].y=yup_coord[b]-offset;
00060 pieces.player1[player1_counter].z=z_coord[b];
00061 pieces.player1[player1_counter].side=false;
00062 player1_counter++;
00063 }
00064 else if(a>12 && a<26)
00065 {
00066 pieces.player1[player1_counter].y=ylow_coord[b]-offset;
00067 pieces.player1[player1_counter].z=z_coord[b];
00068 pieces.player1[player1_counter].side=false;
00069 player1_counter++;
00070 }
00071 else if(a==26)
00072 {
00073 if(b<5)
00074 {
00075 pieces.player1[player1_counter].x=x_fin1[0]-offset;
00076 pieces.player1[player1_counter].y=y_fin[b]-offset;
00077 pieces.player1[player1_counter].z=z_fin;
00078 }
00079 else if(b>=5 && b<10)
00080 {
00081 pieces.player1[player1_counter].x=x_fin1[1]-offset;
00082 pieces.player1[player1_counter].y=y_fin[b-5]-offset;
00083 pieces.player1[player1_counter].z=z_fin;
00084 }
00085 else
00086 {
00087 pieces.player1[player1_counter].x=x_fin1[2]-offset;
00088 pieces.player1[player1_counter].y=y_fin[b-10]-offset;
00089 pieces.player1[player1_counter].z=z_fin;
00090 }
00091 pieces.player1[player1_counter].side=true;
00092 player1_counter++;
00093
00094 }
00095 }
00096
00097 else if(population[a].total<0)
00098 {
00099 pieces.player2[player2_counter].x=x_coord[a]-offset;
00100 if(a>=0 && a<13)
00101 {
00102 pieces.player2[player2_counter].y=yup_coord[b]-offset;
00103 pieces.player2[player2_counter].z=z_coord[b];
00104 pieces.player2[player2_counter].side=false;
00105 player2_counter++;
00106 }
00107 else if(a>12 && a<26)
00108 {
00109 pieces.player2[player2_counter].y=ylow_coord[b]-offset;
00110 pieces.player2[player2_counter].z=z_coord[b];
00111 pieces.player2[player2_counter].side=false;
00112 player2_counter++;
00113 }
00114 else if(a==27)
00115 {
00116 if(b<5)
00117 {
00118 pieces.player2[player2_counter].x=x_fin2[0]-offset;
00119 pieces.player2[player2_counter].y=y_fin[b]-offset;
00120 pieces.player2[player2_counter].z=z_fin;
00121 }
00122 else if(b>=5 && b<10)
00123 {
00124 pieces.player2[player2_counter].x=x_fin2[1]-offset;
00125 pieces.player2[player2_counter].y=y_fin[b-5]-offset;
00126 pieces.player2[player2_counter].z=z_fin;
00127 }
00128 else
00129 {
00130 pieces.player2[player2_counter].x=x_fin2[2]-offset;
00131 pieces.player2[player2_counter].y=y_fin[b-10]-offset;
00132 pieces.player2[player2_counter].z=z_fin;
00133 }
00134 pieces.player2[player2_counter].side=true;
00135 player2_counter++;
00136
00137 }
00138 }
00139 }
00140 }
00141 }
00142
00143 void MoveEngine::diceroll(const int& newplayer,const int& face1,const int& face2,const int& face3,const int& face4,bool computer)
00144 {
00145 checkstate();
00146 player=newplayer;
00147 otherplayer=(player==1) ? 2 : 1;
00148 dice[0]=face1;
00149 dice[1]=face2;
00150 dice[2]=face3;
00151 dice[3]=face4;
00152 marker_current=-1;
00153 if(getPossibleMoves()==0)
00154 {
00155 emit nomove();
00156 return;
00157 }
00158 if(!computer)
00159 return;
00160
00161 QTimer::singleShot(2000,this,SLOT(automove()));
00162 }
00163
00164
00165 void MoveEngine::automove()
00166 {
00167
00168 int maxpos=0;
00169
00170 int from=-1;
00171 int to=-1;
00172
00173 int index_dice=0;
00174 for(int counter=0;counter<26;counter++)
00175 {
00176 int a=(player==1) ? counter : 25-counter;
00177 for(int b=0;b<4;b++)
00178 {
00179 if(moves[a].weight[b]>maxpos)
00180 {
00181 maxpos=moves[a].weight[b];
00182 from=a;
00183 to=moves[a].to[b];
00184 index_dice=b+1;
00185 }
00186 }
00187 }
00188 move(from,to,index_dice);
00189 }
00190
00191
00192 void MoveEngine::boardpressed(const int& x,const int& y,Marker& marker,bool non_qte)
00193 {
00194
00195 bool upper=true;
00196 bool found=false;
00197
00198 int offset=(non_qte) ? 5 : 0;
00199
00200 if(y<=85)
00201 marker.y_current=0;
00202 else if(y>=105)
00203 {
00204 marker.y_current=195-2*offset;
00205 upper=false;
00206 }
00207
00208 int index=13;
00209
00210 while(index<25 && !found)
00211 {
00212 if(x>=x_coord[index] && x<x_coord[index+1])
00213 {
00214 marker.x_current=x_coord[index];
00215 found=true;
00216 ;
00217 }
00218 else
00219 {
00220 index++;
00221 }
00222 }
00223 if(!found)
00224 {
00225 marker.x_current=x_coord[25];
00226 index=25;
00227 }
00228 if(upper)
00229 {
00230 index=25-index;
00231 }
00232
00233 int a=0;
00234 int usedice=-1;
00235 int dice_value=7;
00236 for(a=0;a<4;a++)
00237 {
00238 if(index==marker_next[a] && marker_next[a]!=-1 && dice_value>dice[a])
00239 {
00240 usedice=a;
00241 dice_value=dice[0];
00242 }
00243 }
00244 if(usedice!=-1)
00245 {
00246 move(marker_current,marker_next[usedice],usedice+1);
00247 nomarker(marker);
00248 return;
00249
00250 }
00251
00252
00253 if(dice[0]==7 && dice[1]==7 && dice[2]==7 && dice[3]==7)
00254 {
00255 nomarker(marker);
00256 return;
00257 }
00258 else if(fieldColor(index)==player)
00259 {
00260 marker.visible_current=true;
00261 marker_current=index;
00262 }
00263 else
00264 {
00265 nomarker(marker);
00266 return;
00267 }
00268
00269 for(a=0;a<4;a++)
00270 {
00271 if(moves[index].weight[a]>0)
00272 {
00273 int nextfield=moves[index].to[a];
00274 marker.x_next[a]=x_coord[nextfield];
00275 marker_next[a]=nextfield;
00276 if(nextfield<13)
00277 marker.y_next[a]=0;
00278 else
00279 marker.y_next[a]=195-2*offset;
00280 marker.visible_next[a]=true;
00281 }
00282 else
00283 {
00284 marker.x_next[a]=0;
00285 marker.y_next[a]=0;
00286 marker_next[a]=-1;
00287 marker.visible_next[a]=false;
00288 }
00289 }
00290 return;
00291 }
00292
00293 void MoveEngine::reset()
00294 {
00295 int a=0;
00296 for(a=0;a<28;a++)
00297 {
00298 population[a].total=0;
00299 }
00300
00301 int p1_index[]={1,1,12,12,12,12,12,17,17,17,19,19,19,19,19};
00302 int p2_index[]={24,24,13,13,13,13,13,8,8,8,6,6,6,6,6};
00303
00304
00305 for(a=0;a<15;a++)
00306 {
00307 population[p1_index[a]].total++;
00308 population[p2_index[a]].total--;
00309 }
00310
00311 player=0;
00312 dice[0]=7;
00313 dice[1]=7;
00314 dice[2]=7;
00315 dice[3]=7;
00316
00317 marker_current=-1;
00318 marker_next[0]=-1;
00319 marker_next[1]=-1;
00320 marker_next[2]=-1;
00321 marker_next[3]=-1;
00322
00323 allclear[1]=false;
00324 allclear[2]=false;
00325 last_piece[1]=0;
00326 last_piece[2]=25;
00327 }
00328
00329 void MoveEngine::loadGame(const LoadSave& load)
00330 {
00331 for(int a=0;a<28;a++)
00332 {
00333 population[a].total=load.pop[a].total;
00334 }
00335 checkstate();
00336 }
00337
00338 LoadSave MoveEngine::saveGame()
00339 {
00340 LoadSave save;
00341 for(int a=0;a<28;a++)
00342 {
00343 save.pop[a].total=population[a].total;
00344 }
00345 return save;
00346 }
00347
00348 AISettings MoveEngine::getAISettings()
00349 {
00350 return ai;
00351 }
00352
00353 void MoveEngine::setAISettings(const AISettings& new_ai)
00354 {
00355 ai=new_ai;
00356 }
00357
00358 void MoveEngine::setRules(Rules rules)
00359 {
00360 move_with_pieces_out=rules.move_with_pieces_out;
00361 nice_dice=rules.generous_dice;
00362 }
00363
00364
00365 int MoveEngine::getPossibleMoves()
00366 {
00367 int homezone[]={0,25,0};
00368 int lastToHomeZone=abs(last_piece[player]-homezone[player]);
00369 for(int field=0;field<26;field++)
00370 {
00371
00372 for(int b=0;b<4;b++)
00373 {
00374 int dice_tmp=dice[b];
00375 if(dice[b]!=7 && dice[b]> lastToHomeZone)
00376 dice_tmp=lastToHomeZone;
00377
00378 int nextfield=(player==1) ? field+dice_tmp : field-dice_tmp;
00379
00380 if(nice_dice)
00381 {
00382 if(player==1 && nextfield>homezone[1])
00383 nextfield=homezone[1];
00384 else if(player==2 && nextfield<homezone[2])
00385 nextfield=homezone[2];
00386 }
00387
00388 moves[field].weight[b]=0;
00389 moves[field].to[b]=nextfield;
00390
00391 int out_of_board[]={-1,0,25};
00392 if(!move_with_pieces_out && field!=out_of_board[player] && pieces_out[player])
00393 {
00394 continue;
00395 }
00396
00397
00398
00399 if(dice[b]!=7 && fieldColor(field)==player )
00400 {
00401 if((player==1 && nextfield > homezone[1]) || (player==2 && nextfield < homezone[2]))
00402 {
00403 moves[field].weight[b]=0;
00404 }
00405 else if(nextfield==homezone[player] && !allclear[player])
00406 {
00407 moves[field].weight[b]=0;
00408 }
00409 else if(nextfield==homezone[player] && allclear[player])
00410 {
00411 moves[field].weight[b]=ai.rescue;
00412 }
00413 else if(fieldColor(nextfield)==otherplayer)
00414 {
00415 if(abs(population[nextfield].total)>1)
00416 moves[field].weight[b]=0;
00417 else if(abs(population[nextfield].total)==1)
00418 moves[field].weight[b]=ai.eliminate;
00419 }
00420 else if(fieldColor(nextfield)==player)
00421 {
00422 if(abs(population[field].total)==2)
00423 moves[field].weight[b]=ai.expose;
00424 else if(abs(population[nextfield].total)>1)
00425 moves[field].weight[b]=ai.safe;
00426 else if(abs(population[nextfield].total)==1)
00427 moves[field].weight[b]=ai.protect;
00428 }
00429 else if(population[nextfield].total==0)
00430 {
00431 if(abs(population[field].total)==2)
00432 moves[field].weight[b]=ai.expose;
00433 else
00434 moves[field].weight[b]=ai.empty;
00435 }
00436 else
00437 moves[field].weight[b]=0;
00438 }
00439
00440
00441
00442 else
00443 moves[field].weight[b]=0;
00444 }
00445
00446
00447
00448 }
00449
00450 int total=0;
00451 for(int field=0;field<26;field++)
00452 {
00453 total+=moves[field].weight[0]+moves[field].weight[1]+moves[field].weight[2]+moves[field].weight[3];
00454 }
00455 return total;
00456 }
00457
00458 void MoveEngine::move(const int& from, int to, const int& dice)
00459 {
00460
00461
00462 if(player==1 && to==25)
00463 to=26;
00464 if(player==2 && to==0)
00465 to=27;
00466
00467
00468 if(fieldColor(to)==otherplayer)
00469 {
00470 population[to].total=0;
00471 if(otherplayer==1)
00472 population[0].total++;
00473 else
00474 population[25].total--;
00475 }
00476
00477 if(player==1)
00478 {
00479 population[from].total--;
00480 population[to].total++;
00481 }
00482 else
00483 {
00484 population[from].total++;
00485 population[to].total--;
00486 }
00487
00488 if(dice==1)
00489 emit done_dice1();
00490 else if(dice==2)
00491 emit done_dice2();
00492 else if(dice==3)
00493 emit done_dice3();
00494 else
00495 emit done_dice4();
00496
00497 if(abs(population[26].total)==15)
00498 emit player_finished(1);
00499 if(abs(population[27].total)==15)
00500 emit player_finished(2);
00501 }
00502
00503 void MoveEngine::checkstate()
00504 {
00505
00506 pieces_out[1]=(population[0].total>0) ? true : false;
00507 pieces_out[2]=(population[25].total<0) ? true : false;
00508
00509
00510 allclear[1]=true;
00511 allclear[2]=true;
00512
00513 last_piece[1]=25;
00514 bool found_last_piece1=false;
00515 last_piece[2]=0;
00516
00517 for(int a=0;a<26;a++)
00518 {
00519 if(a<19 && population[a].total>0)
00520 allclear[1]=false;
00521 if(a>6 && population[a].total<0)
00522 allclear[2]=false;
00523
00524 if(population[a].total>0 && !found_last_piece1)
00525 {
00526 last_piece[1]=a;
00527 found_last_piece1=true;
00528 }
00529 if(population[a].total<0)
00530 last_piece[2]=a;
00531 }
00532 }
00533
00534 void MoveEngine::nomarker(Marker& marker)
00535 {
00536 marker.visible_current=false;
00537 marker_current=-1;
00538 for(int a=0;a<4;a++)
00539 {
00540 marker.x_next[a]=0;
00541 marker.y_next[a]=0;
00542 marker_next[a]=-1;
00543 marker.visible_next[a]=false;
00544 }
00545 }
00546
00547 int MoveEngine::fieldColor(const int& index) const
00548 {
00549 if(population[index].total>0)
00550 return 1;
00551 else if(population[index].total<0)
00552 return 2;
00553 else
00554 return 0;
00555 }
00556
00557