PageRenderTime 159ms CodeModel.GetById 31ms RepoModel.GetById 8ms app.codeStats 0ms

/gamazons-0.83/src/moves.c

#
C | 2203 lines | 1589 code | 300 blank | 314 comment | 260 complexity | 7a655390de8a7fa1943b91b60e16bd79 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*************
  2. sean mcmillen
  3. ronald yorgason
  4. CS410 Combinatorial Games -- Spring 2002
  5. amazons player.
  6. amazons -h for options
  7. Project URL: http://www.yorgalily.org/amazons/
  8. ***************/
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <limits.h>
  13. #include <time.h>
  14. #include <assert.h>
  15. #include <ctype.h>
  16. #include <sys/poll.h>
  17. //#ifdef GAMAZONS
  18. #include <gnome.h>
  19. //#endif
  20. #include "amazons.h"
  21. #include "unit-test.h"
  22. #define HEVAL heval // for testing differant hevals
  23. #define MINDEPTH 1
  24. #define VERBOSE 0
  25. #define TIMED 1 // boolean, if 1 then TIMEOUT is in effect, if 0 then no
  26. // macros
  27. //#define MIN(a,b) (a < b ? a : b)
  28. //#define MAX(a,b) (a > b ? a : b)
  29. #define MMSET(p,q) ((p) == 1 ? SHRT_MIN+q : SHRT_MAX-q)
  30. // constants
  31. #define WHITEQUEENS 4
  32. #define BLACKQUEENS 4
  33. /* local prototypes */
  34. move mtdf(state *s, int guess, int tdepth);
  35. // some globals //
  36. FILE *movin; // read moves from here
  37. FILE *movout; // write moves to here
  38. struct pollfd pollstruct; // used to poll FILE *movin
  39. int onmove;
  40. int nodes; // statitics gatherer
  41. int rawnodes; // statitics gatherer
  42. int hevalz; // statitics gatherer
  43. int hits; // statitics gatherer
  44. int ok; // global, if 0 then timeout condition
  45. time_t start; // global, start of search, used for timeout
  46. // check
  47. struct options options;
  48. struct game_states states;
  49. #ifdef GAMAZONS
  50. extern int state_hash;
  51. extern GtkWidget *main_window;
  52. #endif
  53. // command line flags -- set defaults here
  54. /*
  55. int white_player = FALSE;
  56. int black_player = FALSE;
  57. int print_statistics = FALSE;
  58. int TIMEOUT = 5;
  59. int MAXDEPTH = 20;
  60. int MAXWIDTH = 5000;
  61. */
  62. int obst_heval(state *s)
  63. {
  64. int moves;
  65. int t1;
  66. int t2;
  67. int turn;
  68. if (onmove > 10)
  69. return heval(s);
  70. turn = s->turn;
  71. s->turn = WHITE_PLAYER;
  72. t1 = countobst(s);
  73. s->turn = BLACK_PLAYER;
  74. t2 = countobst(s);
  75. s->turn = turn;
  76. moves = t1 - t2;
  77. return moves;
  78. }
  79. int countobst(state *s)
  80. {
  81. int i,j;
  82. int m=0, p=0;
  83. int xo=0, yo=0;
  84. int axo=0, ayo=0;
  85. int dir, adir;
  86. int QUEENS;
  87. uchar *queens_x;
  88. uchar *queens_y;
  89. ull *board;
  90. int queen = 0;
  91. if(s->turn == WHITE_PLAYER)
  92. {
  93. queens_x = s->white_q_x;
  94. queens_y = s->white_q_y;
  95. board = s->white_bd;
  96. QUEENS = WHITEQUEENS;
  97. }
  98. else
  99. {
  100. queens_x = s->black_q_x;
  101. queens_y = s->black_q_y;
  102. board = s->black_bd;
  103. QUEENS = BLACKQUEENS;
  104. }
  105. // order: N NE E SE S SW W NW
  106. for (queen = 0; queen < QUEENS; queen++)
  107. {
  108. for (dir = 0; dir < 8; dir++)
  109. {
  110. // for tightness not speed
  111. switch (dir)
  112. {
  113. case 0:
  114. xo = 0; yo = 1;
  115. break;
  116. case 1:
  117. xo = 1; yo = 1;
  118. break;
  119. case 2:
  120. xo = 1; yo = 0;
  121. break;
  122. case 3:
  123. xo = 1; yo = -1;
  124. break;
  125. case 4:
  126. xo = 0; yo = -1;
  127. break;
  128. case 5:
  129. xo = -1; yo = -1;
  130. break;
  131. case 6:
  132. xo = -1; yo = 0;
  133. break;
  134. case 7:
  135. xo = -1; yo = 1;
  136. break;
  137. }
  138. for (i=1; i < 10; i++)
  139. {
  140. // out of bounds
  141. if (queens_x[queen] + xo*i > 9 ||
  142. queens_y[queen] + yo*i > 9 ||
  143. queens_x[queen] + xo*i < 0 ||
  144. queens_y[queen] + yo*i < 0)
  145. {
  146. // count obst
  147. for (adir = 0; adir < 8; adir++)
  148. {
  149. // for tightness not speed
  150. switch (adir)
  151. {
  152. case 0:
  153. axo = 0; ayo = 1;
  154. break;
  155. case 1:
  156. axo = 1; ayo = 1;
  157. break;
  158. case 2:
  159. axo = 1; ayo = 0;
  160. break;
  161. case 3:
  162. axo = 1; ayo = -1;
  163. break;
  164. case 4:
  165. axo = 0; ayo = -1;
  166. break;
  167. case 5:
  168. axo = -1; ayo = -1;
  169. break;
  170. case 6:
  171. axo = -1; ayo = 0;
  172. break;
  173. case 7:
  174. axo = -1; ayo = 1;
  175. break;
  176. }
  177. if (dir == adir) continue;
  178. for (j=1; j < 2; j++)
  179. {
  180. if (queens_x[queen] + axo*j > 9 ||
  181. queens_y[queen] + ayo*j > 9 ||
  182. queens_x[queen] + axo*j < 0 ||
  183. queens_y[queen] + ayo*j < 0)
  184. {
  185. break;
  186. }
  187. if (test(s, queens_x[queen]+axo*j,
  188. queens_y[queen]+ayo*j))
  189. {
  190. break;
  191. }
  192. m+=1;
  193. }
  194. }
  195. break;
  196. }
  197. // hit a wall
  198. if (test(s, queens_x[queen]+xo*i, queens_y[queen]+yo*i))
  199. {
  200. for (adir = 0; adir < 8; adir++)
  201. {
  202. // for tightness not speed
  203. switch (adir)
  204. {
  205. case 0:
  206. axo = 0; ayo = 1;
  207. break;
  208. case 1:
  209. axo = 1; ayo = 1;
  210. break;
  211. case 2:
  212. axo = 1; ayo = 0;
  213. break;
  214. case 3:
  215. axo = 1; ayo = -1;
  216. break;
  217. case 4:
  218. axo = 0; ayo = -1;
  219. break;
  220. case 5:
  221. axo = -1; ayo = -1;
  222. break;
  223. case 6:
  224. axo = -1; ayo = 0;
  225. break;
  226. case 7:
  227. axo = -1; ayo = 1;
  228. break;
  229. }
  230. //if (dir == adir) continue;
  231. if (dir == adir) continue;
  232. for (j=1; j < 2; j++)
  233. {
  234. if (queens_x[queen] + axo*j > 9 ||
  235. queens_y[queen] + ayo*j > 9 ||
  236. queens_x[queen] + axo*j < 0 ||
  237. queens_y[queen] + ayo*j < 0)
  238. {
  239. break;
  240. }
  241. if (test(s, queens_x[queen]+axo*j,
  242. queens_y[queen]+ayo*j))
  243. {
  244. break;
  245. }
  246. m+=1;
  247. }
  248. }
  249. break;
  250. }
  251. m+=2;
  252. /*
  253. xor(board, queens_x[queen], queens_y[queen]);
  254. queens_x[queen] += i*xo;
  255. queens_y[queen] += i*yo;
  256. xor(board, queens_x[queen], queens_y[queen]);
  257. // look for arrow moves.
  258. // order: N NE E SE S SW W NW
  259. xor(board, queens_x[queen], queens_y[queen]);
  260. queens_x[queen] -= i*xo;
  261. queens_y[queen] -= i*yo;
  262. xor(board, queens_x[queen], queens_y[queen]);
  263. */
  264. }
  265. }
  266. }
  267. return m;
  268. }
  269. // heuristic function
  270. int sean_heval(state *s)
  271. {
  272. int moves;
  273. int t1;
  274. int t2;
  275. int turn;
  276. turn = s->turn;
  277. s->turn = WHITE_PLAYER;
  278. t1 = countchildren(s);
  279. s->turn = BLACK_PLAYER;
  280. t2 = countchildren(s);
  281. s->turn = turn;
  282. moves = t1 - t2;
  283. return moves;
  284. }
  285. int countchildren(state *s)
  286. {
  287. int i,j;
  288. int m=0;
  289. int xo=0, yo=0;
  290. int axo=0, ayo=0;
  291. int dir, adir;
  292. int QUEENS;
  293. uchar *queens_x;
  294. uchar *queens_y;
  295. ull *board;
  296. int queen = 0;
  297. if(s->turn == WHITE_PLAYER)
  298. {
  299. queens_x = s->white_q_x;
  300. queens_y = s->white_q_y;
  301. board = s->white_bd;
  302. QUEENS = WHITEQUEENS;
  303. }
  304. else
  305. {
  306. queens_x = s->black_q_x;
  307. queens_y = s->black_q_y;
  308. board = s->black_bd;
  309. QUEENS = BLACKQUEENS;
  310. }
  311. // look for moves.
  312. // order: N NE E SE S SW W NW
  313. // this loop moves a queen, shoots an arrow, all the while
  314. // checking to see if its run into things.
  315. // populated movelist (passing in as reference) with the valid moves.
  316. for (queen = 0; queen < QUEENS; queen++)
  317. {
  318. for (dir = 0; dir < 8; dir++)
  319. {
  320. // for tightness not speed
  321. switch (dir)
  322. {
  323. case 0:
  324. xo = 0; yo = 1;
  325. break;
  326. case 1:
  327. xo = 1; yo = 1;
  328. break;
  329. case 2:
  330. xo = 1; yo = 0;
  331. break;
  332. case 3:
  333. xo = 1; yo = -1;
  334. break;
  335. case 4:
  336. xo = 0; yo = -1;
  337. break;
  338. case 5:
  339. xo = -1; yo = -1;
  340. break;
  341. case 6:
  342. xo = -1; yo = 0;
  343. break;
  344. case 7:
  345. xo = -1; yo = 1;
  346. break;
  347. }
  348. for (i=1; i < 10; i++)
  349. {
  350. // out of bounds
  351. if (queens_x[queen] + xo*i > 9 ||
  352. queens_y[queen] + yo*i > 9 ||
  353. queens_x[queen] + xo*i < 0 ||
  354. queens_y[queen] + yo*i < 0)
  355. {
  356. break;
  357. }
  358. // hit a wall
  359. if (test(s, queens_x[queen]+xo*i, queens_y[queen]+yo*i))
  360. {
  361. break;
  362. }
  363. xor(board, queens_x[queen], queens_y[queen]);
  364. queens_x[queen] += i*xo;
  365. queens_y[queen] += i*yo;
  366. xor(board, queens_x[queen], queens_y[queen]);
  367. // look for arrow moves.
  368. // order: N NE E SE S SW W NW
  369. for (adir = 0; adir < 8; adir++)
  370. {
  371. // for tightness not speed
  372. switch (adir)
  373. {
  374. case 0:
  375. axo = 0; ayo = 1;
  376. break;
  377. case 1:
  378. axo = 1; ayo = 1;
  379. break;
  380. case 2:
  381. axo = 1; ayo = 0;
  382. break;
  383. case 3:
  384. axo = 1; ayo = -1;
  385. break;
  386. case 4:
  387. axo = 0; ayo = -1;
  388. break;
  389. case 5:
  390. axo = -1; ayo = -1;
  391. break;
  392. case 6:
  393. axo = -1; ayo = 0;
  394. break;
  395. case 7:
  396. axo = -1; ayo = 1;
  397. break;
  398. }
  399. for (j=1; j < 10; j++)
  400. {
  401. if (queens_x[queen] + axo*j > 9 ||
  402. queens_y[queen] + ayo*j > 9 ||
  403. queens_x[queen] + axo*j < 0 ||
  404. queens_y[queen] + ayo*j < 0)
  405. {
  406. break;
  407. }
  408. if (test(s, queens_x[queen]+axo*j,
  409. queens_y[queen]+ayo*j))
  410. {
  411. break;
  412. }
  413. // put arrow
  414. m++;
  415. }
  416. }
  417. xor(board, queens_x[queen], queens_y[queen]);
  418. queens_x[queen] -= i*xo;
  419. queens_y[queen] -= i*yo;
  420. xor(board, queens_x[queen], queens_y[queen]);
  421. }
  422. }
  423. }
  424. return m;
  425. }
  426. // populates movelist[] with all possible moves.
  427. // returns the count of moves
  428. // the value of the move is also set here, that means
  429. // this is the function that calls heval (heuristic)
  430. // and tt_lookup (transposition table retrieve)
  431. int children(state *s, move movelist[])
  432. {
  433. int i,j;
  434. int m=0;
  435. int xo=0, yo=0;
  436. int axo=0, ayo=0;
  437. int dir, adir;
  438. int QUEENS;
  439. uchar *queens_x;
  440. uchar *queens_y;
  441. ull *board;
  442. int queen = 0;
  443. if(s->turn == WHITE_PLAYER)
  444. {
  445. queens_x = s->white_q_x;
  446. queens_y = s->white_q_y;
  447. board = s->white_bd;
  448. QUEENS = WHITEQUEENS;
  449. }
  450. else
  451. {
  452. queens_x = s->black_q_x;
  453. queens_y = s->black_q_y;
  454. board = s->black_bd;
  455. QUEENS = BLACKQUEENS;
  456. }
  457. // look for moves.
  458. // order: N NE E SE S SW W NW
  459. // this loop moves a queen, shoots an arrow, all the while
  460. // checking to see if its run into things.
  461. // populated movelist (passing in as reference) with the valid moves.
  462. for (queen = 0; queen < QUEENS; queen++)
  463. {
  464. for (dir = 0; dir < 8; dir++)
  465. {
  466. // for tightness not speed
  467. switch (dir)
  468. {
  469. case 0:
  470. xo = 0; yo = 1;
  471. break;
  472. case 1:
  473. xo = 1; yo = 1;
  474. break;
  475. case 2:
  476. xo = 1; yo = 0;
  477. break;
  478. case 3:
  479. xo = 1; yo = -1;
  480. break;
  481. case 4:
  482. xo = 0; yo = -1;
  483. break;
  484. case 5:
  485. xo = -1; yo = -1;
  486. break;
  487. case 6:
  488. xo = -1; yo = 0;
  489. break;
  490. case 7:
  491. xo = -1; yo = 1;
  492. break;
  493. }
  494. for (i=1; i < 10; i++)
  495. {
  496. // out of bounds
  497. if (queens_x[queen] + xo*i > 9 ||
  498. queens_y[queen] + yo*i > 9 ||
  499. queens_x[queen] + xo*i < 0 ||
  500. queens_y[queen] + yo*i < 0)
  501. {
  502. break;
  503. }
  504. // hit a wall
  505. if (test(s, queens_x[queen]+xo*i, queens_y[queen]+yo*i))
  506. {
  507. break;
  508. }
  509. xor(board, queens_x[queen], queens_y[queen]);
  510. queens_x[queen] += i*xo;
  511. queens_y[queen] += i*yo;
  512. xor(board, queens_x[queen], queens_y[queen]);
  513. // look for arrow moves.
  514. // order: N NE E SE S SW W NW
  515. for (adir = 0; adir < 8; adir++)
  516. {
  517. // for tightness not speed
  518. switch (adir)
  519. {
  520. case 0:
  521. axo = 0; ayo = 1;
  522. break;
  523. case 1:
  524. axo = 1; ayo = 1;
  525. break;
  526. case 2:
  527. axo = 1; ayo = 0;
  528. break;
  529. case 3:
  530. axo = 1; ayo = -1;
  531. break;
  532. case 4:
  533. axo = 0; ayo = -1;
  534. break;
  535. case 5:
  536. axo = -1; ayo = -1;
  537. break;
  538. case 6:
  539. axo = -1; ayo = 0;
  540. break;
  541. case 7:
  542. axo = -1; ayo = 1;
  543. break;
  544. }
  545. for (j=1; j < 10; j++)
  546. {
  547. if (queens_x[queen] + axo*j > 9 ||
  548. queens_y[queen] + ayo*j > 9 ||
  549. queens_x[queen] + axo*j < 0 ||
  550. queens_y[queen] + ayo*j < 0)
  551. {
  552. break;
  553. }
  554. if (test(s, queens_x[queen]+axo*j,
  555. queens_y[queen]+ayo*j))
  556. {
  557. break;
  558. }
  559. /*
  560. // put arrow
  561. xor(s->blocks_bd, queens_x[queen]+axo*j, queens_y[queen]+ayo*j);
  562. s->turn ^= 3;
  563. // printf("evaluating board:");
  564. // pboard(*s);
  565. if ((stt = tt_lookup(s)))
  566. {
  567. //tt_yes++;
  568. hits++;
  569. movelist[m].val = stt->value;
  570. movelist[m].depth = stt->depth;
  571. }
  572. else
  573. {
  574. //tt_no++;
  575. movelist[m].val = HEVAL(s);
  576. hevalz++;
  577. s->value = movelist[m].val;
  578. s->depth = 1;
  579. tt_store(s, SHRT_MIN, SHRT_MAX);
  580. }
  581. // remove arrow
  582. xor(s->blocks_bd, queens_x[queen]+axo*j, queens_y[queen]+ayo*j);
  583. s->turn ^= 3;
  584. */
  585. movelist[m].queen=queen;
  586. movelist[m].tocol=queens_x[queen];
  587. movelist[m].torow=queens_y[queen];
  588. movelist[m].wallcol=queens_x[queen]+axo*j;
  589. movelist[m].wallrow=queens_y[queen]+ayo*j;
  590. // pmove(movelist[m]);
  591. // printf("\n");
  592. m++;
  593. }
  594. }
  595. xor(board, queens_x[queen], queens_y[queen]);
  596. queens_x[queen] -= i*xo;
  597. queens_y[queen] -= i*yo;
  598. xor(board, queens_x[queen], queens_y[queen]);
  599. }
  600. }
  601. }
  602. return m;
  603. }
  604. // for qsort
  605. int mincompare(move *m1, move *m2) // USED BY MAXIMIZER
  606. {
  607. if (m1->val > m2->val)
  608. return -1;
  609. else if (m1->val < m2->val)
  610. return 1;
  611. return 0;
  612. }
  613. // for qsort
  614. int maxcompare(move *m1, move *m2)
  615. {
  616. if (m1->val < m2->val)
  617. return -1;
  618. else if (m1->val > m2->val)
  619. return 1;
  620. return 0;
  621. }
  622. // top level iterative search function. called from main, pretty
  623. // self explanatory
  624. move isearch(state *s, int think)
  625. {
  626. int i;
  627. move temp1, temp2;
  628. move even, odd;
  629. int temp2_valid = FALSE;
  630. even.val = 0;
  631. odd.val = 0;
  632. for (i=MINDEPTH; i <= options.engine.maxdepth; i++)
  633. {
  634. rawnodes = 0;
  635. nodes = 0;
  636. hits = 0;
  637. hevalz =0;
  638. temp1 = search(s, 0, SHRT_MIN, SHRT_MAX, i, think);
  639. /*
  640. // for mtdf NOT WORKING CURRENTLY
  641. if (i & 1)
  642. {
  643. temp1 = mtdf(s, odd.val, i);
  644. even = temp1;
  645. }
  646. else
  647. {
  648. temp1 = mtdf(s, even.val, i);
  649. odd = temp1;
  650. }
  651. */
  652. //printf("Searched to depth %d, %d cache hits of %d lookups. %d nodes searched.\n", i,hits,rawnodes, nodes);
  653. //printf("hevals = %d\n", hevalz);
  654. if (ok) // using this global ok is pretty sloppy but works.
  655. {
  656. temp2 = temp1;
  657. temp2_valid = TRUE;
  658. }
  659. else
  660. {
  661. if (think)
  662. {
  663. #ifdef DEBUG
  664. printf("searched %d nodes on your time\n", nodes);
  665. #endif
  666. }
  667. #ifdef DEBUG
  668. printf("time's up at depth %d\n", i);
  669. #endif
  670. break;
  671. }
  672. }
  673. if (temp2_valid)
  674. return temp2;
  675. else
  676. return temp1;
  677. }
  678. // NOT WORKING
  679. move mtdf(state *s, int guess, int tdepth)
  680. {
  681. move temp;
  682. //int f;
  683. int lowerbound = SHRT_MIN;
  684. int upperbound = SHRT_MAX;
  685. int beta;
  686. temp.val = guess;
  687. do
  688. {
  689. if (temp.val == lowerbound)
  690. {
  691. beta = temp.val + 1;
  692. }
  693. else
  694. {
  695. beta = temp.val;
  696. }
  697. //temp = search(s, 0, beta - 1, beta, tdepth, think);
  698. if (temp.val < beta)
  699. {
  700. upperbound = temp.val;
  701. }
  702. else
  703. {
  704. lowerbound = temp.val;
  705. }
  706. }
  707. while (!(lowerbound >= upperbound));
  708. return temp;
  709. }
  710. // minimax search.
  711. // tdepth is "target depth", that is the current iterative target level
  712. move search(state *s, int depth, int alpha, int beta, int tdepth, int think)
  713. {
  714. state_t *stt;
  715. move movelist[3000];
  716. int i;
  717. int index=0;
  718. move stemp;
  719. move temp;
  720. int randomizer;
  721. // int tt_yes=0;
  722. // int tt_no=0;
  723. int movecount;
  724. int done;
  725. nodes++;
  726. if ((time_t)time(NULL) - start > options.engine.timeout && TIMED && !think)
  727. {
  728. ok = 0;
  729. return movelist[0];
  730. }
  731. if (think)
  732. {
  733. if (poll(&pollstruct, 1, 0))
  734. {
  735. ok = 0;
  736. return movelist[0];
  737. }
  738. }
  739. movecount = children(s, movelist);
  740. if (movecount == 0) // no more moves
  741. {
  742. if (depth == 0)
  743. {
  744. #ifdef DEBUG
  745. printf("player %d wins!\n", s->turn^3);
  746. #endif
  747. s->winner = s->turn^3;
  748. if (options.print_statistics)
  749. print_stats();
  750. #ifndef GAMAZONS
  751. exit(1);
  752. #endif
  753. }
  754. // if no more moves, then set the value here to
  755. // a very high value plus/minus the depth
  756. // this ensure that the loser will select the longest path
  757. // to loss, and the winner will select the shortest path to
  758. // a win.
  759. movelist[0].val = MMSET(s->turn, depth);
  760. }
  761. // for node reordering, make sure everything has a value.
  762. for (i=0; i <movecount; i++)
  763. {
  764. #ifdef GAMAZONS
  765. //Make the game responsive while the AI is thinking
  766. while (gtk_events_pending())
  767. gtk_main_iteration();
  768. #endif
  769. temp = savemove(s, movelist[i]);
  770. makemove(s, movelist[i]);
  771. if ((stt = tt_lookup(s)))
  772. {
  773. if (alpha >= stt->alpha && beta <= stt->beta) // correct
  774. {
  775. hits++;
  776. movelist[i].val = stt->value;
  777. movelist[i].depth = stt->depth;
  778. }
  779. else
  780. {
  781. movelist[i].val = HEVAL(s);
  782. hevalz++;
  783. s->value = movelist[i].val;
  784. s->depth = 1;
  785. tt_update(s, SHRT_MIN, SHRT_MAX);
  786. }
  787. }
  788. else
  789. {
  790. movelist[i].val = HEVAL(s);
  791. hevalz++;
  792. s->value = movelist[i].val;
  793. s->depth = 1;
  794. tt_store(s, SHRT_MIN, SHRT_MAX);
  795. }
  796. undomove(s, temp);
  797. }
  798. rawnodes += movecount;
  799. // node reordering here.
  800. if (s->turn == WHITE_PLAYER)
  801. qsort(movelist, movecount, sizeof(move), (void*)mincompare);
  802. else
  803. qsort(movelist, movecount, sizeof(move), (void*)maxcompare);
  804. // this is the end of the line, return best move.
  805. if (depth+1 >= tdepth)
  806. return movelist[0];
  807. done = 0;
  808. for (i=0; i < movecount && !done && i < options.engine.maxdepth; i++)
  809. {
  810. // already searched farther than we will in the TT, just return it.
  811. if (movelist[i].depth > tdepth - depth)
  812. return movelist[i];
  813. temp = savemove(s, movelist[i]);
  814. makemove(s, movelist[i]);
  815. stemp = search(s, depth+1, alpha, beta, tdepth, think);
  816. if (ok)
  817. {
  818. // this should perhaps check if tt_lookup still works
  819. // not life changing
  820. if (tdepth-depth > movelist[i].depth)
  821. {
  822. s->value = stemp.val;
  823. s->depth = tdepth-depth;
  824. tt_update(s, alpha, beta);
  825. }
  826. movelist[i].val = stemp.val;
  827. undomove(s,temp); // undo move.
  828. }
  829. else // times up, return back up the tree as fast as possible.
  830. {
  831. undomove(s,temp); // undo move.
  832. return movelist[i];
  833. }
  834. nodes++;
  835. // alpha-beta stuff:
  836. if (s->turn == WHITE_PLAYER)
  837. {
  838. if (movelist[i].val > alpha)
  839. {
  840. alpha = movelist[i].val;
  841. index = i;
  842. }
  843. }
  844. else
  845. {
  846. if (movelist[i].val < beta)
  847. {
  848. beta = movelist[i].val;
  849. index = i;
  850. }
  851. }
  852. if (alpha >= beta)
  853. {
  854. done = 1;
  855. }
  856. }
  857. /* XXX
  858. printf("movelist index = %d\n", index);
  859. if (movecount > 3)
  860. {
  861. randomizer = rand() %3;
  862. printf("randomizer = %d\n", randomizer);
  863. }
  864. */
  865. return movelist[index];
  866. }
  867. // print out a longlong in binary
  868. int pvec(ull v)
  869. {
  870. int i;
  871. printf("->");
  872. for (i=49; i >= 0; i--)
  873. {
  874. printf("%d", (int)((v >> i) & (ull)1));
  875. if (i%10 == 0)
  876. printf(" ");
  877. }
  878. printf("<-\n");
  879. return 0;
  880. }
  881. // bring out a nice representation of the playing board
  882. int pboard(state s)
  883. {
  884. int board[12][12];
  885. int i,j;
  886. int row, col;
  887. // make the whole board blanks
  888. for (i=0; i < 12; i++)
  889. for (j=0; j < 12; j++)
  890. board[i][j] = '.';
  891. // place player1 queens
  892. for (i=0; i < WHITEQUEENS; i++)
  893. {
  894. col = s.white_q_x[i];
  895. row = s.white_q_y[i];
  896. if (options.white_player == HUMAN) board[col][row] = i+48;
  897. else board[col][row] = 'W';
  898. }
  899. // place player2 queens
  900. for (i=0; i < BLACKQUEENS; i++)
  901. {
  902. col = s.black_q_x[i];
  903. row = s.black_q_y[i];
  904. if (options.black_player == HUMAN) board[col][row] = i+48;
  905. else board[col][row] = 'B';
  906. }
  907. // put walls on the board
  908. //pvec(s.blocks_bd[1]);
  909. for (i=0; i < 50; i++)
  910. {
  911. if ((s.blocks_bd[1] >> i) & 1)
  912. {
  913. board[i%10][i/10+5] = 'x';
  914. }
  915. }
  916. //pvec(s.blocks_bd[0]);
  917. for (i=0; i < 50; i++)
  918. {
  919. if ((s.blocks_bd[0] >> i) & 1)
  920. {
  921. board[i%10][i/10] = 'x';
  922. }
  923. }
  924. printf("\n");
  925. // print out the board
  926. for (i=9; i >= 0; i--)
  927. {
  928. printf("%2d ", i);
  929. for (j=0; j < 10; j++)
  930. {
  931. printf(" %c", board[j][i]);
  932. }
  933. printf("\n");
  934. }
  935. printf(" a b c d e f g h i j\n");
  936. //printf(" 0 1 2 3 4 5 6 7 8 9\n");
  937. printf("\n");
  938. return 0;
  939. }
  940. /*==============================================================================
  941. * getmove
  942. *
  943. * Gets the move coordinates from stdin. Does lots of nice error checking on the
  944. * input, and makes sure the move was legal. If no moves are available, the human
  945. * must have lost, so the game ends.
  946. */
  947. move getmove(state *s, int player)
  948. {
  949. char tok;
  950. int done = FALSE;
  951. move movelist[3000];
  952. int move_count;
  953. move m;
  954. char move_str[10];
  955. int i;
  956. move_count = children(s, movelist);
  957. if (move_count == 0)
  958. {
  959. printf("Ha ha ha, you lose SUCKER!\n");
  960. s->winner = s->turn^3;
  961. #ifndef GAMAZONS
  962. exit(0);
  963. #endif
  964. }
  965. do
  966. {
  967. i = 0;
  968. printf("player %d's move.\n", player);
  969. printf("queen newcol newrow burncol burnrow (ex. \"0 c4 c1\")\n");
  970. printf("Move> ");
  971. fflush(stdout);
  972. ok = 1;
  973. isearch(s, THINK);
  974. tok = get_token();
  975. if (isdigit(tok))
  976. {
  977. m.queen = tok - '0';
  978. move_str[i++] = tok;
  979. move_str[i++] = ' ';
  980. }
  981. else
  982. {
  983. printf("%c is not a valid queen\n\n", tok);
  984. clear_buf();
  985. continue;
  986. }
  987. tok = get_token();
  988. if (isdigit(tok - '1')) //convert from alpha char to alpha num
  989. {
  990. m.tocol = tok - 'a';
  991. move_str[i++] = tok;
  992. }
  993. else
  994. {
  995. printf("%c is not a valid column\n\n", tok);
  996. clear_buf();
  997. continue;
  998. }
  999. tok = get_token();
  1000. if (isdigit(tok))
  1001. {
  1002. m.torow = tok - '0';
  1003. move_str[i++] = tok;
  1004. move_str[i++] = ' ';
  1005. }
  1006. else
  1007. {
  1008. printf("%c is not a valid row\n\n", tok);
  1009. clear_buf();
  1010. continue;
  1011. }
  1012. tok = get_token();
  1013. if (isdigit(tok - '1')) //convert from alpha char to alpha num
  1014. {
  1015. m.wallcol = tok - 'a';
  1016. move_str[i++] = tok;
  1017. }
  1018. else
  1019. {
  1020. printf("%c is not a valid column\n\n", tok);
  1021. clear_buf();
  1022. continue;
  1023. }
  1024. tok = get_token();
  1025. if (isdigit(tok))
  1026. {
  1027. m.wallrow = tok - '0';
  1028. move_str[i++] = tok;
  1029. }
  1030. else
  1031. {
  1032. printf("%c is not a valid row\n\n", tok);
  1033. clear_buf();
  1034. continue;
  1035. }
  1036. move_str[i] = '\0';
  1037. //make sure it's a valid move
  1038. if (!move_lookup(&m, movelist, move_count))
  1039. {
  1040. printf("%s is not a legal move\n", move_str);
  1041. continue;
  1042. }
  1043. //User input verified
  1044. done = TRUE;
  1045. }
  1046. while (done == FALSE);
  1047. return m;
  1048. }
  1049. /*==============================================================================
  1050. * get_token
  1051. *
  1052. * Retreives a token from stdin, ignores beginning whitespace.
  1053. */
  1054. char get_token()
  1055. {
  1056. char tok;
  1057. tok = getc(movin);
  1058. while (isspace(tok))
  1059. tok = getc(movin);
  1060. return tok;
  1061. }
  1062. /*==============================================================================
  1063. * clear_buf
  1064. *
  1065. * Clears chars in the stdin buffer all the way up to and including the carriage
  1066. * return.
  1067. */
  1068. void clear_buf()
  1069. {
  1070. while (getc(movin) != '\n');
  1071. }
  1072. /*==============================================================================
  1073. * move_lookup
  1074. *
  1075. * Compares a given move with a move with the moves in the given movelist. If it's
  1076. * found in the list, returns TRUE, otherwise returns FALSE.
  1077. */
  1078. int move_lookup(move *m, move movelist[], int move_count)
  1079. {
  1080. int i;
  1081. for (i=0; i<move_count; i++)
  1082. {
  1083. if (m->queen != movelist[i].queen)
  1084. continue;
  1085. if (m->tocol != movelist[i].tocol)
  1086. continue;
  1087. if (m->torow != movelist[i].torow)
  1088. continue;
  1089. if (m->wallcol != movelist[i].wallcol)
  1090. continue;
  1091. if (m->wallrow != movelist[i].wallrow)
  1092. continue;
  1093. else
  1094. {
  1095. return TRUE;
  1096. }
  1097. }
  1098. return FALSE;
  1099. }
  1100. // returns 1 if bit is set.
  1101. int test(state *s, uchar col, uchar row)
  1102. {
  1103. //printf("sigh %d %d\n", col, row);
  1104. if (row < 5)
  1105. {
  1106. if ( (s->blocks_bd[0] | s->white_bd[0] | s->black_bd[0] ) &
  1107. (ull)1 << ((row*10) + col))
  1108. return 1;
  1109. return 0;
  1110. }
  1111. else // row > 5
  1112. {
  1113. if ( (s->blocks_bd[1] | s->white_bd[1] | s->black_bd[1]) &
  1114. (ull)1 << ((((row-5)*10) + col)))
  1115. {
  1116. return 1;
  1117. }
  1118. return 0;
  1119. }
  1120. }
  1121. // xor bit at col,row
  1122. int xor(ull bd[2], uchar col, uchar row)
  1123. {
  1124. if (row < 5)
  1125. {
  1126. bd[0] ^= (ull)1 << ((row*10) + col);
  1127. }
  1128. else // row > 5
  1129. {
  1130. bd[1] ^= (ull)1 << ((((row-5)*10) + col));
  1131. }
  1132. return 1;
  1133. }
  1134. // takes a move that is to be made and returns a move that will
  1135. // undo it.
  1136. move savemove(state *s, move m)
  1137. {
  1138. move temp;
  1139. temp.wallcol = m.wallcol;
  1140. temp.wallrow = m.wallrow;
  1141. temp.queen = m.queen;
  1142. if (s->turn == WHITE_PLAYER)
  1143. {
  1144. temp.tocol = s->white_q_x[m.queen];
  1145. temp.torow = s->white_q_y[m.queen];
  1146. }
  1147. else
  1148. {
  1149. temp.tocol = s->black_q_x[m.queen];
  1150. temp.torow = s->black_q_y[m.queen];
  1151. }
  1152. return temp;
  1153. }
  1154. int undomove(state *s, move m)
  1155. {
  1156. s->turn ^= 3;
  1157. if (s->turn == WHITE_PLAYER)
  1158. {
  1159. xor(s->white_bd, s->white_q_x[m.queen], s->white_q_y[m.queen]);
  1160. s->white_q_x[m.queen] = m.tocol;
  1161. s->white_q_y[m.queen] = m.torow;
  1162. xor(s->white_bd, s->white_q_x[m.queen], s->white_q_y[m.queen]);
  1163. }
  1164. else
  1165. {
  1166. xor(s->black_bd, s->black_q_x[m.queen], s->black_q_y[m.queen]);
  1167. s->black_q_x[m.queen] = m.tocol;
  1168. s->black_q_y[m.queen] = m.torow;
  1169. xor(s->black_bd, s->black_q_x[m.queen], s->black_q_y[m.queen]);
  1170. }
  1171. xor(s->blocks_bd, m.wallcol, m.wallrow);
  1172. return 1;
  1173. }
  1174. // takes a move and does it.
  1175. int makemove(state *s, move m)
  1176. {
  1177. if (s->turn == WHITE_PLAYER)
  1178. {
  1179. //printf("registering move w/ engine for white\n");
  1180. xor(s->white_bd, s->white_q_x[m.queen], s->white_q_y[m.queen]);
  1181. s->white_q_x[m.queen] = m.tocol;
  1182. s->white_q_y[m.queen] = m.torow;
  1183. xor(s->white_bd, s->white_q_x[m.queen], s->white_q_y[m.queen]);
  1184. }
  1185. else
  1186. {
  1187. //printf("registering move w/ engine for black\n");
  1188. xor(s->black_bd, s->black_q_x[m.queen], s->black_q_y[m.queen]);
  1189. s->black_q_x[m.queen] = m.tocol;
  1190. s->black_q_y[m.queen] = m.torow;
  1191. xor(s->black_bd, s->black_q_x[m.queen], s->black_q_y[m.queen]);
  1192. }
  1193. xor(s->blocks_bd, m.wallcol, m.wallrow);
  1194. s->turn ^= 3;
  1195. return 1;
  1196. }
  1197. // print out a move struct
  1198. int pmove(move m)
  1199. {
  1200. printf("%d) %d -> %c%d ---> %c%d, val = %d\n", onmove,
  1201. m.queen, m.tocol+97, m.torow, m.wallcol+97, m.wallrow, m.val);
  1202. if (movin != stdin) // ?
  1203. {
  1204. fprintf(movout, "%d %c%d %c%d\n",
  1205. m.queen, m.tocol+97, m.torow, m.wallcol+97, m.wallrow);
  1206. fflush(movout);
  1207. fseek(movout,0,0);
  1208. //sleep(6);
  1209. }
  1210. return 0;
  1211. }
  1212. // set up the state
  1213. int init(state *s)
  1214. {
  1215. int i;
  1216. s->blocks_bd[0] = s->blocks_bd[1] = 0;
  1217. s->white_bd[0] = s->white_bd[1] = 0;
  1218. s->black_bd[0] = s->black_bd[1] = 0;
  1219. s->turn = WHITE_PLAYER;
  1220. for (i=0; i < 4; i++)
  1221. {
  1222. s->white_q_x[i] = 0;
  1223. s->white_q_y[i] = 0;
  1224. s->black_q_x[i] = 0;
  1225. s->black_q_y[i] = 0;
  1226. }
  1227. // some lines to trip things up
  1228. // xor(s->blocks_bd, 0,2);
  1229. // xor(s->blocks_bd, 1,2);
  1230. // xor(s->blocks_bd, 2,2);
  1231. // xor(s->blocks_bd, 3,2);
  1232. // xor(s->blocks_bd, 4,2);
  1233. // xor(s->blocks_bd, 5,2);
  1234. // xor(s->blocks_bd, 6,2);
  1235. // xor(s->blocks_bd, 7,2);
  1236. // xor(s->blocks_bd, 8,3);
  1237. // xor(s->blocks_bd, 9,2);
  1238. // place queen on the board
  1239. xor(s->white_bd, 6, 0);
  1240. s->white_q_x[0] = 6;
  1241. s->white_q_y[0] = 0;
  1242. xor(s->white_bd, 3, 0);
  1243. s->white_q_x[1] = 3;
  1244. s->white_q_y[1] = 0;
  1245. xor(s->white_bd, 0, 3);
  1246. s->white_q_x[2] = 0;
  1247. s->white_q_y[2] = 3;
  1248. xor(s->white_bd,9,3);
  1249. s->white_q_x[3] = 9;
  1250. s->white_q_y[3] = 3;
  1251. xor(s->black_bd, 3, 9);
  1252. s->black_q_x[0] = 3;
  1253. s->black_q_y[0] = 9;
  1254. xor(s->black_bd, 6, 9);
  1255. s->black_q_x[1] = 6;
  1256. s->black_q_y[1] = 9;
  1257. xor(s->black_bd, 0, 6);
  1258. s->black_q_x[2] = 0;
  1259. s->black_q_y[2] = 6;
  1260. xor(s->black_bd,9,6);
  1261. s->black_q_x[3] = 9;
  1262. s->black_q_y[3] = 6;
  1263. return 0;
  1264. }
  1265. int meta_init()
  1266. {
  1267. if (!movin)
  1268. {
  1269. #ifdef DEBUG
  1270. printf("not using fifos\n");
  1271. #endif
  1272. movin = stdin;
  1273. movout = stdout;
  1274. }
  1275. pollstruct.fd = fileno(movin);
  1276. pollstruct.events = POLLIN;
  1277. pollstruct.revents = 0;
  1278. return 1;
  1279. }
  1280. // test init function, used to set up potentially interesting
  1281. // board states. Change call in main of init to x_init to put into
  1282. // action.
  1283. int x_init(state *s)
  1284. {
  1285. int i;
  1286. s->blocks_bd[0] = s->blocks_bd[1] = 0;
  1287. s->white_bd[0] = s->white_bd[1] = 0;
  1288. s->black_bd[0] = s->black_bd[1] = 0;
  1289. s->turn = WHITE_PLAYER;
  1290. for (i=0; i < 4; i++)
  1291. {
  1292. s->white_q_x[i] = 0;
  1293. s->white_q_y[i] = 0;
  1294. s->black_q_x[i] = 0;
  1295. s->black_q_y[i] = 0;
  1296. }
  1297. // place queen on the board
  1298. xor(s->white_bd, 0, 0);
  1299. s->white_q_x[0] = 0;
  1300. s->white_q_y[0] = 0;
  1301. xor(s->white_bd, 1, 0);
  1302. s->white_q_x[1] = 1;
  1303. s->white_q_y[1] = 0;
  1304. xor(s->white_bd, 0, 1);
  1305. s->white_q_x[2] = 0;
  1306. s->white_q_y[2] = 1;
  1307. xor(s->white_bd, 6, 0);
  1308. s->white_q_x[3] = 6;
  1309. s->white_q_y[3] = 0;
  1310. xor(s->black_bd, 8, 0);
  1311. s->black_q_x[0] = 8;
  1312. s->black_q_y[0] = 0;
  1313. xor(s->black_bd, 2, 0);
  1314. s->black_q_x[1] = 2;
  1315. s->black_q_y[1] = 0;
  1316. xor(s->black_bd, 2, 1);
  1317. s->black_q_x[2] = 2;
  1318. s->black_q_y[2] = 1;
  1319. xor(s->black_bd, 2, 2);
  1320. s->black_q_x[3] = 2;
  1321. s->black_q_y[3] = 2;
  1322. /*
  1323. xor(s->blocks_bd, 1,1);
  1324. xor(s->blocks_bd, 1,2);
  1325. xor(s->blocks_bd, 0,2);
  1326. */
  1327. xor(s->blocks_bd, 3,0);
  1328. xor(s->blocks_bd, 3,1);
  1329. xor(s->blocks_bd, 3,2);
  1330. xor(s->blocks_bd, 3,3);
  1331. xor(s->blocks_bd, 0,3);
  1332. xor(s->blocks_bd, 1,3);
  1333. xor(s->blocks_bd, 2,3);
  1334. xor(s->blocks_bd, 4,3);
  1335. xor(s->blocks_bd, 4,4);
  1336. xor(s->blocks_bd, 5,4);
  1337. xor(s->blocks_bd, 6,4);
  1338. xor(s->blocks_bd, 7,4);
  1339. xor(s->blocks_bd, 8,4);
  1340. xor(s->blocks_bd, 9,4);
  1341. /*
  1342. xor(s->blocks_bd, 4,2);
  1343. xor(s->blocks_bd, 5,2);
  1344. xor(s->blocks_bd, 6,2);
  1345. xor(s->blocks_bd, 7,2);
  1346. xor(s->blocks_bd, 8,2);
  1347. xor(s->blocks_bd, 9,2);
  1348. */
  1349. /*
  1350. xor(s->blocks_bd, 4,0);
  1351. xor(s->blocks_bd, 4,1);
  1352. xor(s->blocks_bd, 5,0);
  1353. xor(s->blocks_bd, 5,1);
  1354. */
  1355. /*
  1356. xor(s->blocks_bd, 5,0);
  1357. xor(s->blocks_bd, 5,1);
  1358. xor(s->blocks_bd, 6,1);
  1359. xor(s->blocks_bd, 7,0);
  1360. xor(s->blocks_bd, 7,1);
  1361. xor(s->blocks_bd, 8,1);
  1362. xor(s->blocks_bd, 9,1);
  1363. xor(s->blocks_bd, 9,0);
  1364. */
  1365. return 0;
  1366. }
  1367. #ifndef GAMAZONS
  1368. /*==============================================================================
  1369. * main
  1370. *
  1371. *
  1372. */
  1373. int main(int argc, char *argv[])
  1374. {
  1375. state *s;
  1376. //struct move m;
  1377. move temp;
  1378. int i;
  1379. // Initialize game states
  1380. for (i=0; i<100; i++)
  1381. states.s[i] = (state *) malloc(sizeof(state));
  1382. states.current_state = 0;
  1383. states.max_state = 0;
  1384. s = states.s[0];
  1385. parse_args(argc, argv);
  1386. meta_init();
  1387. init(s);
  1388. printf("size of move = %d\n", sizeof(move));
  1389. printf("size of state = %d\n", sizeof(state));
  1390. pboard(*s);
  1391. //test_fdiag(s);
  1392. //test_bdiag(s);
  1393. //test_gen_web_stream(s);
  1394. //test_put_col(s);
  1395. //test_put_row(s);
  1396. //test_put_fdiag(s);
  1397. //test_put_bdiag(s);
  1398. #ifdef DEBUG_HEVAL
  1399. xor(s->white_bd, 9, 3);
  1400. xor(s->white_bd, 8, 2);
  1401. s->white_q_x[3] = 8;
  1402. s->white_q_y[3] = 2;
  1403. xor(s->blocks_bd, 8, 3);
  1404. s->turn = BLACK_PLAYER;
  1405. pboard(*s);
  1406. printf("board value is %d\n", HEVAL(s));
  1407. pbvec(s->white_bd[0], s->white_bd[1]);
  1408. #endif
  1409. #ifndef DEBUG_HEVAL
  1410. /* the main play loop. Gets a move, does a move, repeats.
  1411. lobal ok is set to 1 for use with timeouts
  1412. */
  1413. for (;;)
  1414. {
  1415. dup_state(s, states.s[++(states.current_state)]);
  1416. s = states.s[states.current_state];
  1417. if (states.current_state > states.max_state)
  1418. states.max_state = states.current_state;
  1419. if (options.white_player == HUMAN)
  1420. {
  1421. temp = getmove(s, 1);
  1422. makemove(s, temp);
  1423. onmove++;
  1424. pboard(*s);
  1425. }
  1426. else
  1427. {
  1428. ok = 1;
  1429. start = time(NULL);
  1430. temp = isearch(s, NOTHINK);
  1431. printf("WHITE selected: ");
  1432. pmove(temp);
  1433. makemove(s,temp);
  1434. onmove++;
  1435. pboard(*s);
  1436. }
  1437. dup_state(s, states.s[++(states.current_state)]);
  1438. s = states.s[states.current_state];
  1439. if (states.current_state > states.max_state)
  1440. states.max_state = states.current_state;
  1441. if (options.black_player == HUMAN)
  1442. {
  1443. temp = getmove(s, 2);
  1444. makemove(s, temp);
  1445. onmove++;
  1446. pboard(*s);
  1447. }
  1448. else
  1449. {
  1450. ok = 1;
  1451. start = time(NULL);
  1452. temp = isearch(s, NOTHINK);
  1453. printf("BLACK selected: ");
  1454. pmove(temp);
  1455. makemove(s,temp);
  1456. onmove++;
  1457. pboard(*s);
  1458. }
  1459. }
  1460. #endif
  1461. return 0;
  1462. }
  1463. #endif //ifndef GAMAZONS
  1464. #ifdef GAMAZONS
  1465. /*==============================================================================
  1466. * init_engine
  1467. *
  1468. *
  1469. *
  1470. */
  1471. void init_engine()
  1472. {
  1473. state *s;
  1474. //struct move m;
  1475. move temp;
  1476. int i;
  1477. char *home_env;
  1478. srand(time(NULL));
  1479. // Initialize game states
  1480. for (i=0; i<100; i++)
  1481. states.s[i] = (state *) malloc(sizeof(state));
  1482. states.current_state = 0;
  1483. states.max_state = 0;
  1484. s = states.s[0];
  1485. s->turn = WHITE_PLAYER;
  1486. s->winner = 0;
  1487. state_hash = create_hash(s);
  1488. meta_init();
  1489. init(s);
  1490. dup_state(s, states.s[++(states.current_state)]);
  1491. /* set default options */
  1492. options.engine.maxdepth=20;
  1493. options.engine.maxwidth=3000;
  1494. options.engine.timeout=1;
  1495. options.white_player=HUMAN;
  1496. options.black_player=HUMAN;
  1497. options.print_statistics=FALSE;
  1498. home_env = getenv("HOME");
  1499. strcpy(options.hist_dir, home_env);
  1500. strcat(options.hist_dir, "/");
  1501. if (!load_images_from_theme(PACKAGE_DATA_DIR "/gamazons/default.theme"))
  1502. {
  1503. fprintf(stderr, "Cannot find theme file %s\n", PACKAGE_DATA_DIR "/gamazons/default.theme");
  1504. exit(1);
  1505. }
  1506. #ifdef DEBUG
  1507. printf("white piece image = %s\n", options.images.white_piece);
  1508. #endif
  1509. load_values_from_file();
  1510. }
  1511. /*==============================================================================
  1512. * load_values_from_file
  1513. *
  1514. * If a .gamazons file is found in the user's home directory, it will attempt to
  1515. * load the values stored therein. Any variables it doesn't recognize will be
  1516. * silently ignored.
  1517. */
  1518. void load_values_from_file()
  1519. {
  1520. char *home, file[256];
  1521. FILE *rc_fd;
  1522. char variable[256];
  1523. char buffer[256];
  1524. int value;
  1525. char ch;
  1526. if (!(home = getenv("HOME")))
  1527. return;
  1528. strcpy(file, home);
  1529. strcat(file, "/.gamazons");
  1530. #ifdef DEBUG
  1531. printf("looking for the file %s\n", file);
  1532. #endif
  1533. rc_fd = fopen(file, "r");
  1534. if(rc_fd == NULL)
  1535. return;
  1536. while (fscanf(rc_fd, "%s", variable) != EOF)
  1537. {
  1538. while (ch = fgetc(rc_fd))
  1539. {
  1540. if (ch == EOF)
  1541. return;
  1542. if (ch == '=')
  1543. break;
  1544. }
  1545. if (strcmp(variable, "WHITE_PLAYER") == 0)
  1546. {
  1547. fscanf(rc_fd, "%d", &value);
  1548. options.white_player = value;
  1549. }
  1550. else if (strcmp(variable, "BLACK_PLAYER") == 0)
  1551. {
  1552. fscanf(rc_fd, "%d", &value);
  1553. options.black_player = value;
  1554. }
  1555. else if (strcmp(variable, "TIMEOUT") == 0)
  1556. {
  1557. fscanf(rc_fd, "%d", &value);
  1558. if (value > 0)
  1559. options.engine.timeout = value;
  1560. else
  1561. options.engine.timeout = 1;
  1562. }
  1563. else if (strcmp(variable, "MAXWIDTH") == 0)
  1564. {
  1565. fscanf(rc_fd, "%d", &value);
  1566. if (value > 0)
  1567. options.engine.maxwidth = value;
  1568. else
  1569. options.engine.maxwidth = 1;
  1570. }
  1571. else if (strcmp(variable, "MAXDEPTH") == 0)
  1572. {
  1573. fscanf(rc_fd, "%d", &value);
  1574. if (value > 0)
  1575. options.engine.maxdepth = value;
  1576. else
  1577. options.engine.maxdepth = 1;
  1578. }
  1579. else if (strcmp(variable, "REPLAY_DELAY") == 0)
  1580. {
  1581. fscanf(rc_fd, "%d", &value);
  1582. if (value > 0)
  1583. options.replay_delay = value;
  1584. else
  1585. options.replay_delay = 1;
  1586. }
  1587. else if (strcmp(variable, "MOVEMENT_SPEED") == 0)
  1588. {
  1589. fscanf(rc_fd, "%d", &value);
  1590. if (value > 0 && value <= 10)
  1591. options.movement_speed = value;
  1592. else
  1593. options.movement_speed = 1;
  1594. }
  1595. else if (strcmp(variable, "WHITE_PIECE") == 0)
  1596. {
  1597. fscanf(rc_fd, "%s", buffer);
  1598. strcpy(options.images.white_piece, buffer);
  1599. }
  1600. else if (strcmp(variable, "BLACK_PIECE") == 0)
  1601. {
  1602. fscanf(rc_fd, "%s", buffer);
  1603. strcpy(options.images.black_piece, buffer);
  1604. }
  1605. else if (strcmp(variable, "WHITE_SQUARE") == 0)
  1606. {
  1607. fscanf(rc_fd, "%s", buffer);
  1608. strcpy(options.images.white_sq, buffer);
  1609. }
  1610. else if (strcmp(variable, "GREY_SQUARE") == 0)
  1611. {
  1612. fscanf(rc_fd, "%s", buffer);
  1613. strcpy(options.images.grey_sq, buffer);
  1614. }
  1615. else if (strcmp(variable, "ARROW_SQUARE") == 0)
  1616. {
  1617. fscanf(rc_fd, "%s", buffer);
  1618. strcpy(options.images.arrow_sq, buffer);
  1619. }
  1620. else if (strcmp(variable, "HIST_DIR") == 0)
  1621. {
  1622. fscanf(rc_fd, "%s", buffer);
  1623. strcpy(options.hist_dir, buffer);
  1624. }
  1625. else if (strcmp(variable, "DRAW_GRID") == 0)
  1626. {
  1627. fscanf(rc_fd, "%s", buffer);
  1628. if (strcmp(buffer, "TRUE") == 0)
  1629. options.images.grid = TRUE;
  1630. else
  1631. options.images.grid = FALSE;
  1632. }
  1633. }
  1634. fclose(rc_fd);
  1635. }
  1636. /*==============================================================================
  1637. * store_values_in_file
  1638. *
  1639. * Creates/overwrites a .gamazons file in the user's home directory. Stores
  1640. * the values in the options struct in it.
  1641. */
  1642. void store_values_in_file()
  1643. {
  1644. char *home, file[256];
  1645. FILE *rc_fd;
  1646. #ifdef GAMAZONS
  1647. GtkWidget *delay = (GtkWidget *)lookup_widget(main_window, "ReplayDelaySpinner");
  1648. GtkWidget *speed = (GtkWidget *)lookup_widget(main_window, "MovementSpeedSpinner");
  1649. #endif
  1650. if (!(home = getenv("HOME")))
  1651. return;
  1652. strcpy(file, home);
  1653. strcat(file, "/.gamazons");
  1654. #ifdef DEBUG
  1655. printf("looking for the file %s\n", file);
  1656. #endif
  1657. rc_fd = fopen(file, "w");
  1658. if (rc_fd == NULL)
  1659. return;
  1660. fprintf(rc_fd, "WHITE_PLAYER = ");
  1661. fprintf(rc_fd, "%d\n", options.white_player);
  1662. fprintf(rc_fd, "BLACK_PLAYER = ");
  1663. fprintf(rc_fd, "%d\n", options.black_player);
  1664. fprintf(rc_fd, "TIMEOUT = ");
  1665. fprintf(rc_fd, "%d\n", options.engine.timeout);
  1666. fprintf(rc_fd, "MAXWIDTH = ");
  1667. fprintf(rc_fd, "%d\n", options.engine.maxwidth);
  1668. fprintf(rc_fd, "MAXDEPTH = ");
  1669. fprintf(rc_fd, "%d\n", options.engine.maxdepth);
  1670. fprintf(rc_fd, "WHITE_PIECE = ");
  1671. fprintf(rc_fd, "%s\n", options.images.white_piece);
  1672. fprintf(rc_fd, "BLACK_PIECE = ");
  1673. fprintf(rc_fd, "%s\n", options.images.black_piece);
  1674. fprintf(rc_fd, "WHITE_SQUARE = ");
  1675. fprintf(rc_fd, "%s\n", options.images.white_sq);
  1676. fprintf(rc_fd, "GREY_SQUARE = ");
  1677. fprintf(rc_fd, "%s\n", options.images.grey_sq);
  1678. fprintf(rc_fd, "ARROW_SQUARE = ");
  1679. fprintf(rc_fd, "%s\n", options.images.arrow_sq);
  1680. fprintf(rc_fd, "HIST_DIR = ");
  1681. fprintf(rc_fd, "%s\n", options.hist_dir);
  1682. fprintf(rc_fd, "DRAW_GRID = ");
  1683. if (options.images.grid == TRUE)
  1684. fprintf(rc_fd, "%s\n", "TRUE");
  1685. else
  1686. fprintf(rc_fd, "%s\n", "FALSE");
  1687. #ifdef GAMAZONS
  1688. fprintf(rc_fd, "REPLAY_DELAY = ");
  1689. options.replay_delay = gtk_spin_button_get_value_as_int((GtkSpinButton *)delay);
  1690. fprintf(rc_fd, "%d\n", options.replay_delay);
  1691. fprintf(rc_fd, "MOVEMENT_SPEED = ");
  1692. options.movement_speed = gtk_spin_button_get_value_as_int((GtkSpinButton *)speed);
  1693. fprintf(rc_fd, "%d\n", options.movement_speed);
  1694. #endif
  1695. fclose(rc_fd);
  1696. }
  1697. /*==============================================================================
  1698. * load_images_from_theme
  1699. *
  1700. * This file will read image paths from a theme file. These values get loaded
  1701. * into the options struct, and subsequently used to draw the board.
  1702. */
  1703. int load_images_from_theme(char *theme)
  1704. {
  1705. char *home, file[256];
  1706. FILE *theme_fd;
  1707. char variable[256];
  1708. char buffer[256];
  1709. int value;
  1710. char ch;
  1711. theme_fd = fopen(theme, "r");
  1712. if(theme_fd == NULL)
  1713. {
  1714. fprintf(stderr, "Can't open theme file %s\n", theme);
  1715. return FALSE;
  1716. }
  1717. while (fscanf(theme_fd, "%s", variable) != EOF)
  1718. {
  1719. while (ch = fgetc(theme_fd))
  1720. {
  1721. if (ch == EOF)
  1722. return TRUE;
  1723. if (ch == '=')
  1724. break;
  1725. }
  1726. if (strcmp(variable, "WHITE_PIECE") == 0)
  1727. {
  1728. fscanf(theme_fd, "%s", buffer);
  1729. strcpy(options.images.white_piece, PACKAGE_DATA_DIR "/pixmaps/gamazons/");
  1730. strcat(options.images.white_piece, buffer);
  1731. }
  1732. else if (strcmp(variable, "BLACK_PIECE") == 0)
  1733. {
  1734. fscanf(theme_fd, "%s", buffer);
  1735. strcpy(options.images.black_piece, PACKAGE_DATA_DIR "/pixmaps/gamazons/");
  1736. strcat(options.images.black_piece, buffer);
  1737. }
  1738. else if (strcmp(variable, "WHITE_SQUARE") == 0)
  1739. {
  1740. fscanf(theme_fd, "%s", buffer);
  1741. strcpy(options.images.white_sq, PACKAGE_DATA_DIR "/pixmaps/gamazons/");
  1742. strcat(options.images.white_sq, buffer);
  1743. }
  1744. else if (strcmp(variable, "GREY_SQUARE") == 0)
  1745. {
  1746. fscanf(theme_fd, "%s", buffer);
  1747. strcpy(options.images.grey_sq, PACKAGE_DATA_DIR "/pixmaps/gamazons/");
  1748. strcat(options.images.grey_sq, buffer);
  1749. }
  1750. else if (strcmp(variable, "ARROW_SQUARE") == 0)
  1751. {
  1752. fscanf(theme_fd, "%s", buffer);
  1753. strcpy(options.images.arrow_sq, PACKAGE_DATA_DIR "/pixmaps/gamazons/");
  1754. strcat(options.images.arrow_sq, buffer);
  1755. }
  1756. else if (strcmp(variable, "DRAW_GRID") == 0)
  1757. {
  1758. fscanf(theme_fd, "%s", buffer);
  1759. if (strcmp(buffer, "TRUE") == 0)
  1760. options.images.grid = TRUE;
  1761. else
  1762. options.images.grid = FALSE;
  1763. }
  1764. }
  1765. fclose(theme_fd);
  1766. return TRUE;
  1767. }
  1768. #endif
  1769. /*==============================================================================
  1770. * print_usage_menu
  1771. *
  1772. * Displays a list of all command line options
  1773. */
  1774. void print_usage_menu()
  1775. {
  1776. printf("Amazons Usage:\n");
  1777. printf("amazons [OPTIONS]\n");
  1778. printf(" -d #: Sets the maximum search depth\n");
  1779. printf(" -h: Prints this help menu\n");
  1780. printf(" -p #: User plays against the computer (1 white, 2 black)\n");
  1781. printf(" -s: Prints out interesting statistics\n");
  1782. printf(" -t #: Sets the time limit between moves\n");
  1783. printf("\n\n");
  1784. }
  1785. /* parse args
  1786. *
  1787. * Handles the arguments passed into the program.
  1788. *
  1789. * Note: this expects all arguments to be listed separately,
  1790. * each with it's own '-'
  1791. */
  1792. void parse_args(int argc, char *argv[])
  1793. {
  1794. int i = 1;
  1795. //Set defaults
  1796. options.engine.maxdepth=20;
  1797. options.engine.maxwidth=5000;
  1798. options.engine.timeout=2;
  1799. options.white_player=HUMAN;
  1800. options.black_player=AI;
  1801. options.print_statistics=FALSE;
  1802. while (i < argc)
  1803. {
  1804. switch(argv[i][1])
  1805. {
  1806. case 'd':
  1807. options.engine.maxdepth = atoi(argv[++i]);
  1808. i++;
  1809. break;
  1810. case 'h':
  1811. print_usage_menu();
  1812. exit(0);
  1813. case 'p':
  1814. if (atoi(argv[++i]) == 1)
  1815. options.white_player = HUMAN;
  1816. else
  1817. options.black_player = HUMAN;
  1818. i++;
  1819. break;
  1820. case 'f':
  1821. #ifdef DEBUG
  1822. printf("opening movin\n");
  1823. #endif
  1824. movin = fopen(argv[++i], "r+");
  1825. #ifdef DEBUG
  1826. printf("success\n");
  1827. printf("opening movout\n");
  1828. #endif
  1829. movout = fopen(argv[++i], "r+");
  1830. #ifdef DEBUG
  1831. printf("success\n");
  1832. #endif
  1833. //fprintf(fifop, "wubba wubba\n");
  1834. //fflush(fifop);
  1835. //printf("open success\n");
  1836. i++;
  1837. break;
  1838. case 's':
  1839. options.print_statistics = TRUE;
  1840. i++;
  1841. break;
  1842. case 't':
  1843. options.engine.timeout = atoi(argv[++i]);
  1844. i++;
  1845. break;
  1846. case 'w':
  1847. options.engine.maxdepth = atoi(argv[++i]);
  1848. i++;
  1849. break;
  1850. default:
  1851. printf("Unknown argument %s\n", argv[i]);
  1852. print_usage_menu();
  1853. exit(1);
  1854. }
  1855. }
  1856. }
  1857. void print_stats()
  1858. {
  1859. printf("TT Stats:\n");
  1860. printf(" # nodes over written: %d\n", tt_overwrite);
  1861. printf(" # of nodes stored: %d\n", tt_stores);
  1862. printf(" # of updates made: %d\n", tt_updates);
  1863. printf(" # of lookups made: %d\n", tt_lookups);
  1864. printf(" # of lookups found: %d\n", tt_lookup_finds);
  1865. printf("\n");
  1866. printf("Heuristic Stats:\n");
  1867. printf(" # of heuristic calls %d\n", heval_calls);
  1868. }
  1869. void dup_state(state *s_old, state *s_new)
  1870. {
  1871. int i;
  1872. s_new->white_bd[0] = s_old->white_bd[0];
  1873. s_new->white_bd[1] = s_old->white_bd[1];
  1874. s_new->blocks_bd[0] = s_old->blocks_bd[0];
  1875. s_new->blocks_bd[1] = s_old->blocks_bd[1];
  1876. s_new->black_bd[0] = s_old->black_bd[0];
  1877. s_new->black_bd[1] = s_old->black_bd[1];
  1878. for (i=0; i<4; i++)
  1879. {
  1880. s_new->white_q_x[i] = s_old->white_q_x[i];
  1881. s_new->black_q_x[i] = s_old->black_q_x[i];
  1882. s_new->white_q_y[i] = s_old->white_q_y[i];
  1883. s_new->black_q_y[i] = s_old->black_q_y[i];
  1884. }
  1885. s_new->turn = s_old->turn;
  1886. #ifdef DEBUG
  1887. printf("old turn is %d, new turn is %d\n", s_old->turn, s_new->turn);
  1888. #endif
  1889. s_new->value = s_old->value;
  1890. s_new->depth = s_old->depth;
  1891. s_new->winner = s_old->winner;
  1892. }