summaryrefslogtreecommitdiff
path: root/noncore/games/backgammon/moveengine.cpp
Unidiff
Diffstat (limited to 'noncore/games/backgammon/moveengine.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/backgammon/moveengine.cpp558
1 files changed, 558 insertions, 0 deletions
diff --git a/noncore/games/backgammon/moveengine.cpp b/noncore/games/backgammon/moveengine.cpp
new file mode 100644
index 0000000..009c449
--- a/dev/null
+++ b/noncore/games/backgammon/moveengine.cpp
@@ -0,0 +1,558 @@
1#include "moveengine.h"
2
3#include <qmessagebox.h>
4
5#include <qtimer.h>
6
7MoveEngine::MoveEngine()
8 : QObject()
9{
10 int offset=7;
11 int a=0; //counter variable
12 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};
13 for(a=0;a<26;a++)
14 {
15 x_coord[a]=xfill[a];
16 }
17
18 int yfill[]={10,25,40,55,70,10+offset,25+offset,40+offset,55+offset,25,40,55, 25+offset,40+offset,40};
19 int zfill[]={1,1,1,1,1,2,2,2,2,3,3,3,4,4,5};
20 for(a=0;a<15;a++)
21 {
22 yup_coord[a]=yfill[a];
23 ylow_coord[a]=185-(yfill[a]);
24 z_coord[a]=zfill[a];
25 }
26 for(a=0;a<5;a++)
27 {
28 if(a<3)
29 {
30 x_fin1[a]=65+a*15;
31 x_fin2[a]=155-a*15;
32 }
33 y_fin[a]=225-a*5;
34 }
35 z_fin=1;
36
37 reset();
38}
39
40MoveEngine::~MoveEngine()
41{}
42
43void MoveEngine::position(Pieces& pieces,bool non_qte)
44{
45 int player1_counter=0;
46 int player2_counter=0;
47
48 //non qte styles are smaller !!
49 int offset=(non_qte) ? 5 : 0;
50
51 for(int a=0;a<28;a++)
52 {
53 for(int b=0;b<abs(population[a].total);b++)
54 {
55 if(population[a].total>0) //player 1 pieces
56 {
57 pieces.player1[player1_counter].x=x_coord[a]-offset;
58 if(a>=0 && a<13)
59 {
60 pieces.player1[player1_counter].y=yup_coord[b]-offset;
61 pieces.player1[player1_counter].z=z_coord[b];
62 pieces.player1[player1_counter].side=false;
63 player1_counter++;
64 }
65 else if(a>12 && a<26)
66 {
67 pieces.player1[player1_counter].y=ylow_coord[b]-offset;
68 pieces.player1[player1_counter].z=z_coord[b];
69 pieces.player1[player1_counter].side=false;
70 player1_counter++;
71 }
72 else if(a==26)
73 {
74 if(b<5)
75 {
76 pieces.player1[player1_counter].x=x_fin1[0]-offset;
77 pieces.player1[player1_counter].y=y_fin[b]-offset;
78 pieces.player1[player1_counter].z=z_fin;
79 }
80 else if(b>=5 && b<10)
81 {
82 pieces.player1[player1_counter].x=x_fin1[1]-offset;
83 pieces.player1[player1_counter].y=y_fin[b-5]-offset;
84 pieces.player1[player1_counter].z=z_fin;
85 }
86 else
87 {
88 pieces.player1[player1_counter].x=x_fin1[2]-offset;
89 pieces.player1[player1_counter].y=y_fin[b-10]-offset;
90 pieces.player1[player1_counter].z=z_fin;
91 }
92 pieces.player1[player1_counter].side=true;
93 player1_counter++;
94
95 }
96 }
97
98 else if(population[a].total<0) //player 2 pieces
99 {
100 pieces.player2[player2_counter].x=x_coord[a]-offset;
101 if(a>=0 && a<13)
102 {
103 pieces.player2[player2_counter].y=yup_coord[b]-offset;
104 pieces.player2[player2_counter].z=z_coord[b];
105 pieces.player2[player2_counter].side=false;
106 player2_counter++;
107 }
108 else if(a>12 && a<26)
109 {
110 pieces.player2[player2_counter].y=ylow_coord[b]-offset;
111 pieces.player2[player2_counter].z=z_coord[b];
112 pieces.player2[player2_counter].side=false;
113 player2_counter++;
114 }
115 else if(a==27)
116 {
117 if(b<5)
118 {
119 pieces.player2[player2_counter].x=x_fin2[0]-offset;
120 pieces.player2[player2_counter].y=y_fin[b]-offset;
121 pieces.player2[player2_counter].z=z_fin;
122 }
123 else if(b>=5 && b<10)
124 {
125 pieces.player2[player2_counter].x=x_fin2[1]-offset;
126 pieces.player2[player2_counter].y=y_fin[b-5]-offset;
127 pieces.player2[player2_counter].z=z_fin;
128 }
129 else
130 {
131 pieces.player2[player2_counter].x=x_fin2[2]-offset;
132 pieces.player2[player2_counter].y=y_fin[b-10]-offset;
133 pieces.player2[player2_counter].z=z_fin;
134 }
135 pieces.player2[player2_counter].side=true;
136 player2_counter++;
137
138 }
139 }
140 }
141 }
142}
143
144void MoveEngine::diceroll(const int& newplayer,const int& face1,const int& face2,const int& face3,const int& face4,bool computer)
145{
146 checkstate();
147 player=newplayer;
148 otherplayer=(player==1) ? 2 : 1;
149 dice[0]=face1;
150 dice[1]=face2;
151 dice[2]=face3;
152 dice[3]=face4;
153 marker_current=-1;
154 if(getPossibleMoves()==0)
155 {
156 emit nomove();
157 return; // player will be changed
158 }
159 if(!computer)
160 return; //human intervention required
161
162 QTimer::singleShot(2000,this,SLOT(automove()));
163}
164
165
166void MoveEngine::automove()
167{
168 //the maximimum possibility
169 int maxpos=0;
170 //the position in the moves array
171 int from=-1;
172 int to=-1;
173 //dice1 or dice 2 ??
174 int index_dice=0;
175 for(int counter=0;counter<26;counter++)
176 {
177 int a=(player==1) ? counter : 25-counter;
178 for(int b=0;b<4;b++)
179 {
180 if(moves[a].weight[b]>maxpos)
181 {
182 maxpos=moves[a].weight[b];
183 from=a;
184 to=moves[a].to[b];
185 index_dice=b+1;
186 }
187 }
188 }
189 move(from,to,index_dice);
190}
191
192
193void MoveEngine::boardpressed(const int& x,const int& y,Marker& marker,bool non_qte)
194{
195 //get the position of the mouse click
196 bool upper=true;
197 bool found=false;
198
199 int offset=(non_qte) ? 5 : 0;
200
201 if(y<=85) // board slots 0 to 12
202 marker.y_current=0;
203 else if(y>=105) //board slots 13 to 25
204 {
205 marker.y_current=195-2*offset;
206 upper=false;
207 }
208
209 int index=13; // the clicked board slot
210
211 while(index<25 && !found)
212 {
213 if(x>=x_coord[index] && x<x_coord[index+1])
214 {
215 marker.x_current=x_coord[index];
216 found=true;
217 ;
218 }
219 else
220 {
221 index++;
222 }
223 }
224 if(!found)
225 {
226 marker.x_current=x_coord[25];
227 index=25;
228 }
229 if(upper)
230 {
231 index=25-index;
232 }
233
234 int a=0;
235 int usedice=-1;
236 int dice_value=7;
237 for(a=0;a<4;a++)
238 {
239 if(index==marker_next[a] && marker_next[a]!=-1 && dice_value>dice[a])
240 {
241 usedice=a;
242 dice_value=dice[0];
243 }
244 }
245 if(usedice!=-1)
246 {
247 move(marker_current,marker_next[usedice],usedice+1);
248 nomarker(marker);
249 return;
250
251 }
252
253
254 if(dice[0]==7 && dice[1]==7 && dice[2]==7 && dice[3]==7) //no dice rolled
255 {
256 nomarker(marker);
257 return;
258 }
259 else if(fieldColor(index)==player)
260 {
261 marker.visible_current=true;
262 marker_current=index;
263 }
264 else
265 {
266 nomarker(marker);
267 return;
268 }
269
270 for(a=0;a<4;a++)
271 {
272 if(moves[index].weight[a]>0)
273 {
274 int nextfield=moves[index].to[a];
275 marker.x_next[a]=x_coord[nextfield];
276 marker_next[a]=nextfield;
277 if(nextfield<13) //upper half
278 marker.y_next[a]=0;
279 else //lower half
280 marker.y_next[a]=195-2*offset;
281 marker.visible_next[a]=true;
282 }
283 else
284 {
285 marker.x_next[a]=0;
286 marker.y_next[a]=0;
287 marker_next[a]=-1;
288 marker.visible_next[a]=false;
289 }
290 }
291 return;
292}
293
294void MoveEngine::reset()
295{
296 int a=0;
297 for(a=0;a<28;a++)
298 {
299 population[a].total=0;
300 }
301
302 int p1_index[]={1,1,12,12,12,12,12,17,17,17,19,19,19,19,19};
303 int p2_index[]={24,24,13,13,13,13,13,8,8,8,6,6,6,6,6};
304 //int p1_index[]={19,20,21,22,22,23,23,18,18,23,24,24,24,24,24};
305 //int p2_index[]={6,5,4,3,3,2,2,2,2,2,1,7,7,1,1};
306 for(a=0;a<15;a++)
307 {
308 population[p1_index[a]].total++;
309 population[p2_index[a]].total--;
310 }
311
312 player=0;
313 dice[0]=7;
314 dice[1]=7;
315 dice[2]=7;
316 dice[3]=7;
317
318 marker_current=-1;
319 marker_next[0]=-1;
320 marker_next[1]=-1;
321 marker_next[2]=-1;
322 marker_next[3]=-1;
323 //allclear[0]==false;
324 allclear[1]=false;
325 allclear[2]=false;
326 last_piece[1]=0;
327 last_piece[2]=25;
328}
329
330void MoveEngine::loadGame(const LoadSave& load)
331{
332 for(int a=0;a<28;a++)
333 {
334 population[a].total=load.pop[a].total;
335 }
336 checkstate();
337}
338
339LoadSave MoveEngine::saveGame()
340{
341 LoadSave save;
342 for(int a=0;a<28;a++)
343 {
344 save.pop[a].total=population[a].total;
345 }
346 return save;
347}
348
349AISettings MoveEngine::getAISettings()
350{
351 return ai;
352}
353
354void MoveEngine::setAISettings(const AISettings& new_ai)
355{
356 ai=new_ai;
357}
358
359void MoveEngine::setRules(Rules rules)
360{
361 move_with_pieces_out=rules.move_with_pieces_out;
362 nice_dice=rules.generous_dice;
363}
364
365
366int MoveEngine::getPossibleMoves()
367{
368 int homezone[]={0,25,0};
369 int lastToHomeZone=abs(last_piece[player]-homezone[player]);
370 for(int field=0;field<26;field++)
371 {
372
373 for(int b=0;b<4;b++)
374 {
375 int dice_tmp=dice[b];
376 if(dice[b]!=7 && dice[b]> lastToHomeZone)
377 dice_tmp=lastToHomeZone;
378
379 int nextfield=(player==1) ? field+dice_tmp : field-dice_tmp;
380
381 if(nice_dice)
382 {
383 if(player==1 && nextfield>homezone[1])
384 nextfield=homezone[1];
385 else if(player==2 && nextfield<homezone[2])
386 nextfield=homezone[2];
387 }
388
389 moves[field].weight[b]=0;
390 moves[field].to[b]=nextfield;
391
392 int out_of_board[]={-1,0,25};
393 if(!move_with_pieces_out && field!=out_of_board[player] && pieces_out[player])
394 {
395 continue;
396 }
397
398
399
400 if(dice[b]!=7 && fieldColor(field)==player ) //player can only move his own pieces
401 {
402 if((player==1 && nextfield > homezone[1]) || (player==2 && nextfield < homezone[2]))
403 {
404 moves[field].weight[b]=0; //movement would be far out of board
405 }
406 else if(nextfield==homezone[player] && !allclear[player])
407 {
408 moves[field].weight[b]=0; //can not rescue pieces until all are in the endzone
409 }
410 else if(nextfield==homezone[player] && allclear[player])
411 {
412 moves[field].weight[b]=ai.rescue; //rescue your pieces : nuff said ;-)
413 }
414 else if(fieldColor(nextfield)==otherplayer)
415 {
416 if(abs(population[nextfield].total)>1) //can not move to this field
417 moves[field].weight[b]=0;
418 else if(abs(population[nextfield].total)==1) //eliminate opponent : very nice
419 moves[field].weight[b]=ai.eliminate;
420 }
421 else if(fieldColor(nextfield)==player) //nextfield already occupied by player
422 {
423 if(abs(population[field].total)==2) //expose own piece : not diserable
424 moves[field].weight[b]=ai.expose;
425 else if(abs(population[nextfield].total)>1) //own pices already there : safe
426 moves[field].weight[b]=ai.safe;
427 else if(abs(population[nextfield].total)==1) //protect own piece : most importatnt
428 moves[field].weight[b]=ai.protect;
429 }
430 else if(population[nextfield].total==0) //nextfield empty
431 {
432 if(abs(population[field].total)==2) //expose own piece : not diserable
433 moves[field].weight[b]=ai.expose;
434 else
435 moves[field].weight[b]=ai.empty;
436 }
437 else
438 moves[field].weight[b]=0; //default.
439 }
440
441
442
443 else
444 moves[field].weight[b]=0; //dice already used or field not used by player
445 }
446
447
448
449 }
450
451 int total=0;
452 for(int field=0;field<26;field++)
453 {
454 total+=moves[field].weight[0]+moves[field].weight[1]+moves[field].weight[2]+moves[field].weight[3];
455 }
456 return total;
457}
458
459void MoveEngine::move(const int& from, int to, const int& dice)
460{
461 //qDebug("%d moves from %d to %d (%d) with dice %d",player,from,to,to-from,dice);
462
463 if(player==1 && to==25)
464 to=26;
465 if(player==2 && to==0)
466 to=27;
467
468 //if space is occupied by enemy move pieces to startzone
469 if(fieldColor(to)==otherplayer)
470 {
471 population[to].total=0;
472 if(otherplayer==1)
473 population[0].total++;
474 else
475 population[25].total--;
476 }
477
478 if(player==1)
479 {
480 population[from].total--;
481 population[to].total++;
482 }
483 else //player=2
484 {
485 population[from].total++;
486 population[to].total--;
487 }
488
489 if(dice==1)
490 emit done_dice1();
491 else if(dice==2)
492 emit done_dice2();
493 else if(dice==3)
494 emit done_dice3();
495 else
496 emit done_dice4();
497
498 if(abs(population[26].total)==15)
499 emit player_finished(1);
500 if(abs(population[27].total)==15)
501 emit player_finished(2);
502}
503
504void MoveEngine::checkstate()
505{
506 //check if pieces are out
507 pieces_out[1]=(population[0].total>0) ? true : false;
508 pieces_out[2]=(population[25].total<0) ? true : false;
509
510 //check if all pieces are in the endzones
511 allclear[1]=true;
512 allclear[2]=true;
513
514 last_piece[1]=25;
515 bool found_last_piece1=false;
516 last_piece[2]=0;
517
518 for(int a=0;a<26;a++)
519 {
520 if(a<19 && population[a].total>0)
521 allclear[1]=false;
522 if(a>6 && population[a].total<0)
523 allclear[2]=false;
524
525 if(population[a].total>0 && !found_last_piece1)
526 {
527 last_piece[1]=a;
528 found_last_piece1=true;
529 }
530 if(population[a].total<0)
531 last_piece[2]=a;
532 }
533}
534
535void MoveEngine::nomarker(Marker& marker)
536{
537 marker.visible_current=false;
538 marker_current=-1;
539 for(int a=0;a<4;a++)
540 {
541 marker.x_next[a]=0;
542 marker.y_next[a]=0;
543 marker_next[a]=-1;
544 marker.visible_next[a]=false;
545 }
546}
547
548int MoveEngine::fieldColor(const int& index) const
549{
550 if(population[index].total>0)
551 return 1;
552 else if(population[index].total<0)
553 return 2;
554 else
555 return 0;
556}
557
558