home *** CD-ROM | disk | FTP | other *** search
/ ticalc.org / ticalc_org_rev_b.iso / archives / 85 / asm / source / usgard / stones.c < prev   
Encoding:
C/C++ Source or Header  |  2001-07-01  |  9.8 KB  |  490 lines

  1. #name "DewSoft Stones v1.0"
  2. /*
  3.    This file is copyright 1997 by Jeremy Dewey.
  4. */
  5.  
  6. #include "usglib.h"
  7. #include "lib\tabline.c"
  8. #include "lib\sprite.c"
  9. #include "lib\sprite_x.c"
  10. #include "lib\rand.c"
  11. #include "lib\disp_dec.c"
  12.  
  13. #define true 1
  14. #define false 0
  15.  
  16. #define P_BLOCK 25
  17. #define P_HUMAN -10
  18. #define P_CPU 10
  19.  
  20. /* Sprites - actual data at end of file */
  21. extern char icon_h[], icon_hi[], icon_c[], icon_ci[], icon_sq[];
  22. extern char wait_L1[], wait_0[], icon_0[], icon_b[], square[];
  23. /* Various pointers */
  24. char *brd, *newbrd, *p_wait, i_wait;
  25. /* Human's current cursor position */
  26. int cx, cy;
  27. /* Current scores */
  28. char numci, numc, numhi, numh, nummt;
  29. char onumci, onumc, onumhi, onumh;
  30. extern char* _frstmem(0x8b27);
  31.  
  32. main() {
  33.    char i;
  34.    i_wait = 0;
  35.    cx = 8;
  36.    cy = 5;
  37.  
  38.    // To allocate board space, this game requires 352 bytes free
  39.    brd = _frstmem;
  40.    newbrd = _frstmem + 176;
  41.  
  42.    while (true) {
  43.       clrscr;
  44.       //graphpage(); - Usgard now does this automatically
  45.       tabline("Stones v1.0");
  46.       /* Print my name */
  47.       my_name();
  48.  
  49.       /* Draw message window */
  50.       vline(9,63,92);
  51.  
  52.       /* Populate message window */
  53.       setxy_m(100,8);
  54.       puts_m("Human");
  55.       for (i=9;i<15;i++) hline(93,127,i);
  56.       setxy_m(103,15);
  57.       puts_m("0 ");
  58.       sprite(icon_h,_menu_x, 16,5,5);
  59.       setxy_m(103,21);
  60.       puts_m("0 ");
  61.       sprite(icon_hi,_menu_x, 22,5,5);
  62.       setxy_m(103,27);
  63.       puts_m("0 Total");
  64.  
  65.       setxy_m(95,36);
  66.       puts_m("CPU stats");
  67.       for (i=36;i<43;i++) hline(93,127,i);
  68.       setxy_m(103,43);
  69.       puts_m("0 ");
  70.       sprite(icon_c,_menu_x, 44,5,5);
  71.       setxy_m(103,49);
  72.       puts_m("0 ");
  73.       sprite(icon_ci,_menu_x, 50,5,5);
  74.       setxy_m(103,55);
  75.       puts_m("0 Total");
  76.  
  77.       // Check for amount of free memory
  78.       if (free_mem() < 352) {
  79.          setxy_m(4,10);
  80.          puts_m("Stones requires 352 bytes");
  81.          setxy_m(20,16);
  82.          puts_m("of free memory");
  83.          getkey();
  84.          _exit();
  85.       }
  86.       init_brd();
  87.       draw_brd();
  88.       // Change the text at the top of the screen
  89.       play();
  90.       my_name();
  91.       game_over();
  92.       if (getkey() == K_EXIT) _exit();
  93.       // Change the text back
  94.       game_over();
  95.       my_name();
  96.    }
  97. }
  98.  
  99. free_mem() {
  100.    asm("   call FREEMEM\n");
  101. }
  102.  
  103. my_name() {
  104.    setxy_m(70, 1);
  105.    puts_m("by Jeremy Dewey");
  106. }
  107.  
  108. game_over() {
  109.    setxy_m(50,1);
  110.    puts_m("Game Over - press a key");
  111. }
  112.  
  113. /* Run the game until there are no more empty spaces with cookie jars */
  114.  
  115. play() {
  116.    nummt=1;
  117.    while (nummt) {
  118.       if (human()) return; // If human() returns 1, exit game early
  119.       draw_brd();
  120.       if (nummt) {
  121.          cpu();
  122.          draw_brd();
  123.       }
  124.    }
  125. }
  126.  
  127. /* Wait cursor */
  128.  
  129. waitcycl() {
  130.    p_wait = wait_L1 + i_wait * 10;
  131.    sprite(p_wait  ,48,2,8,5);
  132.    sprite(p_wait+5,56,2,8,5);
  133.    if (++i_wait >=4) i_wait=0;
  134. }
  135.  
  136. waitoff() {
  137.    sprite(wait_0, 48,2,8,5);
  138.    sprite(wait_0, 56,2,8,5);
  139. }
  140.  
  141. /* Initialize the board (with blocks surrounding the visible area */
  142.  
  143. init_brd() {
  144.    int x,y,b;
  145.  
  146.    for(y=0;y<11;y++) {
  147.       /*waitcycl();*/
  148.       for(x=0;x<16;x++) {
  149.          b = bindex(x,y);
  150.          if (!x || x==15 || !y || y==10 || rand16() < 5000) {
  151.             brd[b] = P_BLOCK;
  152.          }
  153.          else brd[b] = 0;
  154.       }
  155.    }
  156. }
  157.  
  158. /* Draw the board */
  159.  
  160. draw_brd() {
  161.    int xx,yy,x,y,b;
  162.    char* spr;
  163.  
  164.    yy = 10;
  165.    onumci = numci;
  166.    onumc = numc;
  167.    onumhi = numhi;
  168.    onumh = numh;
  169.  
  170.    numci = numc = numhi = numh = nummt = 0;
  171.    for(y=1;y<10;y++) {
  172.       waitcycl();
  173.       xx = 1;
  174.       for(x=1;x<15;x++) {
  175.          b = bindex(x,y);
  176.          if (brd[b]==P_BLOCK) spr = icon_b;
  177.          else if (brd[b]==P_HUMAN) { spr = icon_h; numh++;}
  178.          else if (brd[b]==P_CPU) { spr = icon_c; numc++;}
  179.          else if (brd[b]>127) { spr = icon_hi; numhi++;}
  180.          else if (!brd[b]) { spr = icon_0; nummt++;}
  181.          else { spr = icon_ci; numci++;}
  182.          sprite(spr,xx,yy,5,5);
  183.          xx+=6;
  184.       }
  185.       yy+=6;
  186.    }
  187.    waitoff();
  188.    draw_scr(15,onumh,numh);
  189.    draw_scr(21,onumhi,numhi);
  190.    draw_scr(27, onumh+onumhi,numh+numhi);
  191.  
  192.    draw_scr(43,onumc,numc);
  193.    draw_scr(49,onumci,numci);
  194.    draw_scr(55,onumc+onumci,numc+numci);
  195. }
  196.  
  197. draw_scr(y,os,ns) char y,os,ns; {
  198.    draw_sc2(y,os); // erase old score
  199.    draw_sc2(y,ns); // draw new score
  200. }
  201.  
  202. draw_sc2(y,scr) char y,scr; {
  203.    setxy_m(95, y);
  204.    disp_char(scr);
  205. }
  206.  
  207. /* Let human choose their move */
  208.  
  209. human() {
  210.    int c,done,xx,yy;
  211.    done = 0;
  212.  
  213.    do {
  214.       xx = cx*6-6;
  215.       yy = cy*6+3;
  216.       sprite_x(square,xx,yy,7,7);
  217.       c = getkey();
  218.       sprite_x(square,xx,yy,7,7);
  219.       if (c == K_DOWN) {
  220.          if (cy < 9) cy++;
  221.          else cy = 1;
  222.       } else if (c == K_UP) {
  223.          if (cy > 1) cy--;
  224.          else cy = 9;
  225.       } else if (c == K_LEFT) {
  226.          if (cx > 1) cx--;
  227.          else cx = 14;
  228.       } else if (c == K_RIGHT) {
  229.          if (cx < 14) cx++;
  230.          else cx = 1;
  231.       } else if (c == K_EXIT)
  232.          return 1;
  233.       else if (c == K_SECOND) {
  234.          if (islegal(cx,cy,P_HUMAN)) {
  235.             done = 1;
  236.             execute(cx,cy,P_HUMAN,brd);
  237.          }
  238.       }
  239.    } while (!done);
  240.    draw_brd();
  241.    return 0;
  242. }
  243.  
  244. /* Find the best legal move */
  245.  
  246. cpu() {
  247.    int val, x,y;
  248.    int bestVal, bestX, bestY;
  249.  
  250.    bestVal=0;
  251.    for (y=1;y<10;y++)
  252.       for (x=1;x<15;x++) {
  253.          if (islegal(x,y,P_CPU)) {
  254.             if (checkkey() == K_EXIT) _exit();
  255.             copy_brd();
  256.             execute(x,y,P_CPU,newbrd);
  257.             val = eval_brd();
  258.             if (val>bestVal) { bestX=x; bestY=y; bestVal=val; }
  259.             waitcycl();
  260.          }
  261.       }
  262.    execute(bestX,bestY,P_CPU,brd);
  263.    waitoff();
  264. }
  265.  
  266. /* Helper functions */
  267. sign(a) char a; {
  268.    if (a>127) return -1;
  269.    return 1;
  270. }
  271.  
  272. bindex(x,y) int x,y; {
  273.    return (y<<4)+x;
  274. }
  275.  
  276. abs(a) char a; {
  277.    if (a>127) return -a;
  278.    return a;
  279. }
  280.  
  281. islegal(x,y,p) int x,y,p; {
  282.    char b;
  283.    b = brd[bindex(x,y)];
  284.    if (!b || (sign(b)==sign(p) && b!=p && b!=P_BLOCK))
  285.       return true;
  286.    return false;
  287. }
  288.  
  289. /* Modify the board with a CPU or human move */
  290.  
  291. execute(x,y,p,b) int x,y,p; char* b; {
  292.    int i,j,xx,yy,bb;
  293.  
  294.    for(i=0;i<3;i++)
  295.       for(j=0;j<3;j++) {
  296.          xx = x + j - 1;
  297.          yy = y + i - 1;
  298.          bb = bindex(xx,yy);
  299.          if (j==1 && i==1) b[bb] = p;
  300.          else if (abs(b[bb]) < 10) b[bb]+=sign(p);
  301.       }
  302. }
  303.  
  304. can_cpu_place(bi) int bi; {
  305.    char spot;
  306.    spot = newbrd[bi];
  307.    if (!spot || (sign(spot)==1 && spot<10)) return true;
  308.    return false;
  309. }
  310.  
  311. /* This function is never actually called
  312. can_human_place(bi) int bi; {
  313.    char spot;
  314.    spot = newbrd[bi];
  315.    if (!spot || (sign(spot)==-1 && abs(spot)<10)) return true;
  316.    return false;
  317. }
  318. */
  319.  
  320. eval_brd() {
  321.    int x,y,nbi,i,j,bi;
  322.    int score, factor, vuln;
  323.  
  324.    score = 5000;
  325.    for (y=1;y<10;y++) {
  326.       for (x=1;x<15;x++) {
  327.          bi = bindex(x,y);
  328.          // Score each taken block
  329.          if (!newbrd[bi]) continue; // No need to score an empty space
  330.          if (newbrd[bi]==P_BLOCK) continue; // It's a block!
  331.          if (newbrd[bi]==P_CPU) { score+=10; continue; }
  332.          if (newbrd[bi]==P_HUMAN) { score-=10; continue; }
  333.  
  334.          // Score each influenced block
  335.  
  336. /* This code takes to long to run...
  337.  
  338.          vuln=0; // vulnerability
  339.          if (can_cpu_place(bi)) factor = 1;
  340.          else factor = -1;
  341.  
  342.          for (j=0;j<3;j++)
  343.             for (i=0;i<3;i++) {
  344.                if (i==1 && j==1) continue;
  345.                nbi = bindex(x+i-1,y+j-1);
  346.                if (factor==1 && can_human_place(nbi) ||
  347.                    factor==-1 && can_cpu_place(nbi)) vuln++;
  348.             }
  349.          // Now vuln becomes the strength of the position
  350.          vuln = factor * newbrd[bi] - vuln;
  351.          if (vuln > 0) score+=10*factor;
  352.          else score+=8*factor;
  353.  
  354.    It can be approximated thusly...
  355. */
  356.          if (can_cpu_place(bi)) {
  357.             if (newbrd[bi] > 1) score+=10;
  358.             else score+=8;
  359.          } else { /* human can place */
  360.             if (newbrd[bi] < -1) score-=10;
  361.             else score-=8;
  362.          }
  363.  
  364.       }
  365.    }
  366.    return score;
  367. }
  368.  
  369. copy_brd() {
  370. // make a quick copy of the board for modification
  371. #asm
  372.    ld  hl,(brd)      ;source
  373.    ld  de,(newbrd)   ;dest
  374.    ld  bc,176        ;board size
  375.    ldir
  376. #endasm
  377. }
  378.  
  379. checkkey() {
  380. #asm
  381.    call GET_KEY
  382.    ld hl,0
  383.    ld l,a
  384. #endasm
  385. }
  386.  
  387. /* Sprite data */
  388. #asm
  389. icon_h:
  390. .db %00100000
  391. .db %01110000
  392. .db %11111000
  393. .db %01110000
  394. .db %00100000
  395. icon_hi:
  396. .db %00100000
  397. .db %01010000
  398. .db %10001000
  399. .db %01010000
  400. .db %00100000
  401. icon_c:
  402. .db %01110000
  403. .db %11111000
  404. .db %11111000
  405. .db %11111000
  406. .db %01110000
  407. icon_ci:
  408. .db %01110000
  409. .db %10001000
  410. .db %10001000
  411. .db %10001000
  412. .db %01110000
  413. icon_b:
  414. .db %11111000
  415. .db %10101000
  416. .db %11011000
  417. .db %10101000
  418. .db %11111000
  419. icon_0:
  420. .db %00000000
  421. .db %00000000
  422. .db %00000000
  423. .db %00000000
  424. .db %00000000
  425. square:
  426. .db %11111110
  427. .db %10000010
  428. .db %10000010
  429. .db %10000010
  430. .db %10000010
  431. .db %10000010
  432. .db %11111110
  433. wait_0:
  434. .db %00000000
  435. .db %00000000
  436. .db %00000000
  437. .db %00000000
  438. .db %00000000
  439. wait_L1:
  440. .db %11111111
  441. .db %10011001
  442. .db %10110011
  443. .db %11100110
  444. .db %11111111
  445. wait_1R:
  446. .db %11111111
  447. .db %10011001
  448. .db %00110011
  449. .db %01100111
  450. .db %11111111
  451. wait_2L:
  452. .db %11111111
  453. .db %10110011
  454. .db %11100110
  455. .db %11001100
  456. .db %11111111
  457. wait_2R:
  458. .db %11111111
  459. .db %00110011
  460. .db %01100111
  461. .db %11001101
  462. .db %11111111
  463. wait_3L:
  464. .db %11111111
  465. .db %11100110
  466. .db %11001100
  467. .db %10011001
  468. .db %11111111
  469. wait_3R:
  470. .db %11111111
  471. .db %01100111
  472. .db %11001101
  473. .db %10011001
  474. .db %11111111
  475. wait_4L:
  476. .db %11111111
  477. .db %11001100
  478. .db %10011001
  479. .db %10110011
  480. .db %11111111
  481. wait_4R:
  482. .db %11111111
  483. .db %11001101
  484. .db %10011001
  485. .db %00110011
  486. .db %11111111
  487. #endasm
  488.  
  489.  
  490.