/[projet1]/users/barnsey123/HNEFATAFL/main.c
Defence Force logotype

Contents of /users/barnsey123/HNEFATAFL/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 934 - (show annotations)
Mon Jun 3 15:10:45 2013 UTC (6 years, 10 months ago) by barnsey123
File MIME type: text/plain
File size: 76359 byte(s)
v0.050 - color cursor and twilighte dedication
1 // HNEFATAFL by Neil Barnes (a.k.a. Barnsey123)
2 // 24-08-2012 NB: Tided up source (removed "bracket hell")
3 // 27-08-2012 NB: v0.012 Minor changes to save memory
4 // 27-08-2012 NB: v0.013 Created Priority array and routine to populate it
5 // 28-08-2012 NB: v0.014 Add hightarget to pacman checkroute (when route to corners are empty)
6 // 30-08-2012 NB: V0.015 updated pacman routines - added brokenarrow
7 // 01-09-2012 NB: V0.016 Fixed brokenarrow
8 // 02-09-2012 NB: v0.017 Compressed - and fixed - checkroute()
9 // 03-09-2012 NB: v0.018 Rejigged pacman (do a while...to edge)
10 // 05-09-2012 NB: v0.019 pacman2
11 // 21-10-2012 NB: v0.020 Fixed bug in gspot
12 // 22-10-2012 NB: v0.021 Fixed bugs in following:
13 // pacman2 [not calculating hightarget in right place, not doing brokenarrow properly)
14 // sub [not calcing points properly]
15 // 23-10-2012 NB: v0.022 Removed some redundant code (enemytargetupdate)
16 // 24-04-2013 NB: v0.023 starting to add DEADPILE
17 // 25-04-2013 NB: v0.024 Font Changes for deadpile, endgame detection improvements, some memory reduction
18 // 27-04-2013 NB: v0.025 Some changes to make code clearer
19 // 29-04-2013 NB v0.026 some more cleary uppy stuff . fixed bug in endgame detection.broken arrow not working.
20 // 29-04-2013 NB v0.027 adding kingtracker (all the spaces where the king can get to
21 // 01-05-2013 NB v0.028 Brokenarrow fixed
22 // 01-05-2013 NB v0.029 Potential Broken Arrow Situation
23 // 02-05-2013 NB v0.030 Fixed central square "backbone" issue
24 // 02-05-2013 NB v0.031 Added TRIGGER weighting and changes to brokenarrow
25 // 04-05-2013 NB v0.032 Replecaed g variable in gspot with kingtoedge array
26 // 04-05-2013 NB v0.033 Introduced pacman3 and some changes to subpacmanx
27 // 07-05-2013 NB v0.040 Skip 03x coz of differnt versions floating about
28 // 07-05-2013 NB v0.041 Fixed a few bugs, reduced footprint
29 // 08-05-2013 NB v0.042 resolving the vinegar strokes (trying)
30 // 08-05-2013 NB v0.043 SHAZAM! One major bug resolved (broken arrow issue)
31 // 09-05-2013 NB v0.044 Exploiting tzonemode
32 // 13-05-2013 NB v0.045 Introduction of RED FLAG (vinegar strokes issue 1 resolved) PROBLEM with illegal moves
33 // 13-05-2013 NB v0.046 released not tested
34 // 14-05-2013 NB v0.047 bugfix in enemy[][] array testing. Minor font change. Redflag disables full brokenarrow
35 // 15-05-2013 NB v0.048 Fixed illegal moves.
36 // 21-05-2013 NB v0.049 improving AI (RingOfSteel), added color to deadpile
37 // 03-06-2013 NB v0.050 Addec color cursor (removed dotted type as got messy)
38 #include <lib.h>
39 #define NORTH 0
40 #define SOUTH 1
41 #define EAST 2
42 #define WEST 3
43 #define ENEMYWEIGHT 37
44 #define DEADPILEA 222
45 #define DEADPILED 234
46 #define SIDESTEP 3
47 #define ATTACKER 1
48 #define DEFENDER 2
49 #define KING 3
50 #define CASTLE 4
51 #define ENEMYBLOCK 3
52 #define TAKEWEIGHT 5
53 #define TRIGGERHIGH 3
54 #define TRIGGERLOW 7
55 #define PARTIAL1 0
56 #define PARTIAL2 1
57 #define FULL 2
58 #define NO 0
59 #define YES 1
60 //#define VINEGAR 3
61 extern unsigned char ExplodeTiles[]; // extra graphics to "explode" a piece (animation)
62 extern unsigned char PictureTiles[]; // standard graphics for pieces and backgrounds
63 extern unsigned char RunicTiles[]; // Runic alphabet
64 extern unsigned char TimerTiles[]; // display timer in central square when computer's turn
65 /*
66 ; You simply replace the existing font from C doing this:
67 ;
68 ; extern unsigned char Font_6x8_FuturaFull[1024];
69 ;
70 ; Then to set the HIRES font:
71 ; memcpy((unsigned char*)0x9800+32*8,Font_6x8_FuturaFull,768);
72 ;
73 ; Or to set the TEXT font:
74 ; memcpy((unsigned char*)0xb400+32*8,Font_6x8_FuturaFull,768);
75 ;
76 */
77 extern unsigned char Font_6x8_runic1_partial[520]; // runic oric chars (was [1024] 02/02/2012)
78
79 /* RUNIC Alphabet Tiles (NOT the runic1 font) ordered as follows :
80 Actually, the numbers here are not true anymore due to changes in the runes.png file
81 However, Have left the descriptions for educational purposes...
82 The Viking "alphabet" begins with "F" and is rEferred to as "FUTHAR" rather than "Alphabet"
83 0 F: Fehu Cattle/Gold/General Wealth
84 1 U: Uruz Strength/Speed/Good Health
85 2 TH: Thurisaz Norse Giants
86 3 A: Ansuz The Gods, mostly Odin
87 4 R: Raido A long Journey
88 5 K/C: Kenaz Torch/Light source
89 6 G: Gebo sACRIFICE/OFFERING TO THE gODS
90 7 W: Wunjo Comfort/Joy/Glory
91 8 H: Hagalaz Hail/Missile
92 9 N: Nauthiz Need/Necessity
93 10 I: Isa ICE
94 11 Y/J: Jera year/harvest
95 12 EI: Eithwaz Sacred Yew tree
96 13 P: Perth Unknown
97 14 Z: Algiz Defence/Protection/Self-Preservation
98 15 S: Sowilo The Sun
99 16 T: Tiwaz The War God, TYR
100 17 B: Berkano Birch Tree/LDUN(goddess of spring/fertility)
101 18 E: Ehwaz Horse
102 19 M: Mannaz Man/Mankind
103 20 L: Laguz Water
104 21 NG: Ingwaz the Danes (and danish hero ING)
105 22 D: Dagaz Day/Daylight
106 23 O: Othila Inheritance (of property or knowledge)
107 */
108 /******************* Function Declarations ************************/
109 //void brokenarrow();
110 //void deccounter(); // decrement counter
111 //void LookBackInAnger(); // runs subcanbetaken if the piece "behind" an attacker is defender/king and prospective target adjacent to defender/king
112 //void subLookBackInAnger(); // runs the various "lookbackinanger" checks
113 //void zoneupdate(); // Increment target positions on unnocupied rows/columns (especially the "zone")
114 unsigned char cantakepiece(); // returns 0=no, 1 yes
115 unsigned char checkroute(); // sets counter to be number of pieces on a given route
116 void blinkcursor(); // blinks the cursor to attract attention
117 void calccantake(); // can take be made (how many)
118 void calchightarget(); // updates value of hightarget (the highest target so far)
119 //void calctakeweight(); // calculate the weight of "takeweight"
120 void canbetaken(); // can I be taken after moving here? returns value (take) 0=no 1=yes
121 void canpiecemove(); // can a selected piece move? 0=no, 1=yes
122 void cantakeadjust(); // decrement cantake if taken piece is on same plane as king
123 void checkbrokenarrow(); // check to see if brokenarrow can be incremented
124 void checkend(); // check for end game conditions
125 void checkincroute(); // check to see if OK to incroute
126 void computerturn(); // AI for computer
127 void cursormodevalid(); // sets modevalid to 1
128 void cursormodezero(); // set cursor mode to 0 if 1
129 void decpoints(); // decrement points variable
130 void decroute(); // decs route
131 void pointsplusten(); // ADDS 10 TO POINTS
132 void drawarrow(); // draws "arrow"
133 void drawboard(); // kicks off drawgrid/drawtiles
134 void drawcursor(); // draws cursor
135 void drawpiece(); // draws piece
136 void drawplayers(); // draw playing pieces
137 void drawtile(); // draw a tile (subroutine of drawtiles)
138 void drawtiles(); // draws all tiles at board x,y boxsize z (uses draw*tile functions)
139 void enemyzero(); // set enemy value to zero when surrounded=3
140 void explodetile(); // explodes a piece (plays an animation)
141 void findpiece();
142 void flashscreen(); // flashes screen in selected color for a second or so
143 void fliprune(); // flip the rune tiles in title screen
144 void gspot(); // count no of targets from king to edge
145 //void incbrokenarrow(); // increments the value of brokenarrow
146 void inccantake(); // increments cantake
147 void inccounter(); // inc counter
148 void incdefatt(); // increments count of attacker/defenders round king (calls incking...)
149 void inckingattacker(); // increments count of attackers round king
150 void inckingdefender(); // increments count of defenders round king
151 void incmodeone(); // increment the modeonevalid variable (from 0 to 1)
152 void incpoints(); // increment points variable
153 void incroute(); // incs route
154 void incsurround(); // increment "surrounded" variable
155 void inctarget(); // inc target[xns][xew]
156 void inverse(); // inverse the color in the square
157 void movecursor2(); // move cursor routine
158 void movepiece(); // move a piece
159 void pacman2(); // update target positions around king (need to develop further)
160 void pacman3();
161 void pacman4();
162 void pacman5();
163 //void pacman6(); // "vinegar strokes"
164 void pause(); // wait a certain period of time (pausetime)
165 void playerturn(); // takes user input to move cursor
166 void backbone(); // renamed from "printarrowsorblanks"
167 void printdestinations(); // print arrows on tiles where a piece can move
168 void printmessage(); // prints message to screen
169 void printpossiblemoves(); // Print possible moves
170 void printtitles(); // print the title screen (used in titles/menus etc)
171 void printturnprompt(); // prints "your turn" message
172 void prioritycalc(); // updates priority array
173 void setpoints(); // set points to default value
174 void subarrows(); // subroutine of arrows or blanks
175 void subarrows2(); // subroutine of arrows or blanks (updates ENEMY with direction of enemy)
176 void subcanbetaken2(); // attempt to reduce memory footprint
177 //void subpaceastwest(); // subroutine of pacman
178 //unsigned char subpaccrosst(); // sub of pacman2
179 void subpacmanx(); // grand sub of pacman2
180 void subpacmany(); // apply points from the pacman routines
181 //void subpacnorthsouth(); // subroutine of pacman
182 //void subzoneupdate(); // subroutine of pacman
183 void surroundcheck(); // inc surrounded under various conditions
184 void surroundcount(); // counts the number of attackers surrounding KING (or edges, or central square)
185 void surroundpoints(); // increment points around king depending on "surrounded" figure
186 void takepiece(); // takes specified piece
187 void sidestep(); // add SIDESTEP to target (used in escape routine)
188 void targetselect(); // choose a target square
189 void tileloop(); // subfunction of explodetile and drawtile
190 void timertile(); // print timer
191 //void updateroutehightarget();// adds hightarget to targets on route
192 void updateroutetarget(); // increment targets on a given route
193 void updatetarget(); // updates target array
194 void zerocounter(); // set counter=0
195 //void zerofoundpiece(); // set foundpiece to 0 (PIECE NOT FOUND)
196 void deadpile(); // draw deadpile
197 void flashred(); // flash screen in red
198 //void gethightarget(); // without upsetting any other variables
199 void calccantake2(); // alternative calcantake
200 /****************** GLOBAL VARIABLES *******************************/
201 /* Populate array with tile types
202 Tile types:
203 0=blank
204 1=attacker square
205 2=defender square
206 3=king square
207 */
208 extern unsigned char tiles[11][11]; // tile description on board
209 extern unsigned char target[11][11]; // uninitialized variable (will calc on fly) - target values of square
210 extern const unsigned char border[6][11]; // border (of title screens/menus etc)
211 //extern unsigned char presents[8]; // array of runic chars that spell "presents"
212 //extern unsigned char hnefatafl[9]; // array of runic chars that spell "hnefatafl"
213 /* populate array with places of players
214 Players:
215 0=vacant
216 1=attacker resident
217 2=defender resident
218 3=king resident
219 4=corner square // added 21/04/2011
220 */
221 //extern char baseplayers[11][11]; // BASEPLAYERS - the starting board positions. PLAYERS is the working COPY of BASEPLAYERS
222
223 // ARRAY ENEMY unititialized variable (will calc on fly) - can enemy reach a square?
224 // values:
225 // +1 Can be reached from NORTH
226 // +5 can be reached from SOUTH
227 // +10 can be reached from EAST
228 // +20 can be reached from WEST
229 extern unsigned char enemy[11][11]; // where the defenders can get to
230 extern unsigned char computer[11][11]; // where the attackers can get to
231 //extern unsigned char priority[11][11]; // holds the priority of a piece to move
232 extern unsigned char kingtracker[11][11]; // where the king can get to
233 unsigned char players[11][11]; // to be the working copy of baseplayers
234 unsigned char playertype,piecetype; // player 1=attacker, 2=defender
235 unsigned char ns,ew; // default north/south position of central square (0-10)
236 unsigned char cx,cy; // cursor x screen position (pixels across)
237 unsigned char fb=1; // foreground/background 0=background, 1=foreground, 2=opposite, 3=nothing
238 //unsigned char inversex; // x position of square to be inversed (to highlight a selected piece)
239 //unsigned char inversey; // y position of square to be inversed (to highlight a selected piece)
240 char mkey; // code of key pressed (plus loops)
241 unsigned char cursormode; // cursor movement mode 0=freeform 1=restricted
242 unsigned char ons,oew; // original north/south board pos
243 unsigned char ocx,ocy; // original xpos of piece
244 unsigned char orientation; // 0=north, 1=south 2=east 3=west
245 unsigned char tiletype; // type of tile under inspection (used in arrows)
246 unsigned char tpns,tpew; // north-south board location of taken piece (also used for 3) NB:no idea 20/10/2011
247 unsigned char flashcolor; // color of ink to flash in
248 unsigned char flashback; // color of ink to return to
249 char game; // *** MUST NOT BE UNSIGNED ***<=0 means endgame (see checkend for values), 1=GAMEON
250 unsigned char gamestyle; // 0=human vs human; 1=human king vs computer; ** NO!!! 2=human vs computer king**; 3=undefined
251 unsigned char kingns,kingew;// kings position North-South
252 unsigned char kingattacker[4]; // number of attackers in all four directions from king
253 unsigned char kingdefender[4]; // number of defenders in all four directions from king
254 unsigned char kingpieces[4]; // number of pieces in all four directions around king (saves calculating it all the time)
255 unsigned char surrounded; // status of king "surrounded" status //
256 unsigned char ctns=0; // Computer Turn north-south board position
257 unsigned char ctew=0; // Computer Turn east-west board position
258 extern char* playertext;
259 extern char* message;
260 unsigned char foundpiece; // has a piece been found (during computer move) that can move to the hightarget square? 0=no, 1=yes&ok, 9=yes!ok
261 //char xloop=0; // general purpose loop variable
262 unsigned char xns=0; // copy of ns (arrows or blanks, and subarrows)
263 unsigned char xew=0; // copy of ew (arrows or blanks, and subarrows)
264 unsigned char arrow=1; // used in arrowsorblanks(and subarrows)
265 unsigned char flag=0;
266 unsigned char cantake; // can I take? (for computer turn)
267 unsigned char route;
268 unsigned char row,col; // used in tile drawing routines and array navigation ( a row in 11x11 grid)
269 //unsigned char col; // used in tile drawing routines and array navigation ( a column in 11x11 grid)
270 unsigned char tiletodraw; // used in tile drawing routines 0-11 (as at 18-10-2011)
271 int pausetime; // amount of time to wait
272 unsigned char* ptr_draw; // ptr to board starting position (e.g. 0xa002)
273 unsigned char* ptr_graph; // pointer to byte values of loaded picture
274 unsigned char points; // points around king
275 char counter; // general purpose counter (*** DO NOT set to UNSIGNED *** NB 24/10/2011)
276 char uncounter; // *** MUST BE SIGNED *** general purpose counter (can be negative)
277 //unsigned char lookcol,lookrow; // used in lookbackinanger
278 unsigned char origorient; // original orientation of a piece under test (which way he is heading)
279 unsigned char takerow,takecol; // can I be taken if I stop here?
280 unsigned char paclevel1,paclevel2; // used in pacman/subpacmanx either ns/ew
281 unsigned char surns,surew; // count of attackers surrounding king n/s used in surroundcount()
282 unsigned char takena,takenb,takenc,takend,takene; // used in canbetaken routines
283 unsigned char ezns1,ezew1; // used in surroundcount/enemyzero to reset enemy[][] to zero if surrounded=3
284 // WEIGHTS
285 //unsigned char enemyweight=37; // >36. weight of "enemy could get here but piece occupied by attacker"
286 //char defaulttakeweight=5; // default weight assigned to a TAKE
287 //unsigned char takeweight; // weight assigned to a TAKE (calculated in "calctakeweight")
288 //unsigned char cbtweight=4; // weight to be applied to escape position if can be taken
289 // End of Weights
290 //unsigned char pacpointsx,pacpointsy,pacpointsa,pacpointsb; // used to calculate points in subpacmanx
291 unsigned char pcheckns1,pcheckns2; // used in taking pieces and checking for takes
292 unsigned char pcheckew1,pcheckew2; // used in taking pieces and checking for takes
293 unsigned char startrow,startcol; // used in checkroute (returns no of pieces on a given path)
294 unsigned char destrow,destcol; // used in checkroute (returns no of pieces on a given path)
295 unsigned char canmovecursor; // controls wether screen cursor can be moved or not
296 unsigned char hightarget; // contains highest value target
297 unsigned char targetns,targetew; // used to calc takes
298 unsigned char x,y,z,a,b,c,d,e,f; // general purpose variables
299 /* below used for cursor move routine */
300 unsigned char multiple; // concerning central square (how much to multiply the coords to SKIP the square
301 unsigned char xptrns; // copy of NS
302 unsigned char xptrew; // copy of EW
303 unsigned char skipns; // skip to north/south
304 unsigned char skipew; // skip to east/west
305 unsigned char modeonevalid; // is OK for mode 1? 0=no, 1=yes
306 /* above variables used in cursor move routine */
307 unsigned char gameinput=0; // 0=undefined 1=play against computer, 2=human vs human
308 unsigned char take;
309 unsigned char p1; // piece type comparison (lower) - used for determining takes - default=attacker
310 unsigned char p2; // piece type comparison (upper) - used for determining takes - default=attacker
311 /* playerturn variables */
312 unsigned char xkey; // code of key pressed
313 unsigned char canselect; // 0=no, 1=yes (is the piece selectable?)
314 char cursormovetype; // -1=no, 0=yes (n,s,e,w) 1=(north/south only), 2=(east/west only)
315 unsigned char turn; // determines end of player turn 1=playerturn, 0=end of playerturn
316 unsigned char compass[4]; // used in cantake (if compass[NORTH]=1 then means canbetaken if i move here from NORTH
317 /* end of playerturn variables */
318 unsigned char xplayers;
319 unsigned char inkcolor; // screen color
320 unsigned char checkroutemode; // mode used for checkroute function
321 // 1=count number of pieces on route
322 // 2=increment target values on route (if no pieces on route)
323 // 3=amount of targets on route
324 // 4=Number of "enemy" targets on route (where enemies CAN go)
325 // 5= Emergency! Make target=255
326 unsigned char checkrouterow, checkroutecol, checkroutestart, checkroutedest; // used in checkroute routine
327 unsigned char subpacc,subpacd; // used in subpacman5
328 unsigned char turncount=0; // used to count the number of turns
329 //unsigned char enemytargetcount; // count of enemy targets on a route
330 unsigned char brokenarrow[4]; // NORTH/SOUTH/EAST/WEST: 0=OK, 1=BROKENARROW, 2=POTENTIAL BROKEN ARROW in that direction
331 unsigned char deadattackers, deaddefenders, deadplayers, deadtoggle; deadchar; deadcurset; // count of dead attackers or defenders
332 unsigned char kingtoedge[4]; // number of TARGETS from king to edge of board
333 unsigned char tzonemode; // 0=PARTIAL1, 1=PARTIAL2, 2=FULL
334 //unsigned char onlycheck; // restrict check to one route in certain situations
335 unsigned char redflag; // raise the red flag to IGNORE "can I be taken"
336 //unsigned char deadcolor; // color of deadpiece
337 //unsigned int deadspace; // start of deadcolumn
338 /****************** MAIN PROGRAM ***********************************/
339 main(){
340 //gameinput=0; // 0=undefined 1=play against computer, 2=human vs human
341 CopyFont(); //memcpy((unsigned char*)0xb400+32*8,Font_6x8_runic1_full,768);
342 hires();
343 //hiresasm();
344 message="V0.050.IN MEMORY OF:\nJONATHAN 'TWILIGHTE' BRISTOW\nORIC LEGEND [1968-2013]";
345 printmessage();
346 setflags(0); // No keyclick, no cursor, no nothing
347 printtitles();
348 inkcolor=6;inkasm();
349 for(;;){ // endless loop
350 //playertype=0; // 1=attacker, 2=defender (set at zero as incremented within loop)
351 drawboard(); // draw the board
352 while (gamestyle==3){
353 message="PLAYERS:1-2"; // number of players
354 printmessage();
355 gameinput=getchar();
356 if ( gameinput == 49 ) gamestyle=1; // 1=human vs computer (as DEFENDERS)
357 if ( gameinput == 50 ) gamestyle=0; // 0=human vs human
358 if ( gamestyle == 3 ) {flashback=6;flashred();}
359 }
360 while (game > 0){
361 ns=5; // default north/south position of central square
362 ew=5; // default east/west position of central square
363 cx=ew; // cursor x screen position
364 cy=ns; // cursor y screen position
365 playertype++; // playertype inited as 0 so ++ will make it 1 at start of game
366 if ( playertype == 3 ) { playertype = 1; turncount++; } // was defender, set to attacker player, inc turncount
367 //if (( gamestyle == 0 )||((gamestyle==1)&&(playertype==2))||((gamestyle==2)&&(playertype==1)))
368 if (( gamestyle == 0 )||((gamestyle==1)&&(playertype==2))){
369 playerturn(); // player input
370 }else{
371 computerturn(); // computer has a go...
372 }
373 checkend(); // check for end of game conditions
374 }
375 /*
376 game=0 King Wins.
377 game=-1 Stalemate.
378 game=-2 Attacker wins.
379 */
380 message="ATTACKER WINS!"; // default (game=-2)
381 // king escapes or all attackers killed
382 if ( game == 0 ) message="KING WINS!";
383 // computer can't move
384 if ( game == -1 ) message="STALEMATE";
385 printmessage();
386 message="\nPRESS A KEY:";
387 printline();
388 getchar();
389 }
390 }
391
392 /********************* FUNCTION DEFINITIONS ************************/
393 void computerturn(){
394 //if ( playertype == 1 ) { strcpy(playertext,"ATTACKER");}else{ strcpy(playertext,"KING");}
395 message="THINKING...";
396 printmessage();
397 // 1. initialize target, enemy and computer array to zeroes
398 ClearArrays(); // clear target, enemy, priority and computer arrays
399 //prioritycalc(); // calculates the priorities of pieces to move
400 // 2. Loop through players array searching for pieces - calculating where they can go
401 for (fb=4;fb<9;fb++){
402 timertile();
403 for (ctns=0;ctns<11;ctns++){
404 for (ctew=0;ctew<11;ctew++){
405 ns=ctns;ew=ctew;
406 // fb=4 means: don't print destinations, just update ENEMY
407 if (( fb == 4 )&&(( players[ctns][ctew] == DEFENDER )||(players[ctns][ctew] == KING))) printdestinations();
408 // fb=5 (+COMPUTER array):fb=7 (can I be taken)
409 if (((fb == 5)||(fb == 7))&&( players[ctns][ctew] == ATTACKER)) printdestinations();
410 // fb=6 if computer piece can get here update target values
411 if (( fb == 6)&&( computer[ctns][ctew] )) updatetarget();
412 // fb=8 update kingtracker
413 if (( fb == 8)&&( players[ctns][ctew] == KING )) printdestinations();
414 }
415 }
416 }
417 // 3. Increment target positions around King (PACMAN)
418 pacman2();
419 calchightarget();
420 if (hightarget == 0) {
421 game=-1; // signify END of game: computer cannot move: stalemate
422 return;
423 }
424
425 if (redflag == NO ) pacman4(); // check for full broken arrow
426 //pacman6(); // "vinegar strokes"
427 // draw central square (overwriting timer)
428 tiletodraw=9; // KING ON A TILE
429 if (players[5][5] != KING) tiletodraw=3; // CASTLE TILE
430 row=5;col=5; ptr_graph=PictureTiles;drawtile();
431 //if ( playertype == 1 ) {pacman();}
432 // other routines to go here to update the target array
433 // 4,5,6,7..N etc
434 //
435 targetselect(); // Choose the highest value target and piece to move to it
436 ns=targetns;ew=targetew; // make computer move compatible with human move selection
437 movepiece(); // make the move
438 }
439
440
441 void findpiece(){ // find a piece capable of moving to selected target
442 if ( foundpiece == 0 ){
443 if (players[a][b] == ATTACKER){ // a=row, b=column (ns,ew = target location)
444 //foundpiece=1;
445 calccantake2();
446 //cantake=0;
447 //calccantake();
448 //if (( origorient == NORTH ) && ( ns > 1 )) {calccantake();}
449 //if (( origorient == SOUTH ) && ( ns < 9 )) {calccantake();}
450 //if (( origorient == EAST ) && ( ew < 9 )) {calccantake();}
451 //if (( origorient == WEST ) && ( ew > 1 )) {calccantake();}
452 if (( cantake == 0 )&&( surrounded < 3)) canbetaken(); // if cannot take can I be taken?
453 if (compass[origorient] == 0) foundpiece=1;
454 // check NORTH and SOUTH
455 if ((foundpiece == 1)&&(redflag == NO)){ // can't be taken so we've found a candidate
456 if (a != targetns) {// target is not on same row as candidate
457 if ((targetns == kingns)&&((a < 2)||(a > 8))){
458 startrow=a;destrow=a;startcol=0;destcol=10;
459 //see if by moving a piece we leave the way open for the king to escape
460 setcheckmode1(); // set checkroutemode=1 (checkroute will return count of pieces on row or column)
461 checkroute(); // returns z
462 if (z == 1) setfoundpiece10(); // don't move piece (do NOT leave the "zone" unpopulated)
463 }
464 if (a == kingns){ // if candidate is on same row as king (don't move away if only one piece E/W)
465 if ((b > kingew)&&(kingpieces[EAST]==1)) setfoundpiece10();
466 if ((b < kingew)&&(kingpieces[WEST]==1)) setfoundpiece10();
467 }
468 }
469 }
470 // CHECK EAST AND WEST
471 if ((foundpiece == 1)&&(redflag == NO)){ // can't be taken so we've found a candidate
472 if ( b != targetew){// target is not on same column as candidate
473 if ((targetew == kingew)&&((b < 2)||(b > 8))){
474 startrow=0;destrow=10;startcol=b;destcol=b;
475 checkroute(); // returns z
476 if (z == 1) setfoundpiece10(); // don't move piece (do NOT leave the "zone" unpopulated)
477 }
478 if (b == kingew){ // if candidate is on same col as king (don't move away if only one piece N/S)
479 if ((a < kingns)&&(kingpieces[NORTH]==1)) setfoundpiece10();
480 if ((a > kingns)&&(kingpieces[SOUTH]==1)) setfoundpiece10();
481 }
482 }
483 }
484 if (foundpiece == 1){
485 if (origorient < EAST){
486 ons = a;
487 }else{
488 oew = b;
489 }
490 }
491 }
492 if ((players[a][b] == DEFENDER)||(players[a][b] == KING)) foundpiece=9;
493 //if ((players[a][b] == CASTLE)&&(a!=5)) foundpiece=9;
494 }
495 }
496 /*
497 CalcHighTarget used to be part of targetselect (and is still called from it) but
498 it is also now used in PACMAN so that the kings escape route can always be blocked
499 by adding the highest score (so far) onto the necessary targets...
500 It alters the values of ctns,ctew,targetns,targetew,ons,oew,ns,ew and of course,
501 hightarget
502 */
503 void calchightarget(){
504 hightarget=0; // highest value target
505 for (ctns=0;ctns<11;ctns++){ // find the highest value for target
506 for (ctew=0;ctew<11;ctew++){
507 if ( target[ctns][ctew] > hightarget ){
508 hightarget=target[ctns][ctew]; // make hightarget the highest value
509 targetns=ctns;
510 targetew=ctew;
511 ons=ctns; // target is accessible so make ons/oew the default piece position to move
512 oew=ctew; // the ACTUAL piece to move determined below (one of ons or oew will remain same)
513 ns=ctns;
514 ew=ctew;
515 }
516 }
517 }
518 }
519 /*
520 void gethightarget(){ // without upsetting anything else
521 hightarget=0;
522 for (ctns=0;ctns<11;ctns++){ // find the highest value for target
523 for (ctew=0;ctew<11;ctew++){
524 if ( target[ctns][ctew] > hightarget ){
525 hightarget=target[ctns][ctew]; // make hightarget the highest value
526 }
527 }
528 }
529 }
530 */
531 /*
532 void cleartarget(){ // nukes target array
533 for (ctns=0;ctns<11;ctns++){
534 for (ctew=0;ctew<11;ctew++){
535 if (target[ctns][ctew]) target[ctns][ctew]=1;
536 }
537 }
538 }
539 */
540 // TARGETSELECT - find the highest scoring TARGET
541 void targetselect(){
542 NEWTARGET:
543 calchightarget();
544 // having found target we need to select a piece to move
545 compass[NORTH]=0;compass[SOUTH]=0;compass[EAST]=0;compass[WEST]=0; // initialize compass array
546 fb=9;
547 // NORTH + SOUTH
548 b=oew;
549 // NORTH
550 zerofoundpiece(); // set foundpiece to ZERO "piece not found"
551 origorient=NORTH;
552 for (mkey=ons-1; mkey>-1; mkey--){a=mkey;findpiece();}
553 // SOUTH
554 if ( foundpiece != 1 ){
555 zerofoundpiece();
556 origorient=SOUTH;
557 for (mkey=ons+1; mkey<11; mkey++) {a=mkey;findpiece();}
558 }
559 // EAST + WEST
560
561 // EAST
562 if ( foundpiece != 1 ){
563 a=ons;
564 zerofoundpiece();
565 origorient=EAST;
566 for (mkey=oew+1; mkey<11; mkey++) {b=mkey;findpiece();}
567 }
568 // WEST
569 if ( foundpiece != 1 ) {
570 zerofoundpiece();
571 origorient=WEST;
572 for (mkey=oew-1; mkey>-1; mkey--) {b=mkey;findpiece();}
573 }
574 if ( foundpiece != 1 ) {target[targetns][targetew]=1;goto NEWTARGET;} // if can still be taken select new target
575 //if ( target[targetns][targetew]==2) {zoneupdate(); goto NEWTARGET;} // if nothing useful found update the zone
576 cx=oew; // piece x screen position
577 cy=ons; // piece y screen position
578 blinkcursor(); // draw cursor in foreground color at piece to move position cx,cy
579 fb=0;
580 //drawcursor(); // blank cursor
581 cx=targetew; // target x screen position
582 cy=targetns; // target y screen position
583 blinkcursor(); // draw cursor in foreground color at target position cx,cy
584 ocx=oew; // piece to move x screen position
585 ocy=ons; // piece to move y screen position
586 }
587 // subroutine of pacman
588 void subpacmanx(){
589 setpoints(); // Set points to 10
590 surroundpoints(); // add 10 * surrounded
591 /*
592 if (kingpieces[orientation] == 0){
593 incpoints();
594 if ((orientation<EAST)&&((kingew<2)||(kingew>8))) pointsplusten();
595 if ((orientation>SOUTH)&&((kingns<2)||(kingns>8))) pointsplusten();
596 }
597 */
598 // TRIGGERHIGH/TRIGGERLOW = Weight to be added depending on kings closeness to border
599 /*
600 if (( orientation == NORTH )&&(kingns <= TRIGGERLOW)) pointsplusten();
601 if (( orientation == SOUTH )&&(kingns >= TRIGGERHIGH)) pointsplusten();
602 if (( orientation == EAST ) &&(kingew >= TRIGGERHIGH)) pointsplusten();
603 if (( orientation == WEST ) &&(kingew <= TRIGGERLOW)) pointsplusten();
604 */
605 points+=brokenarrow[orientation]*10;
606 //message="NOT SET";
607
608 if (( kingpieces[orientation] == 0 )&&(kingtoedge[orientation])){
609 //calchightarget();
610 if ((orientation < EAST)&&((kingew<2)||(kingew>8))) {
611 redflag=YES; // raise a red flag
612 points=200;
613 }
614 if ((orientation > SOUTH)&&((kingns<2)||(kingns>8))) {
615 redflag=YES; // raise a red flag
616 points=200;
617 }
618 }
619
620 subpacmany(); // apply the points
621 }
622 void subpacmany(){ // apply the points generated in pacman2-6
623 // SET UNCOUNTER
624 pacman5(); // ensure correct paclevels are set
625 uncounter=paclevel2+1; // if south or east
626 if ((orientation == NORTH ) || ( orientation == WEST)){
627 uncounter=paclevel2-1;
628 }
629 // SET X & Y
630 x=paclevel1; // if EAST or WEST
631 y=uncounter;
632 if ( orientation < EAST ){ // IF NORTH OR SOUTH
633 x=uncounter;
634 y=paclevel1;
635 }
636
637 while (((players[x][y] == 0)||(tiles[x][y] == CASTLE)) && ((uncounter > -1)&&(uncounter < 11))){
638 if ( target[x][y] ){ // if accessible by attacker
639 if (( target[x][y] > 1 )||(redflag)){
640 //printmessage();getchar();
641 target[x][y]+=points;
642 }else{
643 target[x][y]=points; // can be caught if i go here
644 if (redflag) target[x][y]-=50; // take another 50 points if redflag=yes
645 }
646 decpoints();
647 }
648 //if (z){decpoints();} // only decrement points if route to edge is blocked
649 if ( (orientation == NORTH) || (orientation == WEST) ) {uncounter--;}else{uncounter++;}
650 if ( orientation < EAST ) {x=uncounter;}else{y=uncounter;}
651 }
652 /*
653 if (tzonemode==VINEGAR){
654 message="VINEGAR STROKES COMPLETE";
655 printmessage();
656 }*/
657 }
658 void checkbrokenarrow(){
659 // f= value of player piece at edge of board (if any)
660 // kingtoedge[orientation]= count of targets from king to edge
661 // kingpieces[]= count of pieces from king in a given orientation
662 unsigned char test=0;
663 //unsigned char testreturn=0;
664 setcheckmode1(); c=checkroute(); // how many pieces on the route?
665 checkroutemode=6; d=checkroute();// can king get to a T-row 0-1
666 if (( c == 0 ) && ( d )) {
667 f=players[a][b]; // check for piece at edge of board
668 if (f == CASTLE) f=0; // check for corner square
669 if (( target[a][b] )&&(tzonemode==FULL)) kingtoedge[orientation]--; // decrement kingtoedge(so maybe kingtoedge=zero) - to trigger brokenarrow
670 //if (( kingpieces[orientation] == 1) && (f) && (f != ATTACKER)) test=1;
671 if (( kingpieces[orientation] == 1) && (f)) test=1;
672 if ((kingpieces[orientation] == 0 )||( test )){
673 if ( kingtoedge[orientation] == 0){ // no targets on route
674 //brokenarrow[orientation]=5;
675 message="BROKEN ARROW UPDATE";
676 printline();
677 message="\nPRESS A KEY";
678 printline();
679 getchar();
680 checkroutemode=5;checkroute();
681 }else{
682 brokenarrow[orientation]++; // POTENTIAL BROKEN ARROW
683 if (tzonemode){ // if tzonemode > PARTIAL1
684 brokenarrow[orientation]+=2; // will be at LEAST 3 if PARTIAL2
685 }
686 // if we have two PARTIAL1s (possible escape) then brokenarrow will be 2 so need to elevate
687 if (brokenarrow[orientation] == 2) brokenarrow[orientation]=4; // 4 beats one PARTIAL2
688 }
689 }
690 }
691 }
692
693 /*
694 // check the T zone (for broken arrow purposes)
695 unsigned char subpaccrosst(){
696 if ( orientation == NORTH ){
697 a=0;b=kingew;startrow=1;destrow=1;startcol=0;destcol=10;
698 }
699 if ( orientation == SOUTH ){
700 a=10;b=kingew;startrow=9;destrow=9;startcol=0;destcol=10;
701 }
702 if ( orientation == EAST ){
703 a=kingns;b=10;startrow=0;destrow=10;startcol=9;destcol=9;
704 }
705 if ( orientation == WEST ){
706 a=kingns;b=0;startrow=0;destrow=10;startcol=1;destcol=1;
707 }
708 return checkroute();
709 }
710 */
711 void gspot(){
712 setcheckmode3(); // count number of targets on route from king to edge
713 // NORTH
714 startrow=0;destrow=kingns;startcol=kingew;destcol=kingew;
715 kingtoedge[NORTH]=checkroute(); // count of targets from king to edge
716 // SOUTH
717 startrow=kingns;destrow=10;
718 kingtoedge[SOUTH]=checkroute(); // count of targets from king to edge
719 // EAST
720 destrow=kingns;destcol=10;
721 kingtoedge[EAST]=checkroute();
722 // WEST
723 startcol=0;destcol=kingew;
724 kingtoedge[WEST]=checkroute();
725 }
726 /*
727 void gspot(){
728 // default=NORTH
729 if (( orientation == NORTH )&&(kingns > 1)) {
730 startrow=0;destrow=kingns;startcol=kingew;destcol=kingew;
731 }
732 if (( orientation == SOUTH )&&(kingns < 9)){
733 startrow=kingns;destrow=10;startcol=kingew;destcol=kingew;
734 }
735 if ((orientation == EAST )&&(kingew < 9)){
736 startrow=kingns;destrow=kingns;startcol=kingew;destcol=10;
737 }
738 if ((orientation == WEST) && (kingew > 1)){
739 startrow=kingns;destrow=kingns;startcol=0;destcol=kingew;
740 }
741 setcheckmode3(); g=checkroute(); // count of targets from king to edge
742 }
743 */
744 /*
745 void checkbrokenarrowhead(){
746 // NORTH
747 orientation=NORTH; brokenarrow[orientation]=0;
748 a=0;b=kingew;startrow=0;destrow=0;startcol=0;destcol=kingew;
749 checkbrokenarrow(); // PARTIAL LEVEL 1 "LEFT"
750 startcol=kingew;destcol=10;
751 checkbrokenarrow(); // PARTIAL LEVEL 1 "RIGHT"
752 // SOUTH
753 orientation=SOUTH; brokenarrow[orientation]=0;
754 a=10;startrow=10;destrow=10;startcol=0;destcol=kingew;
755 checkbrokenarrow(); // PARTIAL LEVEL 1 "LEFT"
756 startcol=kingew;destcol=10;
757 checkbrokenarrow(); // PARTIAL LEVEL 1 "RIGHT"
758 // EAST
759 orientation=EAST; brokenarrow[orientation]=0;
760 a=kingns;b=10;startrow=0; destrow=kingns;startcol=10;
761 checkbrokenarrow(); // PARTIAL LEVEL 1 "LEFT"
762 startrow=kingns;destrow=10;
763 checkbrokenarrow(); // PARTIAL LEVEL 1 "RIGHT"
764 // WEST
765 orientation=WEST; brokenarrow[orientation]=0;
766 b=0; startrow=0;destrow=kingns;startcol=0; destcol=0;
767 checkbrokenarrow(); // PARTIAL LEVEL 1 "LEFT"
768 startrow=kingns;destrow=10;
769 checkbrokenarrow(); // PARTIAL LEVEL 1 "RIGHT"
770 }*/
771
772 void pacman2(){
773 // improved version of pacman
774 redflag=NO; // at this point no red flag to be waived
775 timertile();
776 //calchightarget(); // calc highest target so far
777 //if (hightarget == 0) return; // cannot move...
778 gspot(); // sets kingtoedge[orientation]=count of targets from king to edge (no of pieces is found in kingpieces[])
779 //checkbrokenarrowhead();
780 surroundcount(); // set surrounded value (used in subpacmanx - only have to calc once though)
781 for (orientation = 0; orientation < 4; orientation++){
782 brokenarrow[orientation]=0;
783 tzonemode=PARTIAL1;
784 // count of pieces across the "T"
785 // PARTIAL LEVEL 1 "LEFT"
786 //points=50; // for level 1
787 a=0;b=kingew;startrow=0;destrow=0;startcol=0;destcol=kingew; // NORTH
788 if ( orientation ){
789 a=10;b=kingew;startrow=10;destrow=10;startcol=0;destcol=kingew; // SOUTH
790 if ( orientation == EAST ){
791 a=kingns;b=10;startrow=0; destrow=kingns;startcol=10;destcol=10;
792 }
793 if ( orientation == WEST ){
794 a=kingns;b=0; startrow=0; destrow=kingns;startcol=0; destcol=0;
795 }
796 }
797 pacman3();
798 // PARTIAL LEVEL 1 "RIGHT"
799 if (startrow == destrow){
800 startcol=kingew;destcol=10;
801 }else{
802 startrow=kingns;destrow=10;
803 }
804 pacman3();
805 // LEVEL 2
806 // PARTIAL LEVEL 2 "LEFT"
807 // a + b already set in PARTIAL LEVEL 1
808 tzonemode=PARTIAL2;
809 startrow=1;destrow=1;startcol=0;destcol=kingew; // NORTH
810 if ( orientation ){
811 startrow=9;destrow=9;startcol=0;destcol=kingew; // SOUTH
812 if ( orientation == EAST ){
813 startrow=0; destrow=kingns;startcol=9;destcol=9;
814 }
815 if ( orientation == WEST ){
816 startrow=0; destrow=kingns;startcol=1; destcol=1;
817 }
818 }
819 //points = 100;
820 pacman3();
821 // PARTIAL LEVEL 2 "RIGHT"
822 if (startrow == destrow){
823 startcol=kingew;destcol=10;
824 }else{
825 startrow=kingns;destrow=10;
826 }
827 pacman3();
828 subpacmanx(); // add points to target in all directions from king
829 }
830 }
831 void pacman3(){
832 //unsigned char test=0;
833 unsigned char lower=0; // row/column lower bound
834 unsigned char upper=10; // row/column upper bound
835 pacman5(); // ensure correct paclevels are set
836 if (tzonemode){ // if PARTIAL2 or FULL
837 lower=1;
838 upper=9;
839 }
840 if ((( orientation == NORTH )||( orientation == WEST ))&&(paclevel2 > lower)) checkbrokenarrow();
841 if ((( orientation == SOUTH )||( orientation == EAST ))&&(paclevel2 < upper)) checkbrokenarrow();
842 //if ((paclevel1 > 0 )&&(paclevel1 < 10)) test++;
843 //if ( test==2 ) checkbrokenarrow();
844 }
845 void pacman4(){
846 // Cross the "T", see if a FULL broken arrow condition could exist (LEVEL 2)
847 // FULL LEVEL 2
848 tzonemode=FULL;
849 points=hightarget+1;
850 orientation = NORTH;
851 //pacman5(); // NORTH+SOUTH
852 a=0;b=kingew;startrow=1;destrow=1;startcol=0;destcol=10;
853 pacman3();
854 orientation = SOUTH; // SOUTH
855 a=10;b=kingew;startrow=9;destrow=9;startcol=0;destcol=10;
856 pacman3();
857 orientation = EAST; // EAST
858 //pacman5();
859 a=kingns;b=10;startrow=0;destrow=10;startcol=9;destcol=9;
860 pacman3();
861 orientation = WEST; // WEST
862 a=kingns;b=0;startrow=0;destrow=10;startcol=1;destcol=1;
863 pacman3();
864 }
865 void pacman5(){
866 if (orientation < EAST){ // NORTH AND SOUTH (for pacman3)
867 paclevel1=kingew;
868 paclevel2=kingns;
869 }else{ // EAST AND WEST
870 paclevel1=kingns;
871 paclevel2=kingew;
872 }
873 }
874
875 // check for endgame conditions
876 void checkend() {
877 /* END OF GAME CONDITIONS
878 game=0 King Wins.
879 game=-1 Stalemate.
880 game=-2 Attacker wins.
881 */
882 // ns and ew contains new board co-ords of last piece moved
883 if ((( players[ns][ew] == 3 ) && ( tiles[ns][ew] == 4 ))||( deadattackers > 23)) game=0; // king has escaped
884 // check to see if king is surrounded by attackers (first find king)
885 if ( players[ns][ew] == 1 ){ // if attacker was last to move
886 if ((ns )&&(players[ns-1][ew] == 3 )) surroundcount();
887 if ((ns < 10 )&&(players[ns+1][ew] == 3 )) surroundcount();
888 if ((ew < 10 )&&(players[ns][ew+1] == 3 )) surroundcount();
889 if ((ew )&&(players[ns][ew-1] == 3 )) surroundcount();
890 if ( surrounded == 4 ) game=-2; // king is surrounded on all sides by attackers or king squares
891 }
892 }
893
894 void cursormodezero() {
895 if ( cursormode == 0 ) canmovecursor=1;
896 }
897
898
899 // routine to move the cursor
900 void movecursor2() {
901 /*
902 cursormode = [0 or 1] 0=unrestricted (move anywhere), 1= restricted (only move to possible destinations)
903 */
904 multiple=1; // concerning central square (how much to multiply the coords to SKIP the square
905 xptrns=ns; // copy of NS
906 xptrew=ew; // copy of EW
907 skipns=ns; // skip to north/south
908 skipew=ew; // skip to east/west
909 modeonevalid=0; // is OK for mode 1? 0=no, 1=yes
910 canmovecursor=0;
911 piecetype=players[ons][oew]; // determines the piece type that is currently selected (used in mode 1)
912 if ((mkey == 8 )&&( ew )){ // west
913 cursormodezero();
914 xptrew--; // decrement copyew
915 skipew-=2;
916 incmodeone();
917 }
918 if ((mkey == 9 )&&( ew < 10)) { // east
919 cursormodezero();
920 xptrew++;
921 skipew+=2;
922 incmodeone();
923 }
924 if ((mkey == 10)&&( ns < 10)){ // south
925 cursormodezero();
926 xptrns++;
927 skipns+=2;
928 incmodeone();
929 }
930 if ((mkey == 11)&&( ns )){ // north
931 cursormodezero();
932 xptrns--;
933 skipns-=2;
934 incmodeone();
935 }
936 if (( cursormode ) && ( modeonevalid )){ // if not at edge of board
937 if ( players[xptrns][xptrew] == 0 ) canmovecursor=1; // ok if square vacant
938 if ( tiles[xptrns][xptrew] == 4 ) canmovecursor=0; // !ok if corner
939 if (( piecetype == 3 )&&( tiles[xptrns][xptrew] > 2 )) canmovecursor=1; // ok if KING and corner/central
940 if (( xptrns == ons )&&( xptrew == oew )) canmovecursor=1; // ok if back to self
941 // need to check that for non-king pieces wether the central square is vacant and can be skipped
942 if (( piecetype < 3 )&&( tiles[xptrns][xptrew] == 3)&&(players[xptrns][xptrew] !=3 )){ // tiles=3(central), tiles=4(corner)
943 if ( players[skipns][skipew] ) canmovecursor=0; // cannot skip if otherside occupied
944 if ((( skipns == ons )&&( skipew == oew ))||( players[skipns][skipew] == 0)){ // ok to skip to self
945 canmovecursor=1;
946 multiple=2;
947 }
948 }
949 }
950 if (canmovecursor ){
951 fb=0;
952 //inversex=cx;
953 //inversey=cy;
954 //drawcursor();
955 inverse(); // print blank cursor (effect=remove dots)
956 if ( mkey == 8 ) cx-=multiple; // left
957 if ( mkey == 9 ) cx+=multiple; // right
958 if ( mkey == 10 )cy+=multiple; // down
959 if ( mkey == 11 )cy-=multiple; // up
960
961 fb=1;
962 //inversex=cx;
963 //inversey=cy;
964 //drawcursor(); // print dotted cursor
965 inverse();
966 if ( mkey == 8 ) ew-=multiple; // left
967 if ( mkey == 9 ) ew+=multiple; // right
968 if ( mkey == 10 )ns+=multiple; // down
969 if ( mkey == 11 )ns-=multiple; // up
970 }
971 else{
972 if ( cursormode == 0 ) {flashback=6;flashred();} // flash red: return to cyan:6
973 if ( cursormode == 1 ) {flashback=2;flashred();} // flash red: return to green:2)
974 }
975 }
976
977
978 // kicks off functions that print appropriate arrows at all possible
979 // destinations and blanks them out afterwards
980 void printpossiblemoves(){
981 char k; // key entered
982 fb=1;
983 printdestinations(); // print arrows on all destinations
984 message="* PRESS ANY KEY TO PROCEED *";
985 printmessage();
986 k=getchar();
987 fb=0;
988 printdestinations(); // blank out arrows on all destinations
989 }
990
991 // used in printdestinations
992 void backbone() {
993 origorient=orientation; // original orientation (for computer turn)
994 xns=ns; // copy of ns
995 xew=ew; // copy of ew
996 arrow=1;
997 // orientation 0,1,2,3 = N, S, E, W
998 takerow=ns;takecol=ew; // will set below to be the opposite of the orientation
999 if ( orientation == NORTH ) { xplayers=players[xns-1][xew];takerow=xns+1;} // check north
1000 if ( orientation == SOUTH ) { xplayers=players[xns+1][xew];takerow=xns-1;} // check south
1001 if ( orientation == EAST ) { xplayers=players[xns][xew+1];takecol=xew-1;} // check east
1002 if ( orientation == WEST ) { xplayers=players[xns][xew-1];takecol=xew+1;} // check west
1003 while (( arrow )&&(fb != 7)){ // keep checking until cannot move
1004 if (( orientation == NORTH ) && ( xns )){ // check north
1005 xns--; // decrement provisional north-south player position
1006 subarrows();
1007 }
1008 if (( orientation == SOUTH ) && ( xns < 10 )){ // check south
1009 xns++; // increment provisional north-south player position
1010 subarrows();
1011 }
1012 if ((orientation == EAST ) && ( xew < 10 )){ // check east
1013 xew++; // increment provisional east-west player position
1014 subarrows();
1015 }
1016 if ((orientation == WEST ) && ( xew )){ // check west
1017 xew--; // decrement provisional east-west player position
1018 subarrows();
1019 }
1020 tiletodraw=tiles[xns][xew]; // obtain type of tile
1021 if ( arrow ){ // if MODE is "draw an arrow" (aka: I can move here) arrow=1 or 2
1022 // NOTE: arrow=2 means piece can cross this square but not occupy it as in case with CASTLE squares
1023 row=xns;
1024 col=xew;
1025 if ( arrow == 1 ){ // don't draw the arrow or update any array if arrow=2
1026 if (fb == 1) drawarrow(); // draw arrow
1027 if (fb == 4) subarrows2(); // enemy can get here, update enemy array (direction specific)
1028 if (fb == 5) computer[xns][xew]++;// computer can get here, increment computer array and set default target value
1029 if (fb == 0) drawarrow(); // if MODE is "blank an arrow"
1030 if (fb == 8) kingtracker[xns][xew]=1; // king can get here...
1031 }
1032 }
1033 // have we reached the end of the board?
1034 if (( orientation == NORTH ) && ( xns == 0 )) zeroarrow(); // check north
1035 if (( orientation == SOUTH ) && ( xns == 10 )) zeroarrow(); // check south
1036 if (( orientation == EAST ) && ( xew == 10 )) zeroarrow(); // check east
1037 if (( orientation == WEST ) && ( xew == 0 )) zeroarrow(); // check west
1038 }
1039 if ((fb == 7)&&(xplayers > ATTACKER)){ // check to see if an attacker can be caught if he stays where he is
1040 if ((players[takerow][takecol] == 0)&&(enemy[takerow][takecol] )) {
1041 a=takerow;b=takecol;sidestep();
1042 if (orientation < EAST){ // if heading north or south
1043 a=xns;
1044 if ( xew < 10 ) {b=xew+1;sidestep();}
1045 if ( xew ) {b=xew-1;sidestep();}
1046 }
1047 else{ // if heading east or west
1048 b=xew;
1049 if ( xns < 10 ) {a=xns+1;sidestep();}
1050 if ( xns ) {a=xns-1;sidestep();}
1051 }
1052 }
1053 }
1054 }
1055 // sidestep: take a step sideways if you can be caught where you are...
1056 void sidestep(){
1057 if (target[a][b] > 1) target[a][b]+=SIDESTEP;
1058 }
1059
1060 // Multi function depending on value of "fb"
1061 void printdestinations(){
1062 // check north
1063 if ( ns ) { orientation=NORTH;backbone();}
1064 // check south
1065 if ( ns < 10 ){ orientation=SOUTH;backbone();}
1066 // check east
1067 if ( ew < 10 ){ orientation=EAST;backbone();}
1068 // check west
1069 if ( ew ) { orientation=WEST;backbone();}
1070 }
1071
1072
1073 // CAN A SELECTED PIECE MOVE?
1074 void canpiecemove() {
1075 // returns 0 or 1 depending on wether a piece can move or not
1076 route=0;
1077 piecetype=players[ns][ew]; // determine TYPE of selected piece (1=attacker, 2=defendr, 3=king)
1078 /* for all piece types determine if adjacent square in any direction is blank or not
1079 it won't bother checking a particular direction if piece is at edge of board.
1080 */
1081 if ( ns ){ // check north
1082 a=ns-1;b=ew;checkincroute();
1083 }
1084 if ( ns < 10 ){ // check south
1085 a=ns+1;b=ew;checkincroute();
1086 }
1087 if ( ew < 10 ){ // check east
1088 a=ns;b=ew+1;checkincroute();
1089 }
1090 if ( ew ){ // check west
1091 a=ns;b=ew-1;checkincroute();
1092 }
1093 /* In the case that the central square is unnocupied and a piece is adjacent to that square then - for
1094 non-KING Pieces only - we need to check to see if the opposite square is occupied or not.
1095 ROUTE will be decremented if that piece is occupied (as no piece can occupy the central square except for
1096 the King but all pieces can traverse it */
1097 if (( piecetype < 3 ) && ( players[5][5] == 4 )){ // if not a king and central sqr unoccupied
1098 if ( ns == 5 ) {
1099 if ( ew == 4 ) {if ( players[5][6] ) decroute();} // check east +2 // east occupied, dec route
1100 if ( ew == 6 ) {if ( players[5][4] ) decroute();} // check west +2 // west occupied, dec route
1101 }
1102 if ( ew == 5 ){
1103 if ( ns == 4 ) { if ( players[6][5] ) decroute();} // check south +2 // south occupied, dec route
1104 if ( ns == 6 ) { if ( players[4][5] ) decroute();} // check north +2 // north occupied, dec route
1105 }
1106 }
1107 if ( route ) route=1;
1108 //return route;
1109 }
1110
1111
1112 void checkincroute(){
1113 if ( players[a][b] == 0 ) incroute();
1114 if ( (a == 5) && (b == 5) && (players[a][b] == 4)) incroute();
1115 if (( piecetype == 3 )&&(tiles[a][b] == 4 )) incroute(); // KING: corner square OK
1116 }
1117
1118
1119 // DRAW ALL THE PIECES ON THE BOARD
1120 void drawplayers() {
1121 for (row=0;row<11;row++){
1122 for (col=0;col<11;col++){
1123 if (( players[row][col] )&&(players[row][col] < 4)) drawpiece();
1124 }
1125 }
1126 }
1127 // update the deadpile
1128 void deadpile(){
1129 //curset(212,0,0);
1130 //hchar('X',0,1);
1131 //curset(212+6,0,0);
1132 //hchar('*',0,1);
1133 //curset(212+12,0,0);
1134 //hchar('0',0,1);
1135 //curset(212+18,0,0);
1136 //hchar('X',0,1);
1137 if (playertype == 1){
1138 deaddefenders++;
1139 deadplayers=deaddefenders;
1140 deadcurset=DEADPILED;
1141 deadchar='(';
1142 }
1143 if (playertype == 2){
1144 deadattackers++;
1145 deadplayers=deadattackers;
1146 deadcurset=DEADPILEA;
1147 deadchar=')';
1148 }
1149
1150 if ( deadplayers ){
1151 for (x=0;x<deadplayers;x++){
1152 curset(deadcurset,x*8,0);
1153 hchar(deadchar,0,deadtoggle);
1154 }
1155 }
1156
1157 }
1158 // DRAW THE BOARD
1159 void drawboard(){
1160 deadtoggle=0; // ensure deadpile chars drawn in background
1161 playertype=1;deadpile(); // clear the deadpile of defenders
1162 playertype=2;deadpile(); // clear the deadpile of attackers
1163 deadattackers=0;deaddefenders=0; // reset deadpile counts
1164 game=1; // game=1 means PLAY GAME
1165 gamestyle=3; // 0=play against human, 1=play as DEFENDERS, 2=play as ATTACKERS, 3=nobody
1166 kingns=5;kingew=5; // DEFAULT kings board position
1167 kingattacker[NORTH]=2; // count of attackers NORTH of king
1168 kingattacker[SOUTH]=2; // count of attackers SOUTH of king
1169 kingattacker[EAST]=2; // count of attackers EAST of king
1170 kingattacker[WEST]=2; // count of attackers WEST of king
1171 kingdefender[NORTH]=2; // count of defenders NORTH of king
1172 kingdefender[SOUTH]=2; // count of defenders SOUTH of king
1173 kingdefender[EAST]=2; // count of defenders EAST of king
1174 kingdefender[WEST]=2; // count of defenders WEST of king
1175 surrounded=0; // reset surrounded back to zero
1176 drawtiles(); // draw the background tiles
1177 curset(12,198,1);
1178 draw(198,0,1);
1179 draw(0,-198,1);
1180 drawplayers(); // draw the players
1181 deadatt(); // set dead colors attackers
1182 deaddef(); // set dead colors defenders
1183
1184 }
1185
1186
1187 // blinks the cursor a number of times to attract attention
1188 void blinkcursor() {
1189 //inversex=cx;
1190 //inversey=cy;
1191 for (counter=0;counter<5;inccounter()){ // flash the cursor to draw attention to it
1192 fb=0;
1193 //drawcursor(); // draw cursor in background color at cx,cy
1194 inverse();
1195 pausetime=500;pause();
1196 inverse();
1197 fb=1;
1198 //drawcursor(); // draw cursor in foreground color at cx,cy
1199 pausetime=1000;pause();
1200 }
1201 if ((cx==5)&&(cy==5)) inverse();
1202 }
1203 // flashes the screen in the selected ink color
1204 void flashscreen() {
1205 inkcolor=flashcolor;inkasm();
1206 pausetime=1500;pause();
1207 inkcolor=flashback;inkasm();
1208 }
1209 // The human players turn : filter keyboard input
1210 void playerturn(){
1211 /*
1212 unsigned char key; // code of key pressed
1213 unsigned char canselect; // 0=no, 1=yes (is the piece selectable?)
1214 char cursormovetype=-1; // -1=no, 0=yes (n,s,e,w) 1=(north/south only), 2=(east/west only)
1215 char turn=1; // determines end of player turn 1=playerturn, 0=end of playerturn
1216 */
1217 cursormovetype=-1; // -1=no, 0=yes (n,s,e,w) 1=(north/south only), 2=(east/west only)
1218 turn=1; // determines end of player turn 1=playerturn, 0=end of playerturn
1219 ons=ns; // original ns board position
1220 oew=ew; // original ew board position
1221 ocx=cx; // original x screen position
1222 ocy=cy; // original y screen position
1223 flashback=6;
1224 playertext="ATTACKER";
1225 if ( playertype == 2 ) playertext="KING'S";
1226 /*
1227 if ( playertype == 2 ){
1228 playertext="KING'S";
1229 }
1230 else{
1231 playertext="ATTACKER";
1232 }
1233 */
1234 blinkcursor();
1235 printturnprompt(); // display instructions
1236 while (turn){ // repeat until move is made
1237 xkey=getchar(); // get code of pressed key
1238 mkey=xkey;
1239 if (( xkey > 7 ) && ( xkey < 12 )){ // 8-11 = cursor keys
1240 cursormode=0; // freeform
1241 movecursor2();
1242 }
1243 /*******************************************************/
1244 /* determine if X or P is selected (to select a piece) */
1245 /*******************************************************/
1246 if (( xkey == 88) || ( xkey == 80)){ // if 'X' or 'P' is selected (88=X, 80=P)
1247 canselect=0; // set piece to NOT SELECTABLE
1248 if (( playertype == 1 )&&(players[ns][ew] == 1 )) canselect=1; // piece is selectable
1249 if (( playertype == 2 )&&((players[ns][ew] == 2 )||(players[ns][ew] == 3))) canselect=1;// piece is selectable
1250 if ( canselect ){
1251 canpiecemove();
1252 if (route ) {
1253 flashcolor=2;flashscreen(); // flash green
1254 if ( xkey == 80 ){ // if P is pressed
1255 printpossiblemoves(); // Print possible moves
1256 printturnprompt();
1257 }
1258 }
1259 else {
1260 flashred();
1261 canselect=0; // unselectable, cannot move
1262 }
1263 }
1264 else {
1265 flashred();
1266 }
1267 if (( mkey == 88 )&&( canselect )){ // if piece is SELECTED and CAN move
1268 inkcolor=2;inkasm(); // green to indicate piece is selected
1269 flashback=2;
1270 inverse2();
1271 //printmessage();
1272 //strcpy(message,playertext);
1273 message="PLACE CURSOR ON DESTINATION\nX=SELECT\nR=RESET";
1274 printmessage();
1275 //printf("\n\n\n%s Turn X=Select R=Reset",playertext);
1276 //inversex=cx;
1277 //inversey=cy;
1278 //inverse(); // highlight selected square (inverse color)
1279 mkey=0; // ensure mkey at known value
1280 // set Original cursor and board position of selected square
1281 ocx=cx; ocy=cy; ons=ns; oew=ew;
1282 while (( mkey != 88 ) && ( mkey != 82)){ // move cursor until X or R selected
1283 if (( ons == ns )&&( cursormovetype < 0)) cursormovetype=1; // cursor allowed north-south
1284 if (( oew == ew )&&( cursormovetype < 0)) cursormovetype=2; // cursor allowed east-west
1285 if (( ons == ns )&& (oew == ew )) cursormovetype=0; // cursor can move
1286 if (( cursormovetype == 2) && (( mkey == 8) ||(mkey == 9))) cursormovetype=-1; //!move
1287 if (( cursormovetype == 1) && (( mkey == 10)||(mkey == 11)))cursormovetype=-1; //!move
1288 if (( cursormovetype == 0) && (( mkey == 8) ||(mkey == 9))) cursormovetype=1; //move
1289 if (( cursormovetype == 0) && (( mkey == 10)||(mkey == 11)))cursormovetype=2; //move
1290 if ( cursormovetype > 0 ) {
1291 cursormode=1; // restricted
1292 movecursor2();
1293 }
1294 if ( cursormovetype < 0) { flashred();} // flashscreen red
1295 mkey=getchar();
1296 }
1297 if ( mkey == 82 ){ // R has been selected, Reset cursor to original positions
1298 fb=0;
1299 //drawcursor(); // blank out cursor at current position
1300 //inversex=cx;
1301 //inversey=cy;
1302 inverse();
1303 cx=ocx; // reset coords and board values to original positions
1304 cy=ocy;
1305 ns=ons;
1306 ew=oew;
1307 //inversex=cx;
1308 //inversey=cy;
1309 fb=1;
1310 //drawcursor(); // draw cursor at original selected position
1311 inverse2();
1312 inverse(); // inverse square
1313 }
1314 if ( mkey == 88 ){ // if X selected
1315 //inversex=ocx;
1316 //inversey=ocy;
1317 inverse(); // inverse original position
1318 // X is in original position so return to cursor movement
1319
1320 if (( ons == ns )&&( oew == ew)){
1321 inverse2();
1322 inverse();
1323 mkey=0; // piece de-selected
1324 }
1325 else{
1326 movepiece(); // move selected piece
1327 turn=0; // player has ended turn
1328 }
1329
1330 }
1331 }
1332 inkcolor=6;inkasm(); // back to cyan
1333 flashback=6;
1334 printturnprompt();
1335 } // key = X or P
1336 } // While player turn
1337 }
1338
1339
1340 // Moves selected piece to new location - updating board arrays and re-drawing tiles where necessary
1341 void movepiece(){
1342 p1=ATTACKER; // piece type comparison (lower) - used for determining takes - default=attacker
1343 p2=CASTLE; // piece type comparison (upper) - used for determining takes - default=attacker
1344 piecetype=players[ons][oew]; // obtain type of piece
1345 // move piece
1346 fb=0;
1347 //drawcursor(); // blank out cursor at new selected position
1348 row=ons;
1349 col=oew;
1350 tiletodraw=tiles[ons][oew];
1351 ptr_graph=PictureTiles;drawtile(); //draw tile at original location (blank out square)
1352 players[ons][oew]=0; //set original location to zero (unnocupied)
1353 players[ns][ew]=piecetype; //update square with player info
1354 // row, col required for drawpiece function
1355 row=ns;
1356 col=ew;
1357 drawpiece(); // draw piece at new location - 18-10-2011
1358 if (piecetype == KING){ // update king position (used by AI)
1359 kingns=ns;kingew=ew;
1360 if ((kingns != 5)||(kingew != 5)) {
1361 players[5][5]=CASTLE; // set central square to be 4 so it can be used in takes
1362 tiletodraw=3; row=5;col=5; ptr_graph=PictureTiles;drawtile(); // draw central square
1363 }
1364 }
1365 // having moved piece we now need to check for, and implement any TAKES
1366 if (piecetype > ATTACKER ){ // if defender
1367 p1=DEFENDER;
1368 p2=KING;
1369 }
1370 tpew=ew;
1371 if ( ns > 1 ){// check north
1372 orientation=NORTH;
1373 if ( cantakepiece() ) { tpns=ns-1; takepiece(); }
1374 }
1375 if ( ns < 9 ){ // check south
1376 orientation=SOUTH;
1377 if ( cantakepiece() ) { tpns=ns+1; takepiece(); }
1378 }
1379 tpns=ns;
1380 if ( ew < 9 ){ // check east
1381 orientation=EAST;
1382 if ( cantakepiece() ) { tpew=ew+1; takepiece(); }
1383 }
1384 if ( ew > 1 ){ // check west
1385 orientation=WEST;
1386 if ( cantakepiece() ) { tpew=ew-1; takepiece(); }
1387 }
1388 // update count of attackers around king
1389 kingattacker[NORTH]=0; // count of attackers NORTH of king
1390 kingattacker[SOUTH]=0; // count of attackers SOUTH of king
1391 kingattacker[EAST]=0; // count of attackers EAST of king
1392 kingattacker[WEST]=0; // count of attackers WEST of king
1393 kingdefender[NORTH]=0; // count of defenders NORTH of king
1394 kingdefender[SOUTH]=0; // count of defenders SOUTH of king
1395 kingdefender[EAST]=0; // count of defenders EAST of king
1396 kingdefender[WEST]=0; // count of defenders WEST of king
1397 kingpieces[NORTH]=0;
1398 kingpieces[SOUTH]=0;
1399 kingpieces[EAST]=0;
1400 kingpieces[WEST]=0;
1401 orientation=NORTH;
1402 cy=kingew;
1403 for (counter=0;counter<kingns;inccounter()){
1404 cx=counter;incdefatt();
1405 }
1406 orientation=SOUTH; // SOUTH
1407 for (counter=kingns+1;counter<11;inccounter()){
1408 cx=counter; incdefatt();
1409 }
1410 orientation=EAST; // EAST
1411 cx=kingns;
1412 for (counter=kingew+1;counter<11;inccounter()){
1413 cy=counter; incdefatt();
1414 }
1415 orientation=WEST; // WEST
1416 for (counter=0;counter<kingew;inccounter()){
1417 cy=counter; incdefatt();
1418 }
1419 }
1420
1421 void incdefatt(){
1422 if (players[cx][cy] == ATTACKER) inckingattacker();
1423 if (players[cx][cy] == DEFENDER) inckingdefender();
1424 }
1425
1426 void inckingdefender(){
1427 kingdefender[orientation]++;
1428 kingpieces[orientation]++;
1429 }
1430
1431 void inckingattacker(){
1432 kingattacker[orientation]++;
1433 kingpieces[orientation]++;
1434 }
1435
1436 /*void subcanbetaken(){
1437 target[targetns][targetew]=1;
1438 //if ((ns==kingns)||(ew==kingew)) { target[ns][ew]=3;} // means acceptable risk
1439 }
1440 */
1441 // can I be taken after moving here?
1442 void canbetaken() {
1443 if ((targetns )&&(targetns < 10)){
1444 takena=targetns-1;takenb=targetew;takenc=targetns+1;takend=targetew;takene=1;
1445 subcanbetaken2();
1446 takena=targetns+1;takenb=targetew;takenc=targetns-1;takend=targetew;takene=5;
1447 subcanbetaken2();
1448 }
1449
1450 if ((targetew )&&(targetew < 10)){
1451 takena=targetns;takenb=targetew+1;takenc=targetns;takend=targetew-1;takene=10;
1452 subcanbetaken2();
1453 takena=targetns;takenb=targetew-1;takenc=targetns;takend=targetew+1;takene=20;
1454 subcanbetaken2();
1455 }
1456 }
1457
1458 // Will return a value (take) who's values will be: 0= no, 1=yes
1459 unsigned char cantakepiece(){
1460 take=0;
1461 p1=ATTACKER; // piece type comparison (lower) - used for determining takes - default=attacker
1462 p2=CASTLE; // piece type comparison (upper) - used for determining takes - default=attacker
1463 pcheckns1=ns-1; // defaults to north
1464 pcheckns2=ns-2;
1465 pcheckew1=ew;
1466 pcheckew2=ew;
1467 piecetype=players[ns][ew]; // obtain type of piece
1468 //if ( fb==3) { piecetype=players[ctns][ctew];} // if computer turn set piecetype to piece being checked
1469 if ((fb == 3)||(fb == 9)) piecetype=ATTACKER; // default = ATTACKER
1470 if (piecetype > ATTACKER ){ // if defender
1471 p1=DEFENDER;
1472 p2=KING;
1473 }
1474 if ( orientation == SOUTH){ // if south
1475 pcheckns1=ns+1;
1476 pcheckns2=ns+2;
1477 }
1478 if ( orientation > SOUTH){ // if east or west
1479 pcheckns1=ns;
1480 pcheckns2=ns;
1481 pcheckew1=ew+1;
1482 pcheckew2=ew+2;
1483 if ( orientation == WEST){ // if west
1484 pcheckew1=ew-1;
1485 pcheckew2=ew-2;
1486 }
1487 }
1488 // RingOfSteel: when fb==6 update target if defender outside it's home zone
1489 if ((fb == 6)&&(players[pcheckns1][pcheckew1] == DEFENDER)){
1490 if (( pcheckns1 < 3 ) || (pcheckns1 > 7) || (pcheckew1 < 3)||(pcheckew1 > 7)){
1491 target[ns][ew]+=10;
1492 }
1493 }
1494 // if a take is possible increment the take counter - if values fall within bounds...
1495 if ((pcheckns2 > -1)&&(pcheckns2 < 11)&&(pcheckew2 > -1)&&(pcheckew2 < 11)){
1496 if (( players[pcheckns1][pcheckew1] )&&(players[pcheckns1][pcheckew1] != p1)&&(players[pcheckns1][pcheckew1] != p2 )&&(players[pcheckns1][pcheckew1] != CASTLE)){
1497 // if ((( players[pcheckns2][pcheckew2] == p1 )||(players[pcheckns2][pcheckew2] == p2 )||(players[pcheckns2][pcheckew2] == 4)&&(pcheckns2!=5)&&(pcheckew2!=5))) // the 5 is to EXCLUDE central square
1498 if (( players[pcheckns2][pcheckew2] == p1 )||(players[pcheckns2][pcheckew2] == p2 )||(players[pcheckns2][pcheckew2] == CASTLE)){
1499 take++;
1500 //if ((players[pcheckns1][pcheckew1]==3)&&(surrounded<3))take--; // if possible take is a king but not surrounded
1501 if (players[pcheckns1][pcheckew1]==KING) take--;// if possible take is a king
1502
1503 }
1504 if ( computer[pcheckns2][pcheckew2] ) inctarget(); // 31-10-2011 - can possibly take on next turn
1505 }
1506 }
1507 return take;
1508 }
1509
1510 // performs taking/removing a piece
1511 void takepiece() {
1512 players[tpns][tpew]=0; // clear board location
1513 row=tpns;
1514 col=tpew;
1515 inkcolor=6;inkasm();
1516 explodetile(); // plays animation to "kill" a tile
1517 tiletodraw=tiles[row][col]; // decide tile to draw
1518 ptr_graph=PictureTiles;drawtile();// draw tile at location
1519 // update deadpile
1520 deadtoggle=1; // ensure deadpiece is drawn in foreground color on deadpile
1521 deadpile();
1522 }
1523
1524 void subarrows(){
1525 if ( tiles[xns][xew] == CASTLE ) arrow=2;
1526 if ((players[xns][xew])&&(players[xns][xew] < CASTLE)) {
1527 arrow=0; // !ok if piece occupied
1528 if ((fb == 4)&&(players[xns][xew] == ATTACKER)) enemy[xns][xew]+=ENEMYWEIGHT; // means enemy could get here if attacker moved elsewhere
1529 }
1530 if (( players[ns][ew] == KING )&&( tiles[xns][xew] == CASTLE )) arrow = 1; // CASTLE square ok if king
1531 }
1532
1533 void subarrows2(){
1534 if ( orientation == NORTH ) enemy[xns][xew]+=5; // means enemy can get here from SOUTH
1535 if ( orientation == SOUTH ) enemy[xns][xew]+=1; // means enemy can get here from NORTH
1536 if ( orientation == EAST ) enemy[xns][xew]+=20; // means enemy can get here from WEST
1537 if ( orientation == WEST ) enemy[xns][xew]+=10; // means enemy can get here from EAST
1538 }
1539
1540 void inccantake(){
1541 z=cantakepiece();
1542 if (z ){
1543 cantake+=z;
1544 cantakeadjust(); // decrement take count if taken piece on same plane as king and taker isn't
1545 }
1546 }
1547
1548 // Explodes a tile
1549 void explodetile() {
1550 //unsigned char b;
1551 ptr_graph=ExplodeTiles; // pointer to byte values of loaded picture
1552 for (b=0;b<8;b++){
1553 tileloop();
1554 pausetime=900;
1555 if (b == 5) pausetime=3000; // pause longer on skull&crossbones
1556 pause(); // add a pause
1557 }
1558 }
1559
1560 void timertile(){
1561 unsigned char timer;
1562 ptr_graph=TimerTiles; // pointer to byte values of loaded picture (Timer)
1563 row=5;col=5;
1564 for (timer=0;timer<8;timer++){
1565 tileloop();
1566 pausetime=250;pause();
1567 }
1568 }
1569
1570 void drawpiece(){
1571 tiletodraw=players[row][col];
1572 if ( tiletodraw ) tiletodraw+=3;
1573 if ( tiles[row][col] ) tiletodraw+=3;
1574 ptr_graph=PictureTiles;drawtile();
1575 }
1576
1577 void drawarrow(){
1578 if ( fb == 1 ){
1579 tiletodraw=10;
1580 if ( tiles[row][col] ) tiletodraw++; // add another 1 for arrow with background
1581 }
1582 else{
1583 tiletodraw=tiles[row][col]; // draw original tile (includes blank)
1584 }
1585 ptr_graph=PictureTiles;drawtile();
1586 }
1587
1588 void surroundcount(){
1589 //unsigned char test;
1590 zerocounter();
1591 //setpoints();
1592 surrounded=0;
1593 if (( kingns == 0)||(kingns == 10)||(kingew == 0)||(kingew == 10)) incsurround(); // added 18/10/2011 (inc surround if at an edge)
1594 surew=kingew;
1595 if ( kingns ) {surns=kingns-1;surroundcheck();}
1596 if ( kingns < 10 ){surns=kingns+1;surroundcheck();}
1597 surns=kingns;
1598 if ( kingew ) {surew=kingew-1;surroundcheck();}
1599 if ( kingew < 10 ){surew=kingew+1;surroundcheck();}
1600 /*for (test=surrounded;test >0; test--){
1601 zap();
1602 }*/
1603 // unset any "enemy and target values" ONLY if blank square adjacent to king is accessible
1604 if (surrounded == 3){
1605 ezew1=kingew;
1606 if ( kingns ){ // NORTH
1607 ezns1=kingns-1;
1608 enemyzero();
1609 }
1610 if ( kingns < 10 ){ // SOUTH
1611 ezns1=kingns+1;
1612 enemyzero();
1613 }
1614 ezns1=kingns;
1615 if ( kingew < 10 ){ // EAST
1616 ezew1=kingew+1;
1617 enemyzero();
1618 }
1619 if ( kingew ){
1620 ezew1=kingew-1; // WEST
1621 enemyzero();
1622 }
1623 }
1624 }
1625
1626 void pause(){
1627 int p;
1628 for (p=0; p<pausetime;p++){};
1629 }
1630
1631
1632 /******************************/
1633
1634 void subcanbetaken2(){ // DO NOT MESS with this (NBARNES 10-01-2012)
1635 if (players[takena][takenb] > ATTACKER){
1636 if ((players[takenc][takend] == 0)||(enemy[takenc][takend] > ENEMYWEIGHT)){
1637 if ((enemy[takenc][takend]-takene)&&((enemy[takenc][takend] < ENEMYWEIGHT)||(enemy[takenc][takend]-ENEMYWEIGHT))){ // 23-12-2011
1638 compass[origorient]=1; // e.g. compass[NORTH]=1 means canbetaken here if moving from NORTH
1639 if (enemy[takenc][takend]>ENEMYWEIGHT){ // THIS is the business!!!
1640 if ((origorient < EAST)&&(mkey != takenc)&&(oew != takend)) compass[origorient]=0;
1641 if ((origorient > SOUTH)&&(ons != takenc)&&(mkey != takend))compass[origorient]=0;
1642 }
1643 }
1644 }
1645 }
1646 }
1647
1648
1649 void inctarget(){
1650 target[targetns][targetew]+=2;
1651 //target[targetns][targetew]++; // 28-04-2013
1652 }
1653
1654
1655 void surroundcheck(){
1656 // if attacker or kingsquare n/s/e/w then inc surrounded
1657 //if (players[surns][surew]==1) incsurround(); // is attacker n,s,e,w
1658 //if (tiles[surns][surew]>2) incsurround(); // is king square n,s,e,w
1659 if ((players[surns][surew] == 1)||(tiles[surns][surew] > 2)) {
1660 incsurround();
1661 }
1662 }
1663
1664
1665
1666
1667 // called from "surroundcount()"
1668 void enemyzero() {
1669 if (( players[ezns1][ezew1] == 0 )&&(target[ezns1][ezew1])){ // if adjacent square n/s/e/w is blank and accessible
1670 ClearArrays(); // set all arrays to zero (target, enemy, computer)
1671 target[ezns1][ezew1]=100; // set big target value to final space by king
1672 }
1673 }
1674 // Checkroute:
1675 // Currently only works when "crossing the T"
1676 // checkroutemode=1 Returns number of pieces on a given route
1677 // checkroutemode=2 Increments the target values on route
1678 // checkroutemode=3 Number of targets on route
1679 // checkroutemode=4 Number of "enemy" targets on route (where enemies CAN go)
1680 // checkroutemode=5 Emergency! Make target=hightarget+1
1681 unsigned char checkroute(){
1682 z=0;
1683 // a SINGLE COLUMN (North to South) so check each row on it
1684 checkroutestart=startrow;
1685 checkroutedest=destrow;
1686 checkrouterow=startrow;
1687 checkroutecol=startcol;
1688 if ( startrow == destrow ){ // ELSE a single ROW (EAST to WEST)
1689 checkroutestart=startcol;
1690 checkroutedest=destcol;
1691 }
1692 for (x=checkroutestart;x<=checkroutedest;x++){
1693 //if ( startrow==destrow ) {checkroutecol++;}else{checkrouterow++;}
1694 switch(checkroutemode){
1695 case 1: if ((players[checkrouterow][checkroutecol] == ATTACKER )||(players[checkrouterow][checkroutecol] == DEFENDER )) z++;break;
1696 case 2: if (target[checkrouterow][checkroutecol] ) target[checkrouterow][checkroutecol]+=2;break;
1697 case 3: if (target[checkrouterow][checkroutecol] ) z++;break;
1698 case 4: if (enemy[checkrouterow][checkroutecol] ) z+=ENEMYBLOCK;break;
1699 case 5: if (target[checkrouterow][checkroutecol]){
1700 target[checkrouterow][checkroutecol]+=points;} // brokenarrow
1701 break;
1702 //case 6: if (players[checkrouterow][checkroutecol]) z++;break;
1703 case 6: if (kingtracker[checkrouterow][checkroutecol]) z++;break;
1704 }
1705 if ( startrow == destrow ) {checkroutecol++;}else{checkrouterow++;}
1706
1707 }
1708 return z;
1709 }
1710
1711 /*
1712 // ORIGINAL 02/09/2012
1713 unsigned char checkroute(){
1714 z=0;
1715 if (orientation<EAST){ // if checking ROWS (crossing the T) (used for NORTH SOUTH checks)
1716 for (x=startcol;x<=destcol;x++){ // check row
1717 switch(checkroutemode){
1718 case 1: if ((players[startrow][x]==1)||(players[startrow][x]==2)) {z++;}break;
1719 case 2: if (target[startrow][x]) {target[startrow][x]+=2;}break;
1720 case 3: if (target[startrow][x]) {z++;}break;
1721 case 4: if (enemy[startrow][x]) {z+=10;}break;
1722 case 5: if (target[startrow][x]) {target[startrow][x]=255;}
1723 }
1724 }
1725 }
1726 else { // EAST WEST checks (crossing the T)
1727 for (x=startrow;x<=destrow;x++){ // check accross
1728 switch(checkroutemode){
1729 case 1: if ((players[x][startcol]==1)||(players[x][startcol]==2)) {z++;}break;
1730 case 2: if (target[x][startcol]) {target[x][startcol]+=2;}break;
1731 case 3: if (target[x][startcol]) {z++;}break;
1732 case 4: if (enemy[x][startcol]) {z++;}break;
1733 case 5: if (target[x][startcol]) {target[x][startcol]==255;}
1734 }
1735 }
1736 }
1737 return z;
1738 }
1739 */
1740 // decrements cantake if taken piece is on same plane as king
1741 // and attacking piece isn't AND only one defender on plane
1742 void cantakeadjust(){
1743 flag=0;
1744 if ((playertype == 1)&&(gamestyle == 1)){ // if computer playing as attacker and his turn
1745 if (pcheckns1 == kingns){
1746 flag=1;
1747 if (ctew < kingew){orientation=WEST;}else{orientation=EAST;}
1748 //if ((kingattacker[orientation]+kingdefender[orientation])<4){cantake--;}
1749 }
1750 if (pcheckew1 == kingew){
1751 flag=1;
1752 if (ctns < kingns){orientation=NORTH;}else{orientation=SOUTH;}
1753 //if ((kingattacker[orientation]+kingdefender[orientation])<4){cantake--;}
1754 }
1755 if (flag ) {
1756 //if ((kingattacker[orientation]+kingdefender[orientation])<4){cantake--;}
1757 if (kingpieces[orientation] < 4) cantake--; //10-05-2013 if no other pieces on plane
1758 }
1759
1760 }
1761 }
1762
1763 void updatetarget(){
1764 targetns=ctns;targetew=ctew;
1765 target[targetns][targetew]=2; // set target to 2 (1=canbetaken if i go here)
1766 // set "illegal" squares to zero
1767 target[5][5]=0;
1768 target[0][10]=0;
1769 target[0][0]=0;
1770 target[10][0]=0;
1771 target[10][10]=0;
1772 if ( target[targetns][targetew] ){ // only if target is valid (i.e. not a king square)
1773 // increase target if blocking 1 enemy
1774 if ( enemy[targetns][targetew] ) inctarget();
1775 // increase taregt if blocking 2 enemies
1776 if (( enemy[targetns][targetew] == 6)||(enemy[targetns][targetew] == 11)||(enemy[targetns][targetew] == 21)||(enemy[targetns][targetew] == 15)||(enemy[targetns][targetew] == 25)||(enemy[targetns][targetew] == 30)) inctarget();
1777 // increase target if blocking 3 enemies
1778 if (( enemy[targetns][targetew] == 35)||(enemy[targetns][targetew] == 16)||(enemy[targetns][targetew] == 26) || (enemy[targetns][targetew] == 31)) inctarget();
1779 // calculates how many takes can be made in this position (cantake)
1780 calccantake2();
1781 //calccantake(); // calculates how many takes can be made in this position (cantake)
1782 //y=cantake*TAKEWEIGHT; // value to be added to target
1783 //target[targetns][targetew]+=y; // add cantake (will be zero if cannot take)
1784 target[targetns][targetew]+=(cantake*TAKEWEIGHT);
1785 //if (cantake==0) {canbetaken();} // sets target to 1 if cannot take but can be taken
1786 }
1787 }
1788
1789
1790 // calculate how many takes can be made
1791 /*
1792 void calccantake() {
1793 //unsigned char x;
1794 //cantake=0;
1795 inccantake(); // inc cantake if can take in direction of travel
1796 //for (x=0;x<4;x++) {
1797 //if ( x<2 ){ // heading north/south
1798 if ( origorient < EAST ){ // HEADING NORTH/SOUTH
1799 if ( ew < 10 ) {orientation=EAST; inccantake();} // check EAST
1800 if ( ew > 1 ) {orientation=WEST; inccantake();} // check WEST
1801 }else{ // heading east/west
1802 if ( ns > 1 ) {orientation=NORTH; inccantake();} // check NORTH
1803 if ( ns < 9 ) {orientation=SOUTH; inccantake(); } // check SOUTH
1804 }
1805 }
1806 */
1807 void calccantake2(){
1808 // check all directions from a given target square...
1809 cantake=0;
1810 if ( ew < 10 ) {orientation=EAST; inccantake();} // check EAST
1811 if ( ew > 1 ) {orientation=WEST; inccantake();} // check WEST
1812 if ( ns > 1 ) {orientation=NORTH; inccantake();} // check NORTH
1813 if ( ns < 9 ) {orientation=SOUTH; inccantake();} // check SOUTH
1814 }
1815 // print the title screen
1816 void printtitles() {
1817 unsigned char f=0;
1818 inkcolor=3;inkasm(); // yellow, erm...gold
1819 row=0;c=6;d=11;col=0;
1820 for (mkey=0;mkey<2;mkey++){
1821 for (a=row;a<c;a++){
1822 col=0;
1823 if (mkey ) {fliprune();col=1;} // flip the row
1824 for(b=col;b<d;b++){
1825 tiletodraw=border[a][b]; // get runic chars
1826 if (f == 1) tiletodraw++; // get western chars on 2nd pass
1827 if ( tiletodraw < 99){
1828 ptr_graph=RunicTiles; // pointer to Border Tiles graphics
1829 drawtile(); // draw tile
1830 }
1831 col++;
1832 }
1833 row++;
1834 }
1835 row=1;col=1;c=5;d=10;pausetime=26000;pause();
1836 f++;if (f==2) f=0;
1837 }
1838 }
1839
1840 // performs the rune flipping sequence in title screen
1841 void fliprune() {
1842 for (tiletodraw=30;tiletodraw<35;tiletodraw++){
1843 for (col=1;col<10;col++){
1844 if (border[row][col] < 99){
1845 ptr_graph=RunicTiles; // pointer to Border Tiles graphics
1846 drawtile();pausetime=50;pause();
1847 }
1848 }
1849 }
1850 }
1851 /*
1852 void subzoneupdate(){ // (updates border targets)
1853 message="BROKEN ARROW UPDATE";
1854 printline();
1855 message="\nPRESS A KEY";
1856 printline();
1857 getchar();
1858 checkroutemode=5;checkroute();
1859 }
1860 */
1861 void updateroutetarget(){
1862 //setcheckmode3(); // set the mode of checkroute to 3 (count how many TARGETS are on route)
1863 //pacpointsz=checkroute();
1864 //pacpointsz=25-pacpointsz; // 20 = max amount of targets on a given route to a corner
1865 setcheckmode2(); // set the mode of checkroute to 2 (update targets)
1866 checkroute();
1867 }
1868
1869 // flashes the screen red (goes back to whatever flashback is set to)
1870 void flashred(){
1871 flashcolor=1;
1872 flashscreen();
1873 }
1874
1875 /*
1876 void prioritycalc(){ // calculates the priorities of moving a piece
1877 for(a=0;a<11;a++){
1878 for (b=0;b<11;b++){
1879 if (players[a][b]==1){
1880 // count attackers on row
1881 for (c=0;c<11;c++){
1882 if (players[c][b]==1) priority[a][b]++;
1883 }
1884 for (d=0;d<11;d++){
1885 if (players[a][d]==1) priority[a][b]++;
1886 }
1887 }
1888 }
1889 }
1890 }
1891 */

  ViewVC Help
Powered by ViewVC 1.1.26