1 /**********************************************************************
2 *
3 * FreeDoko a Doppelkopf-Game
4 *
5 * Copyright (C) 2001 – 2018 by Diether Knof and Borg Enders
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You can find this license in the file 'gpl.txt'.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 *
23 * Contact:
24 * Diether Knof dknof@posteo.de
25 *
26 *********************************************************************/
27
28 #include "constants.h"
29
30 #include "trickweighting.h"
31
32 #include "virtual_games_interface.h"
33 #include "ai.h"
34 #include "../../party/party.h"
35 #include "../../party/rule.h"
36 #include "../../game/game.h"
37 #include "../../game/exception.h"
38 #include "../../card/trick.h"
39 #include "../../misc/preferences.h"
40 #include "../../ui/ui.h"
41
42 #ifdef BENDERS
43 #ifndef RELEASE
44 // whether to print some weighting informations
45 #define PLAYERCHECK 10
46
47 // Playernumber for which to produce output
48 unsigned playerCheck;
49 #endif
50 #endif
51
52
53 /** @return whether the opposite team can win the trick
54 **/
55 bool
oppositeTeamCanWinTrick(Trick const & trick,VirtualGamesInterface const & hi)56 oppositeTeamCanWinTrick(Trick const& trick,
57 VirtualGamesInterface const& hi)
58 {
59 if (trick.winnerplayer().team() != hi.team())
60 return true;
61
62 // take a look if all players coming in this trick of other team can still win the trick
63 for (auto i = trick.actcardno(); i < hi.game().playerno(); ++i) {
64 auto const& player = trick.player_of_card(i);
65 if (hi.guessed_opposite_team(player)) {
66 auto const& hand = hi.handofplayer(player);
67 if (hand.higher_card_exists(trick.winnercard()))
68 return true;
69 }
70 }
71 return false;
72 } // bool oppositeTeamCanWinTrick ( Trick t, HeuristicInterface hi )
73
74 /** Modification for dulle and swines
75 **/
76 int
modi_dulle_swines(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)77 TrickWeighting::modi_dulle_swines(VirtualGamesInterface const& vgi,
78 Trick const& trick,
79 Team const team,
80 HandCard const& card,
81 Team const winnerteam,
82 Ai const& ai)
83 {
84 int modi = 0;
85
86 if( !card.istrump() )
87 return modi;
88
89 if (!( card.isswine()
90 || card.ishyperswine()
91 || card.isdulle()))
92 return modi;
93
94 // have played a very high card
95
96 auto const& hand = ai.hand();
97 auto const& game = ai.game();
98 auto const& swines = game.swines();
99 auto const& cards = game.cards();
100
101 // 2005-08-06: swines in the last three tricks
102 // modi -= 29; // previous values: 23,14,21,24, 29, 33, 35,31
103 modi -= (31 - std::max(static_cast<int>(cards.count_played()) - 9 , 0));
104 // previous: 34, 31 (Reference 92672)
105 // previous: no()-12
106
107 if( trick.startcard().istrump() )
108 modi -= 11; // reference
109
110 if ( (static_cast<int>(trick.points()) - card.value()
111 < ai.value(Aiconfig::Type::limitqueen)))
112 modi-= 4;
113
114 if (maybe_to_team(winnerteam) != team)
115 modi -= 26;
116
117 if (maybe_to_team(winnerteam) == team) {
118 if ( // review Reference 260689
119 trick.startplayer().no() == vgi.no() ) // serving with a high trump and something potential higher is still out there
120 {
121 if ( hand.count_swines() +
122 hand.count_hyperswines() +
123 hand.count( Card::dulle ) != hand.count_trumps() ) {
124 modi -= 10; // reference
125 }
126
127 //high trump serving is generally not a good choice
128 if (!(is_solo(vgi.game().type())
129 && (vgi.game().players().soloplayer() == ai)))
130 modi -= 19; // reference 274918
131 }
132 }
133
134 if( (vgi.no() != trick.winnerplayer().no())
135 && !( trick.cardno_of_player( card.player() ) == 3
136 && trick.winnerplayer().team() == vgi.team() )
137 ) {
138 modi -= (36 - std::max(static_cast<int>(cards.count_played()) - 13, 0));
139 modi += trick.points()/2;
140
141 if( trick.cardno_of_player( trick.winnerplayer() )
142 < trick.cardno_of_player( card.player() )
143 || !trick.jabs_cards_before( card.player() ))
144 modi -= 16; // previously 9, 12
145 }
146
147 // not for all three cards
148
149 if ( ! card.isdulle()) // so that a dulle is prefered to a swine
150 modi -= 8; //previous values: 2, 7,9
151
152 if ( trick.startplayer().no() == vgi.no() )
153 {
154 // previous: 12, 18
155 modi -= 30; // 23: 002645, 30:
156 if ( hand.count_swines() +
157 hand.count_hyperswines() +
158 hand.count(Card::dulle) == hand.count_trumps() )
159 {
160
161 if( card.isdulle()
162 && (!swines.swines_announced()
163 || ai.teamofplayer(swines.swines_owner()) == ai.team() )
164 && (!swines.hyperswines_announced()
165 || ai.teamofplayer(swines.hyperswines_owner()) == ai.team()) )
166 {
167 modi += 10;
168 }
169 if ( card.isswine()
170 && ( !swines.hyperswines_announced()
171 || ai.teamofplayer(swines.hyperswines_owner()) == ai.team())) {
172 modi += 30;
173 }
174 if (card.ishyperswine()) {
175 modi += 50;
176 }
177
178 } else {
179 if( is_solo( vgi.game().type() ) // reference 246985
180 && vgi.is_soloplayer() ) //2do no higher card still in game
181 modi += 21;
182 }
183 }
184
185
186 if ( trick.cardno_of_player(card.player()) == 1
187 && vgi.game().cards().count_played(Card::dulle) == 0 //2do before trick
188 && card.isdulle()
189 && vgi.game().second_dulle_over_first() )
190 modi -= 5;
191
192 if ( trick.cardno_of_player(card.player()) == 0
193 && vgi.game().cards().count_played(Card::dulle) == 0 //2do before trick
194 && card.isdulle()
195 && vgi.game().second_dulle_over_first() )
196 modi -= 1; // reference 197840
197
198 // depending on data in the trick
199
200 Trick t(trick.startplayer());
201 for (unsigned i = 0; i < trick.cardno_of_player(card.player()); ++i) {
202 t.add(trick.card( i ));
203 }
204
205 if( trick.cardno_of_player(card.player()) == 2
206 && card.isdulle()
207 && swines.swines_announced() //2do extend to hyperswine, do same for swine hyperswine
208 && trick.cardno_of_player(swines.swines_owner()) == 3 ) {
209 // swine behind dulle
210 modi -= 15; // reference 176246
211 }
212
213 if( trick.cardno_of_player(card.player()) == 1
214 && card.isdulle()
215 && swines.swines_announced() //2do extend to hyperswine, do same for swine hyperswine
216 && trick.cardno_of_player(swines.swines_owner()) >1 ) {
217 // swine behind dulle
218 modi -= 3; // reference 010523
219 }
220
221
222 if( card.isdulle()
223 && swines.swines_announced() //2do extend to hyperswine, do same for swine hyperswine
224 && trick.cardno_of_player(swines.swines_owner()) < trick.cardno_of_player(card.player())) {
225 // swines in game, but before player with dulle
226 modi +=13; // reference 088597, 114803
227 }
228
229 if (trick.cardno_of_player(card.player()) == 3) {
230 modi -= 21; // previous 18, 20, 24
231
232 if (t.winnerplayer().team() == vgi.team()) { // reference 43530
233 modi -= 9; // previous
234 }
235
236 if (t.winnerplayer().team() != vgi.team()) { // reference
237 modi -= 19; // previous
238 }
239 }
240
241
242
243 if ( ai.value(Aiconfig::Type::limithigh).less(t.winnercard()) // !oppositeTeamCanWinTrick( t, vgi ) ) 2do XXX
244 && t.winnerplayer().team() == team ) {
245 modi -= 26;
246 if( is_solo( vgi.game().type() )
247 && !vgi.is_soloplayer())
248 modi -= 4;
249 }
250
251
252 if ( ( card.possible_swine() //2do for a swine possible_swine should return false?
253 && !card.isswine() )
254 || ( card.possible_hyperswine()
255 && !card.ishyperswine()))
256 modi += 9;
257
258
259 // only for soli
260 if( is_solo( vgi.game().type() )
261 && vgi.is_soloplayer())
262 modi += 3;
263
264 #ifdef PLAYERCHECK
265 if (vgi.no() == playerCheck) {
266
267 COUT <<"MDS"<< modi << "\t";
268
269 }
270 #endif
271 return modi;
272 }
273
274
275 /** Modification for a queen
276 **/
277 int
modi_queen(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)278 TrickWeighting::modi_queen(VirtualGamesInterface const& vgi,
279 Trick const& trick,
280 Team const team,
281 HandCard const& card,
282 Team const winnerteam,
283 Ai const& ai)
284 {
285 if (card.value() != Card::queen)
286 return 0;
287 if (!card.istrump())
288 return 0;
289
290 int modi = 0;
291 Player const& ai_virt = trick.game().player(ai.no());
292
293 modi -= 4; // previous 2, 3
294 // 4: Reference 188872
295
296 if (
297 (static_cast<int>(trick.points()) - card.value()
298 < ai.value(Aiconfig::Type::limitqueen)))
299 modi-= 4;
300
301 if ( trick.cardno_of_player(card.player()) == 3 )
302 {
303 modi -= 13; // previous 11, 13, 17, 14
304 // 13 reference 043530
305
306 Trick t( trick.startplayer());
307 t.add(trick.card( 0 ));
308 t.add(trick.card( 1 ));
309 t.add(trick.card( 2 ));
310
311 if (t.winnerplayer().team() == vgi.team()) {
312 modi -= 7; // previous
313
314 }
315 }
316
317 if (is_solo(vgi.game().type())
318 && (vgi.game().players().soloplayer().no() == ai.no())
319 && vgi.trump_card_limit().less(card)
320 && card.less(ai.cards_information().highest_remaining_trump_of_others()))
321 modi -= 8; // reference 246985
322
323
324
325 if( ( vgi.no() != trick.winnerplayer().no()
326 && !( trick.cardno_of_player( card.player() ) == 3
327 && trick.winnerplayer().team() == vgi.team() )
328 )
329
330 )
331 {
332 modi -= (36 - std::max(static_cast<int>(ai.game().cards().count_played()) - 13, 0));
333 modi += trick.points()/2;
334
335 if( trick.cardno_of_player( trick.winnerplayer() )
336 < trick.cardno_of_player( card.player() )
337 || !trick.jabs_cards_before( card.player() ))
338 modi -= 18; // previously 9, 12, 16
339 // 18 261053
340 }
341
342 if ( card == Card::spade_queen ) {
343 if( vgi.no() != trick.winnerplayer().no() ) {
344 modi -= 3; // reference
345 }
346 }
347
348 if ( is_solo(vgi.game().type())
349 && Card::diamond_queen == card )
350 modi += 1; // reference 126305
351
352 if ( card == Card::club_queen ) {
353 if( vgi.no() != trick.winnerplayer().no() ) {
354 modi -= 5; // reference 156330
355 }
356
357 if( vgi.game().teaminfo().get(ai) != ai.team() ) {
358 modi += 3; // previous 1
359 } else {
360 modi -= 4; // previous 2, 3
361 }
362
363 // show your own team.
364 if ( vgi.game().teaminfo().get(ai) != ai.team()
365 && ai.hand().count_trumps() <= 3 + (ai.hand().has_swines()?0:ai.hand().count_trump_aces())
366 && vgi.game().tricks().remaining_no() - 1 > ai.hand().count_trumps()
367 && (trick.cardno_of_player(trick.winnerplayer())
368 > trick.cardno_of_player(card.player())
369 && trick.jabs_cards_before( card.player() ))
370 )
371 {
372 modi += 4; // previous
373 if ( vgi.game().cards().count_played(Card::club_queen) == 0
374 && vgi.game().announcements().last(ai.team()).announcement == Announcement::noannouncement
375 )
376 modi += 12; // previous
377 }
378
379 if( trick.cardno_of_player(ai_virt) == 3
380 && trick.winnerplayer().team() != vgi.team() )
381 {
382 modi -= 3; // reference 234467
383 }
384
385 if( trick.cardno_of_player(ai_virt) == 0 )
386 modi -= 12; // reference 168423
387 }
388
389
390 #ifdef PLAYERCHECK
391 if (vgi.no() == playerCheck) {
392 COUT <<"MQ"<< modi << "\t";
393 }
394 #endif
395 return modi;
396 }
397
398 /** Modification for a jack
399 **/
400 int
modi_jack(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)401 TrickWeighting::modi_jack(VirtualGamesInterface const& vgi,
402 Trick const& trick,
403 Team const team,
404 HandCard const& card,
405 Team const winnerteam,
406 Ai const& ai)
407 {
408 int modi = 0;
409
410 if (!card.istrump()) {
411 return modi;
412 }
413
414 if( card.value() != Card::jack )
415 return modi;
416
417 if ( trick.cardno_of_player(card.player()) == 3 )
418 modi -= 2;
419
420 if ( trick.cardno_of_player(card.player()) == 1 )
421 modi += 14; // reference 028089
422
423 if ( trick.cardno_of_player(card.player()) == 0 )
424 modi += 22; //reference 114558
425
426 if( trick.startcard().istrump()
427 && trick.cardno_of_player(card.player()) !=0 )
428 modi += 5; //reference 099840
429
430
431 // force enemy with a jack to play a queen
432 if ( vgi.no() != trick.winnerplayer().no()
433 && (trick.cardno_of_player(trick.winnerplayer())
434 > trick.cardno_of_player(card.player())
435 && trick.jabs_cards_before( card.player() ) )
436 && (trick.winnercard().value() == Card::queen)
437 && (ai.team() != winnerteam)
438 && trick.winnercard().istrump() )
439 modi += 1;
440
441 Trick t( trick.startplayer());
442 for(unsigned i = 0; i == trick.cardno_of_player(card.player()); i++ )
443 {
444 t.add(trick.card( i ));
445 }
446
447 if ( vgi.no() != trick.winnerplayer().no() ) // playing jack and not winning trick
448 {
449 modi -= 6; // reference 133381
450
451 }
452
453 // save charlie in endgame for extra point
454 if( card == Card::charlie
455 && vgi.game().rule()(Rule::Type::extrapoint_charlie)
456 && vgi.game().tricks().remaining_no() -1 == ai.hand().count_trumps())
457 modi -= 23; // reference 71916
458
459 #ifdef PLAYERCHECK
460 if (vgi.no() == playerCheck) {
461
462 COUT <<"MJ"<< modi << "\t";
463
464 }
465 #endif
466 return modi;
467 }
468
469 /** modification for a fox
470 **/
modi_fox(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)471 int TrickWeighting::modi_fox(VirtualGamesInterface const& vgi,
472 Trick const& trick,
473 Team const team,
474 HandCard const& card,
475 Team const winnerteam,
476 Ai const& ai)
477 {
478 int modi = 0;
479
480 Player const& ai_virt = trick.game().player(ai.no());
481
482 // calculations for fox in trick
483 if ( vgi.no() != trick.winnerplayer().no()
484 && (trick.cardno_of_player(trick.winnerplayer())
485 > trick.cardno_of_player(card.player())
486 && trick.jabs_cards_before( card.player() ) )
487 && ai.value(Aiconfig::Type::limithigh).less(trick.winnercard())
488 && ai.team() != winnerteam )
489 {
490 for (unsigned c = 0; c < trick.actcardno(); c++)
491 {
492 if (trick.card(c).isfox() )
493 modi += 11;
494 }
495
496 }
497
498 if (( (vgi.no() != trick.startplayer().no())
499 || card.istrump())
500 ) {
501 for (unsigned c = 0; c < trick.actcardno(); c++) {
502 // test, whether the fox has been brought home
503
504 if (trick.card(c).isfox() )
505 {
506
507 if( (vgi.game().type() != GameType::poverty)
508 || !vgi.is_soloplayer())
509 {
510 unsigned fact = 25;
511 if( ai.value(Aiconfig::Type::hands_known)
512 || ai.value(Aiconfig::Type::trusting) )
513 {
514 fact += 10;
515 if( card.isfox() )
516 fact += 5;
517 }
518 if( !card.isfox() )
519 fact += 5;
520
521 bool allmyteam = true;
522
523 // take a look if all players coming in this trick are of mine team
524 for( unsigned i = trick.cardno_of_player(ai_virt); i < vgi.game().playerno(); i++ )
525 allmyteam = allmyteam && ( ai.team() == ai.teaminfo( trick.player_of_card( i ) ) );
526
527 if ( card.isfox()
528 && !trick.startcard().istrump()
529 && ai.color_runs( trick.startcard().color() ) > 0
530 && !allmyteam
531 && oppositeTeamCanWinTrick( trick, vgi ))
532 {
533 fact -= 21;
534 }
535
536
537
538 modi += fact * ((team == winnerteam)
539 ? +1
540 : -1);
541
542 } else { // fox from above neutralized.
543 if ( card.isfox() )
544 modi += 30 * ((team != winnerteam)
545 ? +1
546 : 0);
547 }
548 }
549 } // for (c < trick.actcardno())
550 } // if ( (vgi.no() != trick.startplayer().no()) || card.istrump())
551
552
553 // own fox
554 if( !card.isfox() )
555 {
556 #ifdef PLAYERCHECK
557 if (vgi.no() == playerCheck) {
558
559 COUT <<"MFA"<< modi << "\t";
560
561 }
562 #endif
563 return modi;
564 }
565
566 // to play a fox it must be worth it
567 {
568 modi -= 12; // previous 7, 16 (ref 208166)
569 }
570
571 if ( (vgi.no() != trick.startplayer().no())) {
572
573 if (maybe_to_team(winnerteam) == team)
574 {
575 if ( winnerteam == team
576 && ai.value(Aiconfig::Type::limithigh).less(trick.winnercard())
577 )
578 modi += 30; // fox home
579
580 }
581 }
582
583 // bad style to play fox as first card
584 if( trick.startplayer().no() == vgi.no() )
585 {
586 modi -= 90; // previous
587 }
588
589 if( trick.cardno_of_player(card.player()) == 3
590 && maybe_to_team(winnerteam) != team )
591 {
592 modi -= 6; // previous
593
594 if( ai.hand().count_trumps() <= 3 )
595 modi += 2; // reference
596 }
597
598 if( trick.cardno_of_player(card.player()) == 3
599 && winnerteam != team )
600 {// reference 93822
601 modi -= 35; // previous
602
603 }
604
605 if( trick.cardno_of_player(card.player()) == 3
606 && winnerteam == team )
607 {
608 modi += 5; // previous
609 }
610
611 #ifdef PLAYERCHECK
612 if (vgi.no() == playerCheck) {
613
614 COUT <<"MFB"<< modi << "\t";
615
616 }
617 #endif
618
619 return modi;
620 }
621
622 /** Modification for a meatless solo
623 **/
624 int
modi_soli_meat_less(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)625 TrickWeighting::modi_soli_meat_less(VirtualGamesInterface const& vgi,
626 Trick const& trick,
627 Team const team,
628 HandCard const& card,
629 Team const winnerteam,
630 Ai const& ai)
631 {
632 int modi = 0;
633
634 if ( vgi.game().type() != GameType::solo_meatless)
635 return modi;
636 if ( ai.no() != vgi.game().players().soloplayer().no()
637 && vgi.no() != trick.winnerplayer().no()
638 && ai.hand().count(card.color(), vgi.game()) > 0
639 && ai.hand().count(card.color(), vgi.game()) < 3
640 && ( ai.hand().count(Card(card.color(),Card::ace)) > 0
641 || ai.hand().count(Card(card.color(),Card::ten)) > 0
642 || card.value() == Card::ace || card.value() == Card::ten )
643 )
644 { // prevent non soloplayer from blank playing of cards
645 modi -= 12;
646 }
647
648 if ( ai.no() != vgi.game().players().soloplayer().no()
649 && vgi.no() != trick.winnerplayer().no()
650 && (card.value() == Card::ace || card.value() == Card::ten) )
651 modi -=3; // reference 004655
652
653
654 #ifdef PLAYERCHECK
655 if (vgi.no() == playerCheck) {
656
657 COUT <<"MSM"<< modi << "\t";
658
659 }
660 #endif
661
662 return modi;
663 }
664
665 /** Modification for a marriage
666 **/
667 int
modi_marriage(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)668 TrickWeighting::modi_marriage(VirtualGamesInterface const& vgi,
669 Trick const& trick,
670 Team const team,
671 HandCard const& card,
672 Team const winnerteam,
673 Ai const& ai)
674 {
675 if (vgi.game().type() != GameType::marriage)
676 return 0;
677
678 int modi = 0;
679
680 if ( (vgi.game().marriage().selector() != MarriageSelector::team_set)
681 && (card.value() >= 10) )
682 modi -= 9;
683
684 if (trick.cardno_of_player(card.player()) == 0) {
685 switch (vgi.game().marriage().selector()) {
686 case MarriageSelector::silent:
687 case MarriageSelector::team_set:
688 // the marriage is determined
689 break;
690 case MarriageSelector::first_color:
691 case MarriageSelector::first_foreign:
692 if (!card.istrump()) {
693 modi -= 5;
694 }
695 break;
696 case MarriageSelector::first_trump:
697 if (card.istrump()) {
698 modi -= 5;
699 }
700 break;
701 case MarriageSelector::first_club:
702 if ( !card.istrump()
703 && card.color() == Card::club ) {
704 modi -= 5;
705 }
706 break;
707 case MarriageSelector::first_spade:
708 if ( !card.istrump()
709 && card.color() == Card::spade) {
710 modi -= 5;
711 }
712 break;
713 case MarriageSelector::first_heart:
714 if ( !card.istrump()
715 && card.color() == Card::heart ) {
716 modi -= 5;
717 }
718 break;
719 } // switch (this->game().marriage().selector())
720 } // if !(marriage && !card is trickstartcard())
721
722 #ifdef PLAYERCHECK
723 if (vgi.no() == playerCheck) {
724 COUT <<"MM"<< modi << "\t";
725 }
726 #endif
727 return modi;
728 }
729
730 /** Modification for special points
731 **/
732 int
modi_special_points(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)733 TrickWeighting::modi_special_points(VirtualGamesInterface const& vgi,
734 Trick const& trick,
735 Team const team,
736 HandCard const& card,
737 Team const winnerteam,
738 Ai const& ai)
739 {
740 int modi = 0;
741
742 Game const& virt_game = trick.game();
743
744 // create the teams-vector
745 vector<Team> teams;
746 for (auto const& player : virt_game.players()) {
747 // determine team of player from ai out of virtual game
748 auto const t = ai.teamofplayer(player);
749 if (t != Team::unknown)
750 teams.push_back(maybe_to_team(t));
751 else
752 teams.push_back(opposite(maybe_to_team(ai.team())));
753 } // for (player)
754
755 if ( (vgi.no() != trick.startplayer().no())
756 || card.istrump()) {
757
758 if (maybe_to_team(winnerteam) == team) {
759 auto const spv = trick.specialpoints(teams);
760 modi += (30 * sum(spv, winnerteam, trick.startplayer().game()));
761 } else {
762 auto const spv = trick.specialpoints(teams);
763 modi -= (30 * sum(spv, winnerteam, trick.startplayer().game()));
764 }
765
766 } // if ( (vgi.no() != trick.startplayer().no()) || card.istrump())
767 #ifdef PLAYERCHECK
768 if (vgi.no() == playerCheck) {
769
770 COUT <<"MSP"<< modi << "\t";
771
772 }
773 #endif
774 return modi;
775 }
776
777 /** Modification for no trump
778 **/
779 int
modi_no_trump(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)780 TrickWeighting::modi_no_trump(VirtualGamesInterface const& vgi,
781 Trick const& trick,
782 Team const team,
783 HandCard const& card,
784 Team const winnerteam,
785 Ai const& ai)
786 {
787 int modi = 0;
788 if (card.istrump () )
789 return modi;
790
791 Player const& ai_virt = trick.game().player(ai.no());
792
793
794 if( vgi.no() != trick.winnerplayer().no()
795 && is_solo( vgi.game().type() )
796 && ( trick.cardno_of_player( trick.winnerplayer() ) > trick.cardno_of_player( trick.game().players().soloplayer() ) )
797 && !trick.card_of_player( trick.game().players().soloplayer() ).less( vgi.trump_card_limit() )
798 )
799 {
800 modi -= card.value();
801 }
802
803 if( is_solo( vgi.game().type() )
804 && trick.cardno_of_player( trick.game().players().soloplayer() ) == 0 )
805 {
806 modi += card.value();
807 if ( card.value() >= 10 )
808 modi += 3;
809 }
810
811 if( is_solo( vgi.game().type() )
812 && trick.cardno_of_player(ai_virt) == 0 )
813 {
814 // last card with small value to serve a trick
815 if( ai.hand().count( card.color() ) == 0
816 && card.value() < 10 )
817 modi += 34; // reference 64029
818 }
819
820 // game nears it end, no real sense to keep non trump carts any longer, better to hold trumps
821 if ( trick.cardno_of_player(ai_virt) == 0
822 && vgi.game().tricks().remaining_no() < 4 )
823 {
824 modi += 23; // reference 058753
825
826 }
827
828 if ( trick.cardno_of_player(ai_virt) == 0
829 && vgi.game().tricks().remaining_no() < 5 )
830 {
831
832 if ( vgi.team() == Team::re
833 && vgi.game().type() != GameType::marriage
834 && ai.cards_information().played(Card::club_queen)+ai.hand().count_club_queens()<2)
835 modi += 3; // reference 043205
836 }
837
838 if( vgi.no() != trick.winnerplayer().no()
839 && is_solo( vgi.game().type() )
840 && ( trick.cardno_of_player( trick.winnerplayer() ) > trick.cardno_of_player( trick.game().players().soloplayer() ) )
841 && trick.card_of_player( trick.game().players().soloplayer() ).less( vgi.trump_card_limit() )
842 )
843 modi += card.value();
844
845
846
847 // prefer color cards a little bit
848 if( card.value() == Card::nine
849 && trick.winnerplayer().team() != vgi.team() )
850 {
851 modi += 8; // previous: 6
852 if( trick.cardno_of_player(ai_virt) == 0 )
853 modi +=10; // reference 203953
854 }
855 if( card.value() == Card::king
856 && trick.winnerplayer().team() != vgi.team() )
857 modi += 8;
858
859 if( vgi.game().announcements().last( trick.winnerplayer().team() ).announcement != Announcement::noannouncement
860 && trick.winnerplayer().team() != vgi.team() )
861 {
862 // preserve trumps against announcement
863 modi += 6; //reference 006877
864 }
865
866 if ( card.value() == Card::ace )
867 {
868
869 modi -= 2 - vgi.color_runs( card.color() );
870 }
871
872 if( card.value() == Card::jack )
873 modi +=1; // good choice if not trump
874 // reference 112599
875
876 if( is_solo( vgi.game().type() )
877 && vgi.team() == Team::contra )
878 modi -= 2* ai.hand().count( card.color() ); // reference 137807
879
880
881 if ( vgi.no() != trick.winnerplayer().no()
882 && winnerteam != team
883 && trick.startcard().color() != card.color()
884 && !trick.startcard().istrump() )
885 {
886 modi -= 9; //previous 6, 16, 14, 8
887 // 9 : Reference 001236
888
889 if( trick.cardno_of_player(ai_virt) == 3
890 && card.value() >= 10 ) // reference 234467
891 modi -= 29;
892
893 }
894
895 if( trick.cardno_of_player(ai_virt) == 0
896 && card.value() == Card::nine
897 && vgi.color_runs( trick.startcard().color() ) > 0)
898 { modi+=7; } //reference 272170
899
900 bool allmyteam=true;
901
902 for( unsigned i = trick.cardno_of_player(ai_virt);
903 i < ai.game().playerno();
904 i++ )
905 allmyteam=allmyteam && ( ai.team() == ::maybe_to_team( vgi.teamofplayer( trick.player_of_card(i) ) ) );
906
907 if( !trick.startcard().istrump()
908 && vgi.color_runs( trick.startcard().color() ) > 0
909 && card.color() != trick.startcard().color()
910 && !allmyteam)
911 modi -= card.value()+2; //+2 reference 133381
912
913 if( (ai.hand().count_trumps() - 1 <= (vgi.game().tricks().remaining_no() + 1) / 2 ) )
914 {
915 // reference 61146
916 modi += 6;
917 //if fox is still on hand, protect fox.
918 if( ai.hand().count_trump_aces() > 0 && ai.hand().count_swines() == 0 )
919 {
920 modi += 6; //reference 052672
921 if( ai.hand().count_trumps() == 2 )
922 modi += 15; // reference 076221
923 }
924 }
925
926 if ( vgi.color_runs( card.color() ) == 0
927 && card.value() == Card::ace
928 && ai.team() == winnerteam
929 )
930 {
931 modi += 2;
932
933 }
934
935 if( is_solo( vgi.game().type() )
936 && trick.cardno_of_player(trick.game().players().soloplayer()) > trick.cardno_of_player(card.player())
937 && vgi.color_runs( card.color() ) == 0
938 && card.value() == Card::ace
939 )
940 {
941 modi += 22; // reference 9751
942 }
943
944 #ifdef PLAYERCHECK
945 if (vgi.no() == playerCheck) {
946
947 COUT <<"MNT"<< modi << "\t";
948
949 }
950 #endif
951 return modi;
952 }
953
954 /** Modification for a picture solo
955 **/
956 int
modi_picture_soli(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)957 TrickWeighting::modi_picture_soli(VirtualGamesInterface const& vgi,
958 Trick const& trick,
959 Team const team,
960 HandCard const& card,
961 Team const winnerteam,
962 Ai const& ai)
963 {
964 int modi = 0;
965
966 if( ( vgi.game().type() == GameType::solo_king
967 || vgi.game().type() == GameType::solo_king_jack
968 || vgi.game().type() == GameType::solo_king_queen
969 || vgi.game().type() == GameType::solo_koehler)
970 && card.value() == Card::king )
971 {
972 if( vgi.no() != trick.winnerplayer().no() )
973 {
974 modi -= (36 - std::max(static_cast<int>(ai.game().cards().count_played()) - 13, 0));
975 modi += trick.points()/2;
976
977 if( trick.cardno_of_player( trick.winnerplayer() )
978 < trick.cardno_of_player( card.player() )
979 || !trick.jabs_cards_before( card.player() ) )
980 modi -= 4;
981 } else
982 if( trick.cardno_of_player( card.player() ) == 3
983 && trick.points() < 16 ) // reference 131296
984 {
985 modi -= 25;
986 }
987 }
988
989 if( card.istrump()
990 && ( vgi.no() != trick.winnerplayer().no()
991 || trick.winnercardno() != 3)
992 && trick.cardno_of_player(card.player()) == 3 ) {
993 if ( vgi.game().type() != GameType::solo_king
994 && vgi.game().type() != GameType::solo_queen_jack
995 && vgi.game().type() != GameType::solo_king_jack
996 && vgi.game().type() != GameType::solo_king_queen
997 && vgi.game().type() != GameType::solo_koehler
998 && ( card.value() == Card::jack
999 || card.value() == Card::queen)
1000 ) { // a king is better, but has two points more
1001 modi -= 3;
1002 }
1003 }
1004
1005 if( ( vgi.game().type()==GameType::solo_king
1006 || vgi.game().type()==GameType::solo_king_jack
1007 || vgi.game().type()==GameType::solo_king_queen
1008 || vgi.game().type()==GameType::solo_koehler )
1009 && card.value() == Card::king )
1010 modi -= 2;
1011
1012
1013 if( card.istrump()
1014 && ( vgi.game().type()==GameType::solo_king
1015 || vgi.game().type()==GameType::solo_queen
1016 || vgi.game().type()==GameType::solo_jack
1017 )
1018 )
1019 modi -= 4;
1020
1021 #ifdef PLAYERCHECK
1022 if (vgi.no() == playerCheck) {
1023
1024 COUT <<"MPS"<< modi << "\t";
1025
1026 }
1027 #endif
1028 return modi;
1029 }
1030
1031 /** Modification for other trump
1032 **/
1033 int
modi_other_trumps(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)1034 TrickWeighting::modi_other_trumps(VirtualGamesInterface const& vgi,
1035 Trick const& trick,
1036 Team const team,
1037 HandCard const& card,
1038 Team const winnerteam,
1039 Ai const& ai)
1040 {
1041 int modi = 0;
1042 Game const& virt_game = trick.game();
1043 Player const& ai_virt = virt_game.player(ai.no());
1044
1045 if( !card.istrump () )
1046 return modi;
1047
1048 if ( trick.startcard().istrump()
1049 // ToDo: solo
1050 && !card.less(Card::diamond_queen)
1051 && (static_cast<int>(trick.points()) >= ai.value(Aiconfig::Type::limitqueen)) ) {
1052 modi += 2;
1053 }
1054
1055 if (is_solo(vgi.game().type())) {
1056 modi -= 2;
1057 if ( vgi.is_soloplayer()
1058 && card.value() == 0) {
1059 modi -= 12;
1060 }
1061 }
1062
1063 if( ( vgi.no() != trick.winnerplayer().no()
1064 || trick.winnercardno() != 3)
1065 && trick.cardno_of_player(card.player()) == 3 ) {
1066 modi -= 5; // previous -2
1067 }
1068
1069
1070 // have played a high card
1071 if ( ( ai.value(Aiconfig::Type::limithigh).less(card)
1072 || ai.value(Aiconfig::Type::limithigh) == card)
1073 && (static_cast<int>(trick.points()) - card.value()
1074 < ai.value(Aiconfig::Type::limitqueen) ) )
1075 {
1076 modi -= 3;
1077 if ((2 * ai.hand().count_ge(ai.value(Aiconfig::Type::limithigh))
1078 < ai.hand().count_trumps())
1079 && (ai.hand().count_ge(ai.value(Aiconfig::Type::limithigh))
1080 < 3))
1081 modi -= 13; // previous: 18
1082 }
1083
1084 if ( !trick.startcard().istrump()
1085 && (trick.cardno_of_player(card.player()) < 3)
1086 && card.less(ai.value(Aiconfig::Type::limithigh))
1087 && (static_cast<int>(trick.points()) >= ai.value(Aiconfig::Type::limitqueen))
1088 && trick.jabs_cards_before(card.player()) ) {
1089 modi -= 3;
1090 if ( vgi.color_runs( trick.startcard().color() ) > 0 )
1091 modi -= 6;
1092
1093 if ( is_solo(vgi.game().type())
1094 && trick.cardno_of_player(trick.game().players().soloplayer()) > trick.cardno_of_player(card.player()) )
1095 modi -= 7; // reference 197069
1096 }
1097
1098 if( (card.value() == Card::ten)
1099 && (!card.isdulle()) ) {
1100 modi -= 10; // reference 246985
1101 }
1102
1103 if( (card.value() == Card::ace)
1104 && !card.is_special() ) {
1105 modi -= 9; // reference 246985
1106 }
1107
1108 if( (card.value() == Card::king)
1109 && (winnerteam != team) ) {
1110 modi -= 14; // reference 256027
1111 }
1112
1113 if( (card.value() == Card::nine)
1114 && !card.is_special()
1115 && trick.winnercardno() == 3
1116 && trick.cardno_of_player(card.player()) == 3 )
1117 modi -= 3; // reference 064027_1
1118
1119
1120 if ( virt_game.cards().next_higher_card(card).value() != card.value() //2do nect_higher_card_still_in_game compar reference 260689
1121 && (trick.cardno_of_player(trick.winnerplayer())
1122 > trick.cardno_of_player(card.player()))
1123 && trick.jabs_cards_before( card.player() ))
1124 { // a higher card in value is needed to jab my card
1125 // for example a queen to jab my jack
1126 modi += 1;
1127 }
1128
1129
1130 bool allmyteam=true;
1131
1132 for( unsigned i = trick.cardno_of_player(ai_virt);
1133 i < ai.game().playerno();
1134 i++ )
1135 allmyteam=allmyteam && ( ai.team() == ::maybe_to_team( vgi.teamofplayer( trick.player_of_card(i) ) ) );
1136
1137 if( card.less( ai.value(Aiconfig::Type::limithigh) )
1138 && !trick.startcard().istrump()
1139 && (trick.cardno_of_player(trick.winnerplayer())
1140 > trick.cardno_of_player(card.player())
1141 && trick.jabs_cards_before( card.player() ) )
1142 && !( trick.islastcard()
1143 || allmyteam )
1144 ) {
1145 modi -= card.value() * std::min(vgi.color_runs( trick.startcard().color() ),
1146 2u);
1147 }
1148
1149 if ( (vgi.no() == trick.startplayer().no()))
1150 {
1151 modi -= 2;
1152
1153 if( ai.hand().count_trumps() == ai.hand().cardsnumber()
1154 && card.value() < 3 )
1155 modi +=5; // Reference 012664
1156
1157 if( (card.value() == Card::king)
1158 && (winnerteam == team) )
1159 modi += 8;
1160 }
1161
1162 { // the player has overjabbed his partner without need
1163 if (trick.winnerplayer() == ai) {
1164 Trick const t2 = trick.before_player(ai);
1165 if ( (::maybe_to_team(t2.winnerplayer().team()) == ai.team())
1166 && (vgi.trump_card_limit().less(t2.winnercard()))
1167 ) {
1168 modi -= 8;
1169 }
1170 }
1171 } // the player has overjabbed his partner without need
1172
1173 #ifdef PLAYERCHECK
1174 if (vgi.no() == playerCheck) {
1175 COUT <<"MOT"<< modi << "\t";
1176 }
1177 #endif
1178 return modi;
1179 }
1180
1181 /** Modification for a forced trump
1182 **/
1183 int
modi_force_trump(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)1184 TrickWeighting::modi_force_trump(VirtualGamesInterface const& vgi,
1185 Trick const& trick,
1186 Team const team,
1187 HandCard const& card,
1188 Team const winnerteam,
1189 Ai const& ai)
1190 {
1191 int modi = 0;
1192
1193 // force enemy to play high card
1194 if ( vgi.no() != trick.winnerplayer().no()
1195 && (trick.cardno_of_player(trick.winnerplayer())
1196 > trick.cardno_of_player(card.player())
1197 && trick.jabs_cards_before( card.player() ) )
1198 && ai.value(Aiconfig::Type::limithigh).less(trick.winnercard())
1199 && ai.team() != winnerteam )
1200 {
1201
1202 bool bIsForceTrump = true;
1203 // ToDo: start with
1204 for (unsigned c = trick.cardno_of_player(card.player()) + 1; c < trick.actcardno(); c++)
1205 {
1206 if (!trick.card(c).less(card))
1207 bIsForceTrump = false;
1208 } // for(c)
1209 if ( bIsForceTrump )
1210 modi += 27;
1211 }
1212
1213 #ifdef PLAYERCHECK
1214 if (vgi.no() == playerCheck) {
1215
1216 COUT <<"MFT"<< modi << "\t";
1217
1218 }
1219 #endif
1220 return modi;
1221 }
1222
1223 /** Modification for a poverty
1224 **/
1225 int
modi_poverty(VirtualGamesInterface const & vgi,Trick const & trick,Team const team,HandCard const & card,Team const winnerteam,Ai const & ai)1226 TrickWeighting::modi_poverty(VirtualGamesInterface const& vgi,
1227 Trick const& trick,
1228 Team const team,
1229 HandCard const& card,
1230 Team const winnerteam,
1231 Ai const& ai)
1232 {
1233 int modi = 0;
1234 if ( vgi.game().type() != GameType::poverty )
1235 return modi;
1236 Player const& ai_virt = trick.game().player(ai.no());
1237
1238 if( card.istrump()
1239 && trick.cardno_of_player(ai_virt) == 0)
1240 modi -= 3; // 1:reference 208016, 3: reference 194579
1241
1242 // get large cards of poverty player
1243 if(( //only for not poverty-player
1244 vgi.no() == vgi.game().players().poverty_partner().no() ))
1245 {
1246
1247 if( (trick.cardno_of_player(trick.game().players().soloplayer()) > trick.cardno_of_player(card.player())) //
1248 && !card.less(ai.value(Aiconfig::Type::limithigh))
1249 && card.player().no() != vgi.game().players().previous(vgi.game().players().soloplayer()).no())
1250 {
1251 modi += 21;
1252 if( ai.value(Aiconfig::Type::limithigh).less(trick.winnercard()) )
1253 modi += 5;
1254 if ( trick.winnercard().isdulle()
1255 || trick.winnercard().isswine()
1256 || trick.winnercard().ishyperswine() )
1257 modi +=4;
1258 }
1259 }
1260 #ifdef PLAYERCHECK
1261 if (vgi.no() == playerCheck) {
1262 // 4. block
1263 COUT << "MPV" << modi << "\t";
1264 }
1265 #endif
1266
1267 return modi;
1268 }
1269
1270 /** -> result
1271 **
1272 ** @param vgi the virtual games interface
1273 ** @param trick the trick to be examined
1274 ** @param t the team which should make points
1275 ** @param card the card played by the player
1276 **
1277 ** @return the weighting of the trick for the team 'team'
1278 **
1279 ** @todo perhaps points for getting the fox home
1280 ** @todo perhaps when playing the highest card, subtract in modi
1281 ** the distance to the next lower card
1282 **/
1283 int
modi(VirtualGamesInterface const & vgi,Trick const & trick,Team const t,HandCard const & card)1284 TrickWeighting::modi(VirtualGamesInterface const& vgi,
1285 Trick const& trick,
1286 Team const t,
1287 HandCard const& card)
1288 {
1289 DEBUG_ASSERTION(trick.isfull(),
1290 "TrickWeighting::modi()\n"
1291 " trick is not full");
1292 Game const& virt_game = trick.game();
1293 Ai const& ai = (dynamic_cast<Ai const*>(&virt_game.player(vgi.no()))
1294 ? dynamic_cast<Ai const&>(virt_game.player( vgi.no() ))
1295 : dynamic_cast<Ai const&>(vgi.game().player(vgi.no()))
1296 );
1297 Player const& ai_virt = virt_game.player(ai.no());
1298 //Team const winnerteam = ai.teamofplayer(trick.winnerplayer());
1299 Team winnerteam
1300 = ::maybe_to_team(vgi.teamofplayer(trick.winnerplayer()));
1301 if (winnerteam == Team::unknown)
1302 winnerteam = ::opposite(t);
1303
1304 if (virt_game.marriage().is_undetermined()) {
1305 // in an undetermined marriage all players shall play for themselves
1306 if (t == Team::re)
1307 winnerteam = ::maybe_to_team(ai.teaminfo(trick.winnerplayer()));
1308 else if (trick.winnerplayer().no() == vgi.no())
1309 winnerteam = ::maybe_to_team(t);
1310 else
1311 winnerteam = ::opposite(::maybe_to_team(t));
1312 }
1313
1314
1315 Team const team = ((virt_game.type() == GameType::marriage)
1316 ? maybe_to_team(t)
1317 : t);
1318
1319 int modi = 0;
1320
1321
1322 if (winnerteam == team)
1323 modi += trick.points();
1324 else
1325 modi -= trick.points();
1326
1327 #ifdef PLAYERCHECK
1328 // Playernumber for which to produce output
1329 playerCheck = PLAYERCHECK;
1330
1331 // so in virtual games no informatin is shown
1332 if (vgi.game().isvirtual())
1333 playerCheck = 10;
1334 #endif
1335
1336
1337
1338
1339 #ifdef PLAYERCHECK
1340 if (vgi.no() == playerCheck) {
1341 //COUT << trick.game().player(0).hand();
1342 COUT << '\n';
1343 COUT << trick << endl;
1344 COUT << team << "\t" << trick.winnerplayer().no() << " " << winnerteam << std::endl;
1345 for( unsigned i = 0; i < ai.game().playerno(); i++ )
1346 COUT << virt_game.player( i ).team() << "\t";
1347 COUT << std::endl;
1348 // 1. block
1349 COUT << card << "\t";
1350 }
1351 #endif
1352
1353 #ifdef PLAYERCHECK
1354 if (vgi.no() == playerCheck) {
1355
1356 COUT << "START" << modi << "\t";
1357
1358 }
1359 #endif
1360
1361 modi += modi_dulle_swines( vgi, trick, t, card, winnerteam, ai );
1362
1363 modi += modi_queen( vgi, trick, t, card, winnerteam, ai );
1364
1365 modi += modi_jack( vgi, trick, t, card, winnerteam, ai );
1366
1367 modi += modi_fox( vgi, trick, t, card, winnerteam, ai );
1368
1369 modi += modi_soli_meat_less( vgi, trick, t, card, winnerteam, ai );
1370
1371 modi += modi_marriage( vgi, trick, t, card, winnerteam, ai );
1372
1373 modi += modi_special_points( vgi, trick, t, card, winnerteam, ai );
1374
1375 modi += modi_no_trump( vgi, trick, t, card, winnerteam, ai );
1376
1377 modi += modi_picture_soli( vgi, trick, t, card, winnerteam, ai );
1378
1379 modi += modi_other_trumps( vgi, trick, t, card, winnerteam, ai );
1380
1381 modi += modi_force_trump( vgi, trick, t, card, winnerteam, ai );
1382
1383 modi += modi_poverty( vgi, trick, t, card, winnerteam, ai );
1384
1385
1386 bool allmyteam=true;
1387
1388 for (auto i = trick.cardno_of_player(ai_virt);
1389 i < ai.game().playerno();
1390 i++ )
1391 allmyteam = allmyteam && ( ai.team() == ::maybe_to_team( vgi.teamofplayer( trick.player_of_card(i) ) ) );
1392
1393 /// @todo jabbed by player of other team behind me
1394 if( !trick.startcard().istrump()
1395 && vgi.jabbedbyotherteam( trick.startcard().color() )
1396 && card.value() >= 10
1397 && !allmyteam
1398 && oppositeTeamCanWinTrick( trick, vgi )
1399 ) {
1400 modi -= 4;
1401 #ifdef PLAYERCHECK
1402 if (vgi.no() == playerCheck) {
1403
1404 COUT << "XX " << modi << "\t";
1405 }
1406 #endif
1407 }
1408
1409 #ifdef PLAYERCHECK
1410 if (vgi.no() == playerCheck) {
1411 COUT << "END" << modi << endl;
1412 }
1413 #endif
1414
1415 return modi;
1416 } // int WVirtualGames::modi(Trick const& trick, Team const& team, Card const& card)
1417
1418
1419 /** -> result
1420 **
1421 ** @param vgi virtual game interface
1422 ** @param c the card played by the player
1423 ** @param virt_game actual virtual game
1424 **
1425 ** @return weighting modifier for getting own team in backhand
1426 **/
1427 int
backhand(VirtualGamesInterface const & vgi,HandCard const & c,Game const & virt_game)1428 TrickWeighting::backhand(VirtualGamesInterface const& vgi,
1429 HandCard const& c,
1430 Game const& virt_game )
1431 {
1432 int result = 0;
1433
1434 // add some points, if the own team is in the back,
1435 if (virt_game.players().previous( virt_game.tricks().current().winnerplayer() ).team()
1436 == vgi.team() && !c.isfox() &&
1437 vgi.game().type() != GameType::solo_meatless )
1438 {
1439 result = 5;
1440
1441 if( virt_game.tricks().current().points() > 10 )
1442 result -= 3; // Bugreport reference 1236
1443
1444 if (virt_game.type() == GameType::poverty )
1445 result -= 3;
1446 }
1447 else
1448 result = -6;
1449
1450
1451 return result;
1452 }
1453
1454