1 /*--------------------------------------------------------------------------
2
3 REVERSEM :
4
5 UNIT : Main unit
6
7 COPYRIGHT (C) 1994 Erich P. Gatejen ALL RIGHTS RESERVED
8 This is Freeware. You may distribute it as you wish. However, you may not
9 distribute a modified version without my consent.
10
11 Feel free to cut and paste any algorthm.
12
13 NOTE: XTILE is (C) 1992, 1994 by myself. It is NOT freeware. You may use
14 it for personal projects, but otherwise, it is not to be distributed
15 outside this REVERSEM package. (Contact me if you wish to do
16 otherwise)
17
18 ---------------------------------------------------------------------------*/
19
20 // ------------------------------------------------------------------------
21 // --- INCLUDES
22 // ------------------------------------------------------------------------
23 #include<stdlib.h>
24 #include<stdio.h>
25 extern "C" {
26 #include "xtile21!.h"
27 };
28 #include<conio.h>
29 #include<dos.h>
30 #include<alloc.h>
31 #include"heap.hpp"
32 #include"reversem.hpp"
33 #include"eval.hpp"
34 #include"spots.hpp"
35 #include"board.hpp"
36 #include"graphics.hpp"
37
38 // ------------------------------------------------------------------------
39 // --- DEFINITIONS
40 // ------------------------------------------------------------------------
41
42 // --- In game status
43 enum STATUS { STATUS_CONT = 0, STATUS_END, STATUS_DONE, STATUS_NEW };
44
45 // --- Timing definitions (all in miliseconds)
46 #define BUTTON_TIME 500
47
48
49 // ------------------------------------------------------------------------
50 // --- CLASSES
51 // ------------------------------------------------------------------------
52
53 // --- This prototype is need here!
54 void *getnew( void );
55
56 // --- MMNode. A minimax node --------------------------------------------
57 class MMNode: public Board {
58
59 MMNode *Children[MAX_CHILDREN];
60
61 int NumberChildren;
62
63 SpotStates Owner;
64
65 static unsigned int CurrentPly;
66 static Go AGoTo;
67
68 public:
69
70 // Constructors
71 MMNode( Board *OldBoard, SpotStates Who ) : Board( OldBoard ) {
72 Owner = Who;
73 };
74
75 MMNode( Spot TheSpots[BOARDXSIZE][BOARDYSIZE],
76 SpotStates Who ) : Board( TheSpots ) {
77 Owner = Who;
78 };
79
80 MMNode( Spot TheSpots[BOARDXSIZE][BOARDYSIZE],
81 Go GoTo, SpotStates Who ) : Board( TheSpots ) {
82 // This will make the move that creates this board
83 Owner = Who;
84 DoGo( GoTo, Owner );
85 };
86 ~MMNode( void ) {};
87
88 void SetPly( unsigned int Ply ) { CurrentPly = Ply; };
89
90 // Enter the tree, call for root only
91 heuristic TREE( SpotStates ThePlayer,
92 Go &TheMove );
93
94 // Enter the tree, call all non-root nodes
95 heuristic TREE( heuristic UseThresh, // For A/B pruning
96 heuristic PassThresh,
97 BOOLEAN Pass = FALSE // So we can tell an end move
98 );
99
100 // DAMN THING IS DRIVING ME NUTS!!! Overload new.
101 void * operator new( size_t size ) { return( getnew() ); };
102 void operator delete( void *p ) {}; // Don't delete anything.
103 // The heap will handle it
104 // OK, lesson learned. DO NOT recursively delete!!!
105 // and don't use Borlands heap. It blows up EVERY time!!!
106 };
107
108
109
110 // ------------------------------------------------------------------------
111 // --- DATA DECLARATIONS
112 // ------------------------------------------------------------------------
113
114 // --- Static members of MMNode
115 unsigned int MMNode::CurrentPly;
116 Go MMNode::AGoTo;
117
118 // --- Global variables
119
120 // Plys for each Brain levels
121 unsigned int MaxPlys4Level[EXPERIMENTAL+1] = {
122
123 2, // Simpleton
124 3, // Dullard
125 3, // Average
126 4, // Swift
127 5, // Genius // <- 5 may be too high, I'm not sure.
128 6, // Experimental
129
130 // NOTE: With the heap limit set the way it is, any plys over
131 // 5 may cause it to actually get stupider <sic>.
132
133 };
134
135 // Boards
136 Board MasterBoard;
137
138 // Default the brain setting at the lowest level.
139 BRAIN BrainSetting = SIMPLETON;
140
141 // --- Define the graphics control item
142 GraphicsControl GCI;
143
144 // --- Give use a bigger stack!!!
145 extern unsigned _stklen = ( 16 * 1024 );
146
147 // --- Define the heap for the minimax tree.
148 Heap MMHeap( sizeof( class MMNode ) );
149
150 // --- Running score
151 int RunningScore = 0;
152
153 // --- Flag show heuristic
154 BOOLEAN ShowH = FALSE;
155
156
157 // ------------------------------------------------------------------------
158 // --- FUNCTIONS PROTOTYPES
159 // ------------------------------------------------------------------------
160 void ComputerMoves( void );
161 void HelpHuman( void );
162 heuristic MINiMAX( SpotStates ThePlayer,
163 Go &TheMove,
164 Board TheBoard );
165
166
167 // -----------------------------------------------------------------------
168 // --- FUNCTIONS
169 // -----------------------------------------------------------------------
170
171 // -- Heap allocate fof the overloaded new -------------------------------
172 void *getnew( void ) {
173 return ( MMHeap.Allocate() );
174 };
175
176 // -- Computer moves -----------------------------------------------------
177 void ComputerMoves( void ) {
178
179 Go AGo;
180
181 heuristic H;
182
183 char Buffer[40];
184
185 // Say I'm thinking
186 GCI.Me.ShowPicture( PIC_THINKING );
187 GCI.Me.SayText( "OK. GIVE ME A 'SEC.", NULL, NULL );
188 delay( 200 );
189
190 // Amove exists. Generate the move we want
191 MasterBoard.BrainIs( BrainSetting );
192 H = MINiMAX( SPOT_BLACK, AGo, MasterBoard );
193
194 // OK. Show where I wanna go
195 GCI.Me.ShowPicture( PIC_LOOKRIGHT );
196 GCI.Me.SayText( "I WILL GO HERE", NULL, NULL );
197 GCI.Here( AGo );
198 delay( 1000 );
199
200 // We have a move. Apply it and show it.
201 MasterBoard.DoGo( AGo, SPOT_BLACK );
202 GCI.ShowBoard( MasterBoard );
203
204
205 // --- OK. Respond to the move.
206
207 // If on, show H
208 if ( ShowH ) {
209 itoa( H, Buffer, 10);
210 XSet_Box( 112, 235, 80, 5, 0 );
211 XString4_C( 116, 235, 15, Buffer );
212 };
213
214 // Show my reaction
215 if ( H > A_EXCELLENT ) {
216 GCI.Me.ShowPicture( PIC_HALFSMILE );
217 GCI.Me.SayText( "HE HE HE HE", "NOT LOOKING TO BAD", "FOR ME HERE" );
218 } else
219 if ( H > A_GOOD ) {
220 GCI.Me.ShowPicture( PIC_HALFSMILE );
221 GCI.Me.SayText( "WELL, NOT BAD.", NULL, NULL );
222 } else
223 if ( H > A_OK ) {
224 GCI.Me.ShowPicture( PIC_LOOKRIGHT );
225 GCI.Me.SayText( "HMMMMM...", "I'M NOT SURE WHAT TO", "THINK HERE." );
226 } else
227 if ( H > A_UNKNOWN ) {
228 GCI.Me.ShowPicture( PIC_CALM );
229 GCI.Me.SayText( "WELL. THIS COULD GO", "EITHER WAY.", NULL );
230 } else
231 if ( H > A_UNGOOD ) {
232 GCI.Me.ShowPicture( PIC_CURIOUSFROWN );
233 GCI.Me.SayText( "UGG.", "THIS DOESN'T LOOK", "PROMISING" );
234 } else
235 if ( H > A_BAD ) {
236 GCI.Me.ShowPicture( PIC_LOOKRIGHTC );
237 GCI.Me.SayText( "OH.", "THIS IS NOT GOOD!", NULL );
238 } else {
239 GCI.Me.ShowPicture( PIC_FROWN );
240 GCI.Me.SayText( "I'M DEAD.", NULL, NULL );
241 };
242
243 };
244
245 // -- Help human with a move -----------------------------------------------
246 void HelpHuman( void ) {
247
248 Go AGo;
249
250 char Buffer[40];
251
252 // Say I'm thinking
253 GCI.Me.ShowPicture( PIC_THINKING );
254 GCI.Me.SayText( "OK. GIVE ME A 'SEC.", NULL, NULL );
255 delay( 200 );
256
257 // Amove exists. Generate the move we want
258 MasterBoard.BrainIs( BrainSetting );
259 MINiMAX( SPOT_WHITE, AGo, MasterBoard );
260
261 // OK. Show where I wanna go
262 GCI.Me.ShowPicture( PIC_IDEA );
263 GCI.Me.SayText( "I HAVE AN IDEA", NULL, NULL );
264 delay( 1000 );
265
266 // OK. Show where I wanna go
267 GCI.Me.ShowPicture( PIC_LOOKRIGHT );
268 GCI.Me.SayText( "I WOULD GO HERE", NULL, NULL );
269 GCI.Here( AGo );
270 delay( 1000 );
271
272
273
274 };
275
276
277 // -- Handle the end of a game ---------------------------------------------
278 void EndGame( void ) {
279
280 int PlayerCount;
281
282 // Count the players points and determine a win or loss
283 PlayerCount = MasterBoard.Count( SPOT_WHITE );
284
285 if ( PlayerCount == 0 ) {
286
287 // A draw
288 GCI.Me.ShowPicture( PIC_CALM );
289 GCI.Me.SayText( "HEY, HOW DID THAT", "HAPPENED.", "WE TIED!" );
290
291 } else if ( PlayerCount < 0 ) {
292
293 // A loss
294 GCI.Me.ShowPicture( PIC_VICTORY );
295 GCI.Me.SayText( "HA HA HA HA HA", "I WIN!", NULL );
296
297
298 } else {
299
300 // A win
301 GCI.Me.ShowPicture( PIC_WHATUPSET );
302 GCI.Me.SayText( "HEY!!!", "HOW DID YOU DO THAT.", "YOU WIN" );
303
304 }
305
306 RunningScore += PlayerCount;
307 GCI.Score( RunningScore );
308
309 };
310
311 // -- Minimax function ------------------------------------------------------
312 heuristic MINiMAX( SpotStates ThePlayer,
313 Go &TheMove,
314 Board TheBoard ) {
315
316 int X, Y;
317
318 heuristic H;
319
320 register int Step;
321
322 heuristic PassThresh = VERY_BAD_THING;
323 heuristic UseThresh = VERY_GOOD_THING;
324
325 Go ChildGoTo[MAX_CHILDREN];
326 heuristic ChildValue[MAX_CHILDREN];
327 MMNode *Children[MAX_CHILDREN];
328 unsigned int NumberChildren;
329
330
331 // OK, do the drudgery. Make the children.. For this player
332 // Only here will we have to remeber the moves.
333 NumberChildren = 0;
334 for ( X = 0; X < BOARDXSIZE; X++ ) {
335 for ( Y = 0; Y < BOARDYSIZE; Y++ ) {
336
337 ChildGoTo[NumberChildren].XIs( X );
338 ChildGoTo[NumberChildren].YIs( Y );
339
340 if ( TheBoard.ValidGo( ChildGoTo[NumberChildren], ThePlayer ) ) {
341
342 // ---- Found a child. Build 'em ----
343
344 // Reset the Heap
345 MMHeap.Reset();
346
347 Children[NumberChildren] =
348 new MMNode( TheBoard.Spots, ChildGoTo[NumberChildren],
349 ThePlayer );
350
351 // If it is a NULL pointer, we are not getting anymore
352 if ( Children[NumberChildren] == NULL ) {
353 X = BOARDXSIZE; // So it breaks out of both 'for's
354 break;
355 }
356
357 Children[NumberChildren]->SetPly( 1 );
358
359 // Oh No! recursion!
360 ChildValue[NumberChildren] =
361 Children[NumberChildren]->TREE( -PassThresh, -UseThresh );
362 // WARNING!!! ^^^^^^^
363 // Do A/B pruning
364 H = ChildValue[NumberChildren]; // Negate it
365
366 H = -H;
367 if ( H > PassThresh ) {
368
369 // A better value for the pass threshhold
370 PassThresh = H;
371
372 }
373
374 // Prepare for another iteration.
375 NumberChildren++;
376 if ( NumberChildren == MAX_CHILDREN ) {
377 X = BOARDXSIZE;
378 break;
379 }
380
381 }
382 }
383 }
384
385 // Find the best move and value.. and return it
386 H = ChildValue[0];
387 X = 0;
388 for ( Step = 1; Step < NumberChildren; Step++ ) {
389 if ( ChildValue[Step] > H ) {
390 H = ChildValue[Step];
391 X = Step;
392 }
393 };
394 TheMove = ChildGoTo[X];
395
396 return( H );
397
398
399 };
400
401
402
403
404 // ------------------------------------------------------------------------
405 // --- MEMBERS
406 // ------------------------------------------------------------------------
407
408 // --- MMNode class ---------------------------------------------------------
409
410 // -- The recursive tree function
411 heuristic MMNode::TREE( heuristic UseThresh, // For A/B pruning
412 heuristic PassThresh,
413 BOOLEAN Pass // So we can tell an end move
414 ) {
415
416 int X, Y;
417 SpotStates OtherGuy;
418 heuristic H;
419
420 register int Step;
421
422 // Who's the other guy? (Just flip the owner)
423 if( Owner == SPOT_BLACK )
424 OtherGuy = SPOT_WHITE;
425 else
426 OtherGuy = SPOT_BLACK;
427
428 // OK, have I reached the end of my plys for the level?
429 if ( CurrentPly == MaxPlys4Level[BrainLevel] ) {
430
431 // Is is a win or loss situation.
432 if (Pass) {
433
434 // If no more children can be created, then it is
435 for ( X = 0; X < BOARDXSIZE; X++ ) {
436 for ( Y = 0; Y < BOARDYSIZE; Y++ ) {
437
438 AGoTo.XIs( X );
439 AGoTo.YIs( Y );
440
441 if ( ValidGo( AGoTo, OtherGuy ) )
442 return ( Evaluate(Owner) );
443 }
444 }
445
446 // No valid moves. It is the end of a game.
447 return( WinOrLose(Owner) );
448
449 } // end if pass situation
450
451 // Just evaluate self and unroll recusive call
452 return( Evaluate(Owner) );
453
454 };
455
456 // OK, do the drudgery. Make the children
457 NumberChildren = 0;
458 for ( X = 0; X < BOARDXSIZE; X++ ) {
459 for ( Y = 0; Y < BOARDYSIZE; Y++ ) {
460
461 AGoTo.XIs( X );
462 AGoTo.YIs( Y );
463
464 if ( ValidGo( AGoTo, OtherGuy ) ) {
465
466 // Found a child. Build 'em
467 Children[NumberChildren] = new MMNode( Spots, AGoTo, OtherGuy );
468
469 // If it is a NULL pointer, we are not getting anymore
470 if ( Children[NumberChildren] == NULL ) {
471 X = BOARDXSIZE;
472 break;
473 }
474
475 // Otherwise, tick up one more ply
476 CurrentPly++;
477
478 // Oh No! recursion!
479 H = Children[NumberChildren]->TREE( -PassThresh, -UseThresh );
480
481 // Tack back the ply one
482 CurrentPly--;
483
484 // Do A/B pruning
485 H = -H; // Negate it
486 if ( H > PassThresh ) {
487
488 // A better value for the pass threshhold
489 PassThresh = H;
490
491 } else
492 if ( PassThresh >= UseThresh ) {
493
494 // not a better value. Stop pursuing this branch
495 return( PassThresh );
496
497 };
498
499 // Prepare for another iteration.
500 NumberChildren++;
501 if ( NumberChildren == MAX_CHILDREN ) {
502 X = BOARDXSIZE;
503 break;
504 }
505
506 }
507 }
508 }
509
510 // Ok, if no children, it is a pass. If this function was called with
511 // a pass, then it is a game ender. Evaluate as a winner or loser.
512 // Else, make a single pass child, and recurse into it
513 if ( NumberChildren == 0 ) {
514
515 // Account for no children due to lack of memory
516 if ( Children[NumberChildren] == NULL ) return( Evaluate(Owner) );
517
518 if ( Pass ) {
519
520 return( WinOrLose(Owner) );
521
522 } else {
523
524 // Build the child if we can. Else return current board eval
525 Children[NumberChildren] = new MMNode( Spots, OtherGuy );
526
527 // Otherwise, tick up one more ply
528 CurrentPly++;
529
530 // Oh No! recursion!
531 PassThresh =
532 Children[NumberChildren]->TREE( -PassThresh, -UseThresh, TRUE );
533
534 // Tack back the ply one
535 CurrentPly--;
536
537 NumberChildren = 1;
538
539 } // end if pass
540
541 }
542
543 // This joker has explored all it's children.
544 return( PassThresh );
545
546 };
547
548 // ------------------------------------------------------------------------
549 // --- PRIMARY GAME ROUND ROUTINE - StartGame
550 // ------------------------------------------------------------------------
551
552 STATUS StartGame( SpotStates WhoStarts ) {
553
554 STATUS TheStatus = STATUS_CONT;
555 SpotStates WhosTurn = WhoStarts;
556 USER_ACTION Command;
557
558 BOOLEAN Pass = FALSE;
559 Go AGo;
560
561 // Reset the master board and show it
562 MasterBoard.InitBoard2Start();
563 GCI.ShowBoard( MasterBoard );
564
565 // Keep playing
566 while( TheStatus == STATUS_CONT ) {
567
568 if ( WhosTurn == SPOT_BLACK ) {
569
570 // Computer turn
571
572 // Is there a move?
573 if ( !MasterBoard.MoveExists( WhosTurn ) ) {
574
575 // No move exists. If end game, end. Else pass.
576 if ( Pass ) {
577
578 // End game
579 TheStatus = STATUS_END;
580 EndGame();
581
582 } else {
583
584 // Pass
585 GCI.Me.ShowPicture( PIC_CURIOUSFROWN );
586 GCI.Me.SayText( "HMMM!!!", "LOOKS LIKE I HAVE TO", "PASS" );
587 delay( 1000 );
588 Pass = TRUE;
589
590 } // end if game end
591
592 } else {
593
594 // Clear the pass flag and move
595 Pass = FALSE;
596 ComputerMoves();
597
598 }
599
600 } else {
601
602 // Player turn
603
604 // Is there a move?
605 if ( !MasterBoard.MoveExists( WhosTurn ) ) {
606
607 // No move exists. If end game, end. Else pass.
608 if ( Pass ) {
609
610 // End game
611 TheStatus = STATUS_END;
612 EndGame();
613
614 } else {
615
616 // Pass
617 GCI.YouMustPass();
618 Pass = TRUE;
619
620 } // end if game end
621
622 } else {
623
624 // Show valid moves
625 GCI.ShowValidMoves( MasterBoard );
626
627 // Clear the pass flag
628 Pass = FALSE;
629
630 // Loop until the player does something that shifts turns or quits
631 do {
632
633 Command = GCI.WaitUser( AGo );
634
635 // Switch through actions
636 switch( Command ) {
637
638 // Set brain levels
639 case CLICK_BRAIN1:
640 BrainSetting = SIMPLETON;
641 GCI.BrainSetting( SIMPLETON );
642 break;
643 case CLICK_BRAIN2:
644 BrainSetting = DULLARD;
645 GCI.BrainSetting( DULLARD );
646 break;
647 case CLICK_BRAIN3:
648 BrainSetting = AVERAGE;
649 GCI.BrainSetting( AVERAGE );
650 break;
651 case CLICK_BRAIN4:
652 BrainSetting = SWIFT;
653 GCI.BrainSetting( SWIFT );
654 break;
655 case CLICK_BRAIN5:
656 BrainSetting = GENIUS;
657 GCI.BrainSetting( GENIUS );
658 break;
659 case CLICK_BRAIN6:
660 BrainSetting = EXPERIMENTAL;
661 GCI.BrainSetting( EXPERIMENTAL );
662 break;
663
664 case CLICK_HELP: GCI.PushMainButton( HELP_BUTTON );
665 HelpHuman();
666 GCI.PopMainButton( HELP_BUTTON );
667 break;
668
669 case CLICK_DONE: GCI.PushMainButton( DONE_BUTTON );
670 GCI.Me.ShowPicture( PIC_ARMSCROSS );
671 GCI.Me.SayText( "CHICKEN!", "ARE YA?", NULL );
672 delay( 1000 );
673 GCI.PopMainButton( DONE_BUTTON );
674
675 // End it all
676 if (GCI.YouSure()) {
677
678 TheStatus = STATUS_DONE;
679 Command = CLICK_DONE;
680
681 } else {
682
683 GCI.Me.ShowPicture( PIC_CALM);
684 GCI.Me.SayText( "GOOD", "THAT'S BETTER", NULL );
685 delay( 1000 );
686
687 // Dummy command so it will
688 // continue allowing user to click
689 Command = CLICK_HELP;
690
691 }
692 break;
693
694 case CLICK_NEW : GCI.PushMainButton( NEW_BUTTON );
695 GCI.Me.ShowPicture( PIC_WHAT );
696 GCI.Me.SayText( "NEW GAME?", "I'M GONNA HAVE TO", "DOCK YOU 100 POINTS" );
697 delay( 1000 );
698 GCI.PopMainButton( NEW_BUTTON );
699
700 // End it all
701 if (GCI.YouSure()) {
702
703 GCI.Me.ShowPicture( PIC_CALM);
704 GCI.Me.SayText( "OK", "YOU'RE THE BOSS", NULL );
705
706 RunningScore -= 100;
707 GCI.Score( RunningScore );
708
709 TheStatus = STATUS_NEW;
710 Command = CLICK_DONE;
711
712 } else {
713
714 GCI.Me.ShowPicture( PIC_CALM);
715 GCI.Me.SayText( "GOOD", "THAT'S BETTER", NULL );
716 delay( 1000 );
717
718 }
719 break;
720
721 case CLICK_BOARD:
722 if ( MasterBoard.ValidGo(AGo, SPOT_WHITE) ) {
723
724 // A valid player move
725 MasterBoard.DoGo( AGo, SPOT_WHITE );
726 GCI.ShowBoard( MasterBoard );
727
728 // Break out
729 Command = CLICK_DONE;
730 }
731 break;
732
733
734 } //end case
735
736
737 } while( Command != CLICK_DONE );
738
739 } // end if move exists
740
741 } // end if player turn
742
743 // Flip turn
744 if ( WhosTurn == SPOT_WHITE ) WhosTurn = SPOT_BLACK;
745 else WhosTurn = SPOT_WHITE;
746
747 } // end while play
748
749 return( TheStatus );
750
751
752 };
753
754
755
756 // ------------------------------------------------------------------------
757 // --- MAIN
758 // ------------------------------------------------------------------------
759 void main( int argn, char *argc[] ) {
760
761 // SORRY!! ^^^ will cause a warning
762
763 USER_ACTION Command;
764 BOOLEAN YouFirst;
765
766 Go DummyGo;
767
768 STATUS ReturnStatus;
769
770 randomize();
771
772 // Should we show the heuristic?
773 if ( argn > 1 ) ShowH = TRUE;
774
775 // First time in, so go ahead and init main screen
776 GCI.InitMainScreen();
777
778 // Scrub it
779 ReturnStatus = STATUS_CONT;
780
781 // Loop through user actions
782 do {
783
784 // Check for a new game request during last game
785 if ( ReturnStatus == STATUS_NEW ) {
786 Command = CLICK_NEW;
787
788 } else
789 Command = GCI.WaitUser( DummyGo );
790
791
792 // Switch through actions
793 switch( Command ) {
794
795 // Set brain levels
796 case CLICK_BRAIN1:
797 BrainSetting = SIMPLETON;
798 GCI.BrainSetting( SIMPLETON );
799 break;
800 case CLICK_BRAIN2:
801 BrainSetting = DULLARD;
802 GCI.BrainSetting( DULLARD );
803 break;
804 case CLICK_BRAIN3:
805 BrainSetting = AVERAGE;
806 GCI.BrainSetting( AVERAGE );
807 break;
808 case CLICK_BRAIN4:
809 BrainSetting = SWIFT;
810 GCI.BrainSetting( SWIFT );
811 break;
812 case CLICK_BRAIN5:
813 BrainSetting = GENIUS;
814 GCI.BrainSetting( GENIUS );
815 break;
816 case CLICK_BRAIN6:
817 BrainSetting = EXPERIMENTAL;
818 GCI.BrainSetting( EXPERIMENTAL );
819 break;
820
821 case CLICK_HELP: GCI.PushMainButton( HELP_BUTTON );
822 delay( BUTTON_TIME );
823 GCI.PopMainButton( HELP_BUTTON );
824 break;
825
826 case CLICK_NEW: GCI.PushMainButton( NEW_BUTTON );
827 delay( BUTTON_TIME );
828
829 GCI.PopMainButton( NEW_BUTTON );
830 YouFirst = GCI.WhoFirst();
831 if( YouFirst )
832 ReturnStatus = StartGame(SPOT_WHITE);
833 else
834 ReturnStatus = StartGame(SPOT_BLACK);
835
836 // Check for quit
837 if ( ReturnStatus == STATUS_DONE )
838 Command = CLICK_DONE;
839
840 break;
841
842 case CLICK_DONE: GCI.PushMainButton( DONE_BUTTON );
843 delay( BUTTON_TIME );
844 GCI.PopMainButton( DONE_BUTTON );
845 break;
846
847
848 } //end case
849
850
851 } while( Command != CLICK_DONE );
852
853 // Done
854 GCI.Me.ShowPicture( PIC_BYE );
855 GCI.Me.SayText( "GOODBYE!", NULL, NULL );
856 delay( 3000 );
857
858 };
859
860
|