Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

543 lines
8.2 KiB

  1. /************/
  2. /* ROUTINES */
  3. /************/
  4. #define _WINDOWS
  5. #include <windows.h>
  6. #include <port1632.h>
  7. #include "main.h"
  8. #include "res.h"
  9. #include "rtns.h"
  10. #include "grafix.h"
  11. #include "pref.h"
  12. #include "sound.h"
  13. #include "util.h"
  14. /*** Global/Local Variables ***/
  15. INT iPlayer;
  16. BOOL fFlash = fFalse; /* Integerate these ! */
  17. BOOL fFlashOnOff;
  18. BOOL f4; /* TRUE if need 4 in a row */
  19. INT cPlane; /* Number of planes */
  20. INT cBlkRow; /* Number of balls in a row */
  21. INT cBlkPlane; /* Number of positions in a single plane */
  22. INT cBlkMac; /* Total number of available positions */
  23. /* Computer stuff */
  24. INT iBlkLose; /* Place to put if about to lose */
  25. INT iMoveCurr;
  26. BLK rgBlk[cBlkMax]; /* The main grid data */
  27. BLK rgFlash[cDimMax]; /* list of balls to flash */
  28. BLK rgMove[cBlkMax]; /* list of moves (for UNDO) */
  29. BLK rgBest[cBlkMax]; /* count of times "best" */
  30. #include "tbls.inc"
  31. #define cChkMax k4x4x4
  32. INT cChkMac;
  33. INT rgChk[cChkMax][cDimMax];
  34. /*** Global/External Variables ***/
  35. extern STATUS status;
  36. extern PREF Preferences;
  37. extern blkCurr;
  38. BLK ComputerMove(VOID);
  39. /****** F C H E C K W I N ******/
  40. /* Return TRUE if anyone won */
  41. /* rgFlash contains winning set */
  42. BOOL FCheckWin(VOID)
  43. {
  44. REGISTER INT x;
  45. REGISTER INT y;
  46. INT c;
  47. if (f4)
  48. {
  49. for (y = 0; y < cChkMac; y++)
  50. {
  51. if (c = rgBlk[rgChk[y][0]])
  52. if (c == rgBlk[rgChk[y][1]])
  53. if (c == rgBlk[rgChk[y][2]])
  54. if (c == rgBlk[rgChk[y][3]])
  55. {
  56. for (x = 0; x < cBlkRow; x++)
  57. rgFlash[x] = rgChk[y][x];
  58. return (fFlash = fTrue);
  59. }
  60. }
  61. }
  62. else
  63. {
  64. for (y = 0; y < cChkMac; y++)
  65. {
  66. if (c = rgBlk[rgChk[y][0]])
  67. if (c == rgBlk[rgChk[y][1]])
  68. if (c == rgBlk[rgChk[y][2]])
  69. {
  70. for (x = 0; x < cBlkRow; x++)
  71. rgFlash[x] = rgChk[y][x];
  72. return (fFlash = fTrue);
  73. }
  74. }
  75. }
  76. return fFalse;
  77. }
  78. /****** D O M O V E ******/
  79. VOID DoMove(BLK blk)
  80. {
  81. #ifdef DEBUG3
  82. CHAR sz[80];
  83. LMove:
  84. wsprintf(sz,"Move=%d Player=%d\r\n",blk,iPlayer);
  85. OutputDebugString(sz);
  86. if (blk < 0 || blk >= cBlkMac)
  87. {
  88. Oops("Invalid blk");
  89. return;
  90. }
  91. else if (rgBlk[blk])
  92. {
  93. Oops("Invalid Move!");
  94. return;
  95. }
  96. #else
  97. LMove:
  98. #endif
  99. rgMove[iMoveCurr++] = blk; /* Remember move */
  100. PlaceBall(blk, iPlayer);
  101. if (FCheckWin())
  102. {
  103. ClrStatusPlay();
  104. fFlashOnOff = fTrue;
  105. fFlash = fTrue;
  106. PlayTune(iPlayer == iComputer ? TUNE_LOSEGAME : TUNE_WINGAME);
  107. }
  108. else if (iMoveCurr == cBlkMac)
  109. ClrStatusPlay();
  110. else
  111. {
  112. blkCurr = blk;
  113. if ((iPlayer ^= 3) == iComputer)
  114. {
  115. blk = ComputerMove();
  116. goto LMove;
  117. }
  118. else
  119. PlayTune(TUNE_DROP); /* Computer makes noise too */
  120. }
  121. }
  122. /****** U N D O M O V E ******/
  123. VOID UnDoMove(VOID)
  124. {
  125. if (iMoveCurr)
  126. {
  127. rgBlk[rgMove[--iMoveCurr]] = iBallBlank; /* Undo Computer move */
  128. if (iMoveCurr)
  129. {
  130. rgBlk[rgMove[--iMoveCurr]] = iBallBlank; /* Undo Human move */
  131. ReDoDisplay();
  132. DisplayGrid();
  133. }
  134. else
  135. {
  136. iPlayer = iComputer;
  137. DoMove(ComputerMove());
  138. }
  139. }
  140. else
  141. MessageBeep(0); /* Should be a sound !!! */
  142. }
  143. /****** G E T B E S T B L K ******/
  144. BLK GetBestBlk(VOID)
  145. {
  146. INT cMac;
  147. BLK blkBest;
  148. BLK iBlk;
  149. INT cBlk;
  150. /* Future: If f4 & we have a set of corners, try recursion */
  151. /* Find most promising position */
  152. cMac = 0;
  153. cBlk = 0;
  154. blkBest = 0;
  155. for (iBlk = 0; iBlk < cBlkMac; iBlk++)
  156. if (rgBest[iBlk] != 0)
  157. {
  158. if (rgBest[iBlk] > cMac)
  159. {
  160. cBlk = 1;
  161. blkBest = iBlk;
  162. cMac = rgBest[iBlk];
  163. }
  164. else if (rgBest[iBlk] == cMac)
  165. {
  166. if (Rnd(++cBlk) == 0)
  167. blkBest = iBlk;
  168. }
  169. }
  170. if (blkBest != 0)
  171. return blkBest;
  172. switch (Preferences.iGameType)
  173. {
  174. case iGame3x3:
  175. if (rgBlk[4] == iBallBlank)
  176. return 4;
  177. break;
  178. case iGame3x3x3:
  179. if (rgBlk[13] == iBallBlank)
  180. return 13;
  181. break;
  182. default:
  183. break;
  184. }
  185. /* Find an empty corner */
  186. iBlk = Rnd(8);
  187. for (cMac = 0; cMac++ < 8;)
  188. {
  189. if (rgBlk[blkBest = rgCorner[Preferences.iGameType][iBlk]] == iBallBlank)
  190. return blkBest;
  191. iBlk = (iBlk+1) % 8;
  192. }
  193. return iBlkNil;
  194. }
  195. /****** B L K C H K 3 ******/
  196. BLK BlkChk3(INT b1, INT b2, INT b3)
  197. {
  198. #ifdef DEBUG
  199. CHAR sz[80];
  200. wsprintf(sz,"BlkChk3=%d %d %d v=%d\r\n",b1,b2,b3,rgBlk[b1]+rgBlk[b2]*3+rgBlk[b3]*9);
  201. OutputDebugString(sz);
  202. #endif
  203. switch (rgBlk[b1] + rgBlk[b2]*3 + rgBlk[b3]*9)
  204. {
  205. case 4:
  206. return b3;
  207. case 10:
  208. return b2;
  209. case 12:
  210. return b1;
  211. case 8:
  212. iBlkLose = b3;
  213. break;
  214. case 20:
  215. iBlkLose = b2;
  216. break;
  217. case 24:
  218. iBlkLose = b1;
  219. break;
  220. case 1:
  221. rgBest[b3]++;
  222. break;
  223. case 9:
  224. rgBest[b1]++;
  225. break;
  226. }
  227. return iBlkNil;
  228. }
  229. /****** B L K C H K 4 ******/
  230. BLK BlkChk4(INT b1, INT b2, INT b3, INT b4)
  231. {
  232. switch (rgBlk[b1] + rgBlk[b2]*3 + rgBlk[b3]*9 + rgBlk[b4]*27)
  233. {
  234. case 13:
  235. return b4;
  236. case 31:
  237. return b3;
  238. case 37:
  239. return b2;
  240. case 39:
  241. return b1;
  242. case 26:
  243. iBlkLose = b4;
  244. break;
  245. case 62:
  246. iBlkLose = b3;
  247. break;
  248. case 74:
  249. iBlkLose = b2;
  250. break;
  251. case 78:
  252. iBlkLose = b1;
  253. break;
  254. case 1:
  255. rgBest[b4]++;
  256. break;
  257. case 27:
  258. rgBest[b1]++;
  259. break;
  260. case 28:
  261. rgBest[b2] += 4;
  262. rgBest[b3] += 4;
  263. break;
  264. }
  265. return iBlkNil;
  266. }
  267. /****** S K I L L ******/
  268. BOOL Skill(INT intel, INT chance)
  269. {
  270. if (Preferences.skill > intel)
  271. return fTrue;
  272. return (Rnd(100) < chance);
  273. }
  274. /****** C O M P U T E R M O V E ******/
  275. BLK ComputerMove(VOID)
  276. {
  277. REGISTER INT iBlk;
  278. REGISTER INT y;
  279. iBlkLose = iBlkNil;
  280. for (iBlk = 0; iBlk < cBlkMac; iBlk++) /** USE A BLT !!! **/
  281. rgBest[iBlk] = 0;
  282. if (Skill(10, 10))
  283. {
  284. if (Skill(10, 50))
  285. /* Search for winning location */
  286. {
  287. if (f4)
  288. {
  289. for (y = 0; y < cChkMac; y++)
  290. if ((iBlk = BlkChk4(rgChk[y][0], rgChk[y][1], rgChk[y][2], rgChk[y][3])) != iBlkNil)
  291. return iBlk;
  292. }
  293. else
  294. {
  295. for (y = 0; y < cChkMac; y++)
  296. if ((iBlk = BlkChk3(rgChk[y][0], rgChk[y][1], rgChk[y][2])) != iBlkNil)
  297. return iBlk;
  298. }
  299. }
  300. /* Is there a losing location ? */
  301. if ((iBlkLose != iBlkNil) && Skill(50, 50))
  302. return iBlkLose;
  303. /* Is there a best spot ? */
  304. if (Skill(70, 80) && ((iBlk = GetBestBlk()) != iBlkNil))
  305. return iBlk;
  306. }
  307. /* Random search for a valid spot */
  308. while (rgBlk[iBlk = Rnd(cBlkMac)] != iBallBlank)
  309. ;
  310. return iBlk;
  311. }
  312. /****** D O T I M E R ******/
  313. VOID DoTimer(VOID)
  314. {
  315. if (fFlash)
  316. DoFlash(fFlashOnOff ^= 1);
  317. }
  318. /****** S E T U P D A T A */
  319. VOID SetupData(VOID)
  320. {
  321. #ifdef DEBUG2
  322. CHAR sz[80];
  323. #endif
  324. INT c,c2,c3;
  325. POS pos;
  326. INT iTbl = 0;
  327. INT cTblMac = 0;
  328. switch (Preferences.iGameType)
  329. {
  330. case iGame3x3:
  331. f4 = fFalse;
  332. cBlkRow = 3;
  333. cPlane = 1;
  334. iTbl = i3x3;
  335. cTblMac = c3x3;
  336. break;
  337. case iGame3x3x3:
  338. f4 = fFalse;
  339. cBlkRow = 3;
  340. cPlane = 3;
  341. iTbl = i3x3x3;
  342. cTblMac = c3x3x3;
  343. break;
  344. case iGame4x4x4:
  345. f4 = fTrue;
  346. cBlkRow = 4;
  347. cPlane = 4;
  348. iTbl = i4x4x4;
  349. cTblMac = c4x4x4;
  350. break;
  351. }
  352. cBlkPlane = cBlkRow * cBlkRow;
  353. cBlkMac = cBlkPlane * cPlane;
  354. #ifdef DEBUG3
  355. wsprintf(sz,"Game=%d cBlkRow=%d cPlane=%d\r\n",Preferences.iGameType, cBlkRow, cPlane);
  356. OutputDebugString(sz);
  357. wsprintf(sz,"cBlkPlane=%d cBlkMac=%d cTblMac=%d\r\n",cBlkPlane, cBlkMac, cTblMac);
  358. OutputDebugString(sz);
  359. #endif
  360. cChkMac = 0;
  361. c3 = 0;
  362. while (c3++ < cTblMac)
  363. {
  364. pos = rgtbl[iTbl][iposStart];
  365. c2 = 0;
  366. while (c2 < cBlkRow)
  367. {
  368. for (c=0; c < cBlkRow; c++)
  369. {
  370. rgChk[cChkMac][c] = pos;
  371. #ifdef DEBUG2
  372. wsprintf(sz," %d",pos);
  373. OutputDebugString(sz);
  374. #endif
  375. pos = (pos + rgtbl[iTbl][iposOff]) % cBlkMac;
  376. }
  377. cChkMac++;
  378. c2++;
  379. if (rgtbl[iTbl][iposLine] == (BYTE) -1)
  380. c2 = cBlkRow;
  381. else
  382. pos = (pos + rgtbl[iTbl][iposLine] - rgtbl[iTbl][iposOff]) % cBlkMac;
  383. #ifdef DEBUG2
  384. OutputDebugString("\r\n");
  385. #endif
  386. }
  387. iTbl++;
  388. #ifdef DEBUG2
  389. OutputDebugString("------\r\n");
  390. #endif
  391. }
  392. #ifdef DEBUG2
  393. wsprintf(sz,"cChkMac=%d",cChkMac);
  394. OutputDebugString(sz);
  395. #endif
  396. }
  397. /****** S T A R T G A M E *******/
  398. VOID StartGame(VOID)
  399. {
  400. REGISTER i;
  401. fFlash = fFalse;
  402. ClrStatusIcon();
  403. SetStatusPlay();
  404. iMoveCurr = 0;
  405. #ifdef DEBUG3
  406. OutputDebugString("*** New Game ***\r\n");
  407. #endif
  408. for (i = 0; i < cBlkMac; i++) /* USE A BLT ! */
  409. rgBlk[i] = iBallBlank;
  410. ReDoDisplay();
  411. DisplayGrid();
  412. if (Preferences.iStart == iStartRnd)
  413. iPlayer = 1 + Rnd(2);
  414. else
  415. iPlayer = Preferences.iStart;
  416. if (iPlayer == iComputer)
  417. {
  418. iPlayer = iComputer;
  419. DoMove(ComputerMove());
  420. }
  421. }