home *** CD-ROM | disk | FTP | other *** search
/ GameStar Special 2004 August / GSSH0804.iso / Rollenspiele / SwordOfFargoal / fargoal20030731b.exe / fargoal / src / game.c < prev    next >
C/C++ Source or Header  |  2003-07-31  |  19KB  |  815 lines

  1. /*
  2.     TODO:
  3.     
  4.     - Faster healing
  5.     
  6.     - Play in SLOW speed mode, and see how the rendering messes up. 
  7.  
  8.     + Full original gameplay compliance
  9.         + Pass key
  10.             - Lets you pass over monsters
  11.             + Instant chest open
  12.             + Instant pit climb
  13.             * Pass key is available in Original and Enhanced modes
  14.         + Overlapped character attacking
  15.             + Hide floating damage
  16.  
  17.     + Free movement on high levels, 18 and lower, the monster sound is
  18.     constantly going. It needs to be shut off, or the moves need to be
  19.     slowed down a bit for Free mode, or something
  20.        + I guess you already fixed it? I see no problem in level 20.
  21.  
  22.     - Smoother character/tile interaction
  23.  
  24.  
  25.     DONE:
  26.     
  27.     + Joystick support
  28.  
  29.     + Monster movement timing, on DL 1 it seems to be more like 12 of the
  30.     player's steps instead of 19. How come? steptime/global_steps timing is
  31.     wrong somehow
  32.         + OK, I think I found a good compromise between synchronized and 
  33.         flexible, and it still gives you 19 steps like it should. Please
  34.         verify.
  35.  
  36.     + Monsters pick up gold
  37.         - Does it just disappear?
  38.         395 ifp=47andm2=0orp=0thenp=32:goto397
  39.         - I think this is just for the screen, to hide the gold so the monster
  40.         sprite is clear
  41.     + Monsters who steal gold should run from you
  42.     + Improve battles
  43.     + Adjust level generation to match original, adjust if necessary
  44.     + Add sword level
  45.     + Better random monster movement, walk longer in one direction
  46.     + go through basic monster movement code and check if it does the same,
  47.     + number of mnsters spawned at level creation
  48.         
  49.     + Light spell can be turned off and on with 'o':
  50.  
  51.         121 gosub113:ifl1=1thenl1=2:print"(home)light off":gosub112:goto42
  52.         122 l1=1:gosub211:print"(home)light on":gosub112:goto42
  53.         294 gosub113:ifsf=1thensf=0:print"(home)the sword is stolen!!":gosub112:goto296
  54.  
  55.     + light spell nullifies invisibility spell
  56.       377 ifv1=0orl1=1then379
  57.     
  58.     + Remove rendering related calls from game frame logic
  59.  
  60.     + Include monster movement sound somehow? It sounds cool, and it indicates
  61.     the general speed of the monsters
  62.  
  63.     + There's some really wonky stuff going on in the window if I use GFX_GDI 
  64.     under Win32. Something to do with dirty rectangles? It's choppy, and it 
  65.     glitches the graphics as well. Can't debug without crashing in non-GDI
  66.     though
  67.     
  68.     + C64 code:
  69.         - Tag relevent portions of code with the associated C64 code, using a 
  70.         searchable "C64:" tag. We can then convert this C64 code to C and have
  71.         all of the original Sword of Fargoal gameplay rules
  72.     
  73.     + Smarter monster movement
  74.         + Lateral movement when behind a wall, don't just bunch up in a corner
  75.         + creatures fall into traps
  76.     
  77.     + rule of spawning humans/creatures. spawn from 1 level below
  78.     
  79.     + Proper function of Beacon spell, IE:
  80.         + "Beacons are an added tool. When you find a mystical BEACON, pick a 
  81.         convenient spot and place it there by pressing "+'. Within the BEACON's 
  82.         square you are invisible to the monsters. From there you can TELEPORT to 
  83.         the TEMPLE by pressing the FIRE BUTTON ... without wasting a TELEPORT! ANY 
  84.         other time you TELEPORT using your spells, you will appear at the BEACON 
  85.         that you placed on that level!!"
  86.         + Should be invisible on a Beacon, monsters shouldn't crowd around
  87.  
  88.     + Cumulative 0-HP attacks... IE, if you lose zero during a round
  89.     then add the current damage you did to the next round and attack all at
  90.     once. This will allow for more instant slayings.
  91.  
  92.     + General game/message timing
  93.     + No escape from being attacked
  94.         + Can't escape in the same direction, or into a wall
  95.  
  96.     OBSOLETE:
  97.  
  98.     - Dice rolling... multiple d6 rolls to determine stats for everything?
  99.  
  100.     - Game Research
  101.         - Hitpoints increases per level
  102.             - From Lv 1 to Lv 2, test game increased from max of 12HP to 27HP,
  103.             and 38HP at Lv 3 (3d6?)
  104.  
  105.         - Rate of health recovery
  106.             - Lv 1-3: With 13 HP max, looks like about 10 or 12 seconds per 
  107.             point near the top of health, and 5 seconds near the middle, 
  108.             and what at the bottom?
  109.         - Rate of monster movement
  110.         - Monster strength, damage, amount and type per level, frequency of 
  111.         spawning
  112.             -Types seen
  113.                 - Lv 1: Werebear, Barbarian, Hobgoblin (blue), Dwarf, Elf
  114.             - Speed
  115.                 - Lv 1: 19 player moves per 1 monster move
  116.             - Count
  117.                 - Lv 1: 4 monsters 
  118.  
  119.         - Effect of Skill points
  120.             - How do they increase?
  121.                 - Battle Skill 57 after finishing Lv 1 and defeating about 
  122.                 7 monsters
  123.         - Effect of Enchanted Weapon
  124.         - Trap damage
  125.         - Level generation
  126.         - Treasure
  127.             - On level 1, counted 5 Golds, 3 Secrets
  128.             - Gold added directly to EXP at Temple
  129.         - Healing potion doesn't heal fully... looks more like 10-15 HP after
  130.         one test on dungeon Lv 2
  131.  
  132.  
  133.     CONSIDERATIONS:
  134.     
  135.     - Assassins stay visible after fight?
  136.         - Don't think so
  137.  
  138.     - Battle adjustments
  139.         - Slaying a weak or inferior foe should not add any BS, 
  140.         or perhaps just 1 BS
  141.         - Slaying a monster could add only 1-3 instead of 1-5, maybe even only
  142.         1-2
  143.         - Slaying a strong or superior foe would allow the full BS range of
  144.         1-5
  145.         - Advancing an experience level should maybe only add 1-6 BS, or 1-8 BS
  146.  
  147.  
  148.     NOTES:
  149.                 
  150.     Legend of C64 Sword of Fargoal variables: (add more)
  151.  
  152.     a
  153.     a()        Monster map marker?
  154.     a%      human monster count
  155.     a%()    Monster health array?
  156.     a$()    Creature preposition
  157.     a1      Counter for monster spawning?
  158.     b       Joystick direction
  159.     b()        Human map marker?
  160.     b%      Creature monster count
  161.     b%()    Human health array?
  162.     b$()    Creature name
  163.     b1        Beacon is placed
  164.     be        Beacon spell count
  165.     bs        Battle skill
  166.     c        Monster ID?
  167.     c()     sword level positions
  168.     c$()    Human preposition
  169.     cl      clear map after teleport
  170.     d
  171.     d()     Directions <-> Number conversion
  172.     d%
  173.     d%()
  174.     d$()    Human name
  175.     de
  176.     e        Experience
  177.     el        Level
  178.     ep        Experience peak (for next level)
  179.     f
  180.     fa        Drift spell count
  181.     fl
  182.     fr      Fire button
  183.     g%      hidden gold stashes
  184.     gd      gold stashes count
  185.     h%        Currently fighting monster health
  186.     h()     sword level dirs
  187.     h1        Temporary, hit damage, starting HP, etc.
  188.     hi
  189.     hp      Healing potions
  190.     ht        Hit points
  191.     i1      Counter for treasure maps
  192.     iv        Invisible spell count
  193.     j
  194.     j%()
  195.     jv      Joystick value
  196.     k        Current tile
  197.     l        Dungeon level        
  198.     l%        Monster level?
  199.     l%()    Monster level array?
  200.     l1        Light spell active
  201.     lg        Light spell count
  202.     lo
  203.     m
  204.     m%()    Monster position (creatures)
  205.     m2      1 = creature, 0 = human
  206.     mk        Monsters killed
  207.     n
  208.     n%()    Monster position (humans)
  209.     o
  210.     o%()    Monster colour array
  211.     p
  212.     pt      pit depth
  213.     q       Player position
  214.     p1
  215.     pl        Enchanted weapon count
  216.     ql        Quest Level, the level the sword is on
  217.     r       trap type
  218.     r()     room positions
  219.     r%
  220.     rg        Regeneration spell count
  221.     r1
  222.     r2
  223.     s       Spawn time?
  224.     s%        Monster Skill
  225.     s%()    Monster Skill Array
  226.     s1        Shield spell active
  227.     so      sound related?
  228.     s2      "
  229.     s3      "
  230.     s4      " 
  231.     s5      " 
  232.     s6      "
  233.     sa%()   "
  234.     sb%()   "
  235.     sf        Have the Sword of Fargoal
  236.     sh        Shield spell count
  237.     sk
  238.     sn      sprite number?
  239.     sp      Healing counter
  240.     sr        Start game
  241.     sr%
  242.     ss%()
  243.     st%()
  244.     t%()    Map array
  245.     t        Treasure(=gold)
  246.     t1        Max gold carry (increases by 100 per sack)
  247.     t2        Timer?
  248.     t3        Timer?
  249.     th        Total hit points
  250.     ti        Timer?
  251.     tm        Total map count
  252.     tn%()
  253.     tp        Teleport spell count
  254.     tr%(,)
  255.     u%      number of spawnpoints - 1
  256.     v()     Opposite directions
  257.     v%        Spawning monster level
  258.     v%()    Spawn positions
  259.     v%      general variable?
  260.     v1        Invisible spell active
  261.     v3
  262.     w%
  263.     x        Temporary
  264.     x%
  265.     x()
  266.     x2        Temporary?
  267.     y
  268.     y%
  269.     y()
  270.     y1
  271.     z
  272.         
  273. */
  274.  
  275. #include "main.h"
  276. #include "map.h"
  277. #include "game.h"
  278. #include "gfx.h"
  279. #include "scroller.h"
  280.  
  281. SAMPLE *human[7];
  282. SAMPLE *creature[7];
  283. SAMPLE *boom;
  284. SAMPLE *crash;
  285. SAMPLE *gold;
  286. SAMPLE *pit;
  287. SAMPLE *spell;
  288. SAMPLE *step;
  289. SAMPLE *attack;
  290. SAMPLE *teleport;
  291. SAMPLE *beacon;
  292. SAMPLE *potion;
  293. SAMPLE *ding;
  294. SAMPLE *victory;
  295. SAMPLE *up;
  296. SAMPLE *down;
  297. SAMPLE *climb;
  298. SAMPLE *fight;
  299. SAMPLE *item;
  300. SAMPLE *levelup;
  301. SAMPLE *intro;
  302. SAMPLE *sacrifice;
  303. SAMPLE *slain;
  304. SAMPLE *crunch;
  305. SAMPLE *monstermove;
  306.  
  307. int extensions_nomonsterpause = 1;
  308. int extensions_balance = 1;
  309. int extensions_monsteraction = 1;
  310. int extensions_controls = 1;
  311. int extensions_overlapfight = 1;
  312. int extensions_dungeons = 1;
  313. int extensions_speed = 1;
  314.  
  315. int notrunning = 1;
  316. int won = 0;
  317. int gameover = 0;
  318. int spiral_map = 0;
  319. int swordrun = 0;
  320. int global_steps = 0; /* Step counter to trigger monster movement. */
  321. int stepcount = 0;
  322. int quest_number = 0;
  323.  
  324. /* The global paused state, to halt the game during messages. */
  325. int paused = 0;
  326.  
  327. static int stats_redraw = 1;
  328.  
  329. #define try_load_sample(__s, __n) \
  330.     __s = load_sample (__n); \
  331.     if (!__s) \
  332.     { \
  333.         printf ("Could not find %s.\n", __n); \
  334.         return 1; \
  335.     }
  336.  
  337. void
  338. game_alt_tab (void)
  339. {
  340.     update_stats ();
  341.     DR_add (0, -8, MAP_W - 1, MAP_H - 1);
  342. }    
  343.     
  344. int
  345. game_init (void)
  346. {
  347.     try_load_sample (human[0], "sfx/chop.wav");
  348.     try_load_sample (human[1], "sfx/clang.wav");
  349.     try_load_sample (human[2], "sfx/ugh.wav");    //ouch
  350.     try_load_sample (human[3], "sfx/thump.wav");    //thud
  351.     try_load_sample (human[4], "sfx/clink.wav");
  352.     try_load_sample (human[5], "sfx/shriek.wav");
  353.     try_load_sample (human[6], "sfx/slash.wav");
  354.  
  355.     creature[0] = human[2];        //ugh
  356.     try_load_sample (creature[1], "sfx/claw.wav");
  357.     try_load_sample (creature[2], "sfx/crunch.wav");
  358.     try_load_sample (creature[3], "sfx/gnarl.wav");
  359.     creature[4] = creature[3];    //growl
  360.     try_load_sample (creature[5], "sfx/shred.wav");
  361.     creature[6] = human[3];        //thump
  362.  
  363.     try_load_sample (boom, "sfx/boom.wav");
  364.     try_load_sample (crash, "sfx/crash.wav");
  365.     try_load_sample (gold, "sfx/gold.wav");
  366.     try_load_sample (pit, "sfx/pit.wav");
  367.     try_load_sample (spell, "sfx/spell.wav");
  368.     try_load_sample (step, "sfx/step.wav");
  369.     try_load_sample (attack, "sfx/attack.wav");
  370.     try_load_sample (teleport, "sfx/teleport.wav");
  371.     try_load_sample (beacon, "sfx/beacon.wav");
  372.     try_load_sample (potion, "sfx/potion.wav");
  373.     try_load_sample (ding, "sfx/ding.wav");
  374.     try_load_sample (victory, "sfx/victory.wav");
  375.     try_load_sample (up, "sfx/up.wav");
  376.     try_load_sample (down, "sfx/down.wav");
  377.     try_load_sample (climb, "sfx/climb.wav");
  378.     try_load_sample (fight, "sfx/fight.wav");
  379.     try_load_sample (item, "sfx/item.wav");
  380.     try_load_sample (levelup, "sfx/levelup.wav");
  381.     try_load_sample (intro, "sfx/intro.wav");
  382.     try_load_sample (sacrifice, "sfx/sacrifice.wav");
  383.     try_load_sample (slain, "sfx/slain.wav");
  384.     try_load_sample (monstermove, "sfx/move.wav");
  385.     crunch = creature[2];
  386.  
  387.     if (graphics_init ())
  388.         return 1;
  389.     chars_init ();
  390.     map_init ();
  391.     
  392.     return 0;
  393. }
  394.  
  395. void
  396. game_original (int health, int skill)
  397. {
  398.     //   26 next:w%=0:gosub175:ifsr=1thensr=0:print"your quest begins!!";:goto28
  399.     char_num = 1;
  400.     player_create (0, 0, health, skill);
  401.     swordlev = rnd (15, 20);
  402.     game_start_new ();
  403. }
  404. /*
  405. void
  406. game_enhanced1 (void)
  407. {
  408.     swordlev = rnd (40, 50);
  409.     game_start_new ();
  410. }
  411.  
  412. void
  413. game_enhanced2 (void)
  414. {
  415.     swordlev = 100;
  416.     game_start_new ();
  417. }
  418. */
  419. void
  420. game_start_new (void)
  421. {
  422.     list[1].current_level = 1;
  423.     list[1].lev = 1;
  424.     paused = 0;
  425.     messages_init (NULL);
  426.     message (FPS * 1, intro, "Your quest begins!!");
  427.     gameover = 0;
  428.     won = 0;
  429.     notrunning = 0;
  430.     swordrun = 0;
  431.     monster_strength = 0;
  432.     map_enter (SPOT_VOID, 0);
  433. }
  434.  
  435.  
  436. void
  437. game_continue (void)
  438. {
  439.     //   27 print"your quest continues!"    
  440.     {
  441.         paused = 0;
  442.         if (gameover)
  443.             message (FPS * 1, NULL, "Thou hast already failed in thy quest.");
  444.         else if (won)
  445.             message (FPS * 1, NULL, "Thou hast already completed thy quest!!");
  446.         else
  447.             message (FPS * 1, NULL, "Your quest continues!");
  448.         update_stats ();
  449.         DR_add (0, -6, MAP_W - 1, MAP_H - 1);
  450.     }
  451. }
  452.  
  453. void
  454. game_exit (void)
  455. {
  456. }
  457.  
  458. static int hitx[10], hity[10];
  459. static int hitv[10], hitt[10];
  460.  
  461.  
  462. void
  463. add_hit (int mx, int my, int v)
  464. {
  465.     int i;
  466.     
  467.     if (!extensions_overlapfight)
  468.         return;
  469.  
  470.     for (i = 0; i < 10; i++)
  471.     {
  472.         if (!hitt[i])
  473.         {
  474.             hitx[i] = mx * tw + tw / 2;
  475.             hity[i] = TOP + my * th - th;
  476.             hitv[i] = v;
  477.             hitt[i] = FPS;
  478.             return;
  479.         }
  480.     }
  481.     return;
  482. }
  483.  
  484.  
  485. static void
  486. _fly_hits (void)
  487. {
  488.     int i;
  489.     
  490.     for (i = 0; i < 10; i++)
  491.     {
  492.         if (hitt[i])
  493.         {
  494.             hity[i]--;
  495.             hitt[i]--;
  496.             DR_add (hitx[i] / tw - 1, (hity[i] - TOP) / th - 1, hitx[i] / tw + 1, (hity[i] - TOP) / th + 1);
  497.         }
  498.     }
  499. }
  500.  
  501.  
  502. static void
  503. _draw_hits (void)
  504. {
  505.     int i;
  506.     
  507.     text_mode (-1);
  508.     for (i = 0; i < 10; i++)
  509.     {
  510.         if (hitt[i])
  511.         {
  512.             if (hitv[i])
  513.                 textprintf_centre (page, font, hitx[i], hity[i], hitv[i] < 0 ? makecol (255, 0, 0) : makecol (0, 200, 0), "%i", abs (hitv[i]));
  514.         }
  515.     }
  516. }
  517.  
  518.  
  519. void
  520. update_stats (void)
  521. {
  522.     stats_redraw = 1;
  523. }
  524.  
  525.  
  526. int get_steptime()
  527. {
  528.     if(extensions_speed)
  529.         return STEPTIME;
  530.  
  531.     return STEPTIME*2;
  532. }
  533.  
  534.  
  535. void
  536. game_frame (void)
  537. {
  538.     int i;
  539.     
  540. #if defined(DEBUGMODE) || defined(_DEBUG)
  541.     if (key[KEY_F1])
  542.         clear_to_color (screen, makecol (255, 0, 0));
  543.     
  544.     if (key[KEY_F2])
  545.         clear_to_color (page, makecol (0, 255, 0));
  546.     
  547.     if (key[KEY_F3])
  548.     {
  549.         gameover = 1;
  550.         spiral_map = MAP_W * MAP_H / 2;
  551.     }
  552.     if (key[KEY_F4])
  553.     {
  554.         map_hide_completely ();
  555.         gameover = 0;
  556.     }
  557.     if (key[KEY_F5])
  558.     {
  559.         swordrun=5 * FPS;
  560.     }
  561.     if (key[KEY_F6])
  562.     {
  563.         swordrun=SWORD_TIME;
  564.     }
  565.     
  566. #endif
  567.  
  568.     messages_update ();
  569.  
  570.     if (!gameover && !won)
  571.     {
  572.         player_process (1);        /* 1 = id of player object */
  573.     }
  574.     else
  575.     {
  576.         if (spiral_map && frames % 2 == 0)
  577.         {
  578.             int x = 0, y = MAP_H;
  579.             int dx = 0, dy = -1;
  580.             int spiral_steps = MAP_W * MAP_H / 2 - spiral_map;
  581.             int  w = MAP_W - 1, h = MAP_H;
  582.             int row = w, column = h;
  583.             for (i = 0; i <= spiral_steps; i++)
  584.             {
  585.                 if (dx)
  586.                 {
  587.                     if (row)
  588.                         row--;
  589.                     else
  590.                     {
  591.                         dy = dx;
  592.                         dx = 0;
  593.                         h -= 2;
  594.                         column = h;
  595.                     }
  596.                 }
  597.                 if (dy)
  598.                 {
  599.                     if (column)
  600.                         column--;
  601.                     else
  602.                     {
  603.                         dx = -dy;
  604.                         dy = 0;
  605.                         w -= 2;
  606.                         row = w;
  607.                     }
  608.                 }
  609.                 x += dx;
  610.                 y += dy;
  611.             }
  612.             map_seen (x, y, 0);
  613.             map_seen (MAP_W - 1 - x, MAP_H - 1 - y, 0);
  614.             spiral_map--;
  615.         }
  616.     }
  617.     
  618.     if (won)
  619.     {
  620.         won++;
  621.         if (won > FPS * 5)
  622.         {
  623.             won = 1;
  624.             scroller_init ();
  625.         }
  626.     }
  627.  
  628.     if (stepcount)
  629.     {
  630.         if (!list[1].fighting && !paused)
  631.             stepcount--;
  632.     }
  633.     else
  634.     {
  635.         stepcount = get_steptime();
  636.         if (global_steps)
  637.             global_steps--;
  638.     }
  639.     
  640.     if (!global_steps)
  641.     {
  642.         monsters_spawn ();
  643.  
  644.         if(monster_count())
  645.             message(extensions_nomonsterpause ? 0 : get_steptime()*2, monstermove, NULL);
  646.  
  647.     }
  648.     
  649.     for (i = 2; i < char_num; i++)
  650.     {
  651.         monster_process (i);
  652.     }
  653.     
  654.     if (!global_steps)
  655.     {
  656.         global_steps = MAX (1, 20 - list[1].current_level);
  657.         stepcount = extensions_nomonsterpause ? 
  658.             (extensions_speed ? FPS : FPS*2) : 
  659.             get_steptime();
  660.     }
  661.  
  662.  
  663.     if (!won && !gameover && swordrun)
  664.     {
  665.         swordrun--;
  666.         if ((swordrun % FPS) == 0)
  667.             update_stats();
  668.         if (!swordrun)
  669.         {
  670.             //  411 print"(down)(down)out of time!"
  671.             map_hide_completely();
  672.             message (FPS*3.5, crash, "Out of time!");
  673.             map_crash();
  674.             message(FPS, slain, "Game Over");
  675.             player_die (1);
  676.         }
  677.     }
  678.  
  679.     _fly_hits ();
  680. }
  681.  
  682.  
  683. void
  684. game_render (void)
  685. {
  686.     int spellbook_x = 500;
  687.     int spellbook_y = SCREEN_H - 90 + 15;
  688.     int inventory_x = 340;
  689.     int inventory_y = SCREEN_H - 90 + 15;
  690.     int stats_x = 10;
  691.     int stats_y = SCREEN_H - 90 + 15;
  692.     int info_x = 180;
  693.     int info_y = SCREEN_H - 90 + 15;
  694.  
  695.     text_mode (-1);
  696.  
  697.     messages_render ();
  698.  
  699.     map_draw ();
  700.     
  701.     if (stats_redraw || map_check_DRs (0, -3, MAP_W - 1, -3))
  702.     {
  703.         blit (title, page, 30, TOP - 3 * th, 30, TOP - 3 * th, 120, 8);
  704.         textprintf (page, font, 30, 54,
  705.             list[1].hit < list[1].maxhit ?
  706.             list[1].hit < list[1].maxhit / 3 ?
  707.             layout_color (LC_HURT) :
  708.             layout_color (LC_HEALTH) :
  709.             layout_color (LC_HEALTHY),
  710.             "Hits: %i/%i", list[1].hit, list[1].maxhit);
  711.         
  712.         blit (title, page, 280, 54, 280, 54, 80, 8);
  713.         textprintf_centre (page, font, 320, 54, layout_color (LC_GOLD),
  714.             "Gold: %i", list[1].gold);
  715.         
  716.         if (swordrun)
  717.         {
  718.             int seconds = (swordrun - 1) / FPS;
  719.             int blink = seconds & 1;
  720.             blit (title, page, 0, 40, 0, 40, SCREEN_W, 8);
  721.             blit (title, page, 480, 54, 480, 54, 130, 8);
  722.             textprintf_right (page, font, SCREEN_W - 30, 40,
  723.                 blink ? layout_color (LC_TIME) :
  724.                 layout_color (LC_BLINK), "%s", list[1].sword ? "Carrying sword"
  725.                 : "Sword stolen");
  726.             textprintf_right (page, font, SCREEN_W - 30, 54,
  727.                 blink ? layout_color (LC_TIME) :
  728.                 layout_color (LC_BLINK), "Time left %02i:%02i", seconds / 60, seconds % 60);
  729.         }
  730.     }
  731.  
  732.     _draw_hits ();
  733.  
  734.     if (stats_redraw)
  735.     {
  736.         blit (title, page, 0, SCREEN_H - 90, 0, SCREEN_H - 90, SCREEN_W, 90);
  737.         
  738.         /* Print stats. */
  739.         textprintf (page, font, stats_x, stats_y, layout_color (LC_STATS),
  740.             "Experience %i", list[1].exp);
  741.         textprintf (page, font, stats_x, stats_y + 22, layout_color (LC_STATS),
  742.             "Level %i (%i)", list[1].lev, list[1].next);
  743.         textprintf (page, font, stats_x, stats_y + 44, layout_color (LC_STATS),
  744.             "Skill %i", list[1].dex);
  745.         
  746.         /* Print additional info. */
  747.         textprintf (page, font, info_x, info_y, layout_color (LC_INFO),
  748.             "Slain foes %7i", list[1].slain_foes[0]);
  749.         textprintf (page, font, info_x, info_y + 11, layout_color (LC_INFO),
  750.             "Enchanted Sword+%2i", list[1].weapon);
  751.         textprintf (page, font, info_x, info_y + 44, layout_color (LC_DUNGEON),
  752.             "Dungeon level  %3i", list[1].current_level);
  753.         textprintf (page, font, info_x, info_y + 55, layout_color (LC_DUNGEON),
  754.             "Deepest Descent%3i", list[1].deepest_level);
  755.  
  756.  
  757.         /* Display spellbook. */
  758.         {
  759.             int i;
  760.  
  761.             for (i = 0; i < 6; i++)
  762.             {
  763.                 int c = list[1].spells[i].amount ? layout_color (LC_SPELL) : layout_color (LC_NOSPELL);
  764.  
  765.                 if (list[1].spells[i].active)
  766.                     c =layout_color (LC_CAST);
  767.                 if (i == SPELL_REGENERATION && list[1].amulets_of_healing)
  768.                     textprintf (page, font, spellbook_x, spellbook_y + i * 11, c,
  769.                     "%-12s %2i+%i", spell_names[i], list[1].spells[i].amount,
  770.                         list[1].amulets_of_healing);
  771.                 else
  772.                 if (i == SPELL_LIGHT && list[1].amulets_of_light)
  773.                     textprintf (page, font, spellbook_x, spellbook_y + i * 11, c,
  774.                     "%-12s %2i+%i", spell_names[i], list[1].spells[i].amount,
  775.                         list[1].amulets_of_light);
  776.                 else
  777.                     textprintf (page, font, spellbook_x, spellbook_y + i * 11, c,
  778.                         "%-12s %2i", spell_names[i], list[1].spells[i].amount);
  779.             }
  780.         }
  781.  
  782.         /* Display inventory. */
  783.         textprintf (page, font, inventory_x, inventory_y, list[1].beaconx ? layout_color (LC_BEACON) : list[1].beacons ? layout_color (LC_BEACON) : layout_color (LC_EMPTY),
  784.             "Beacons         %2i", list[1].beacons);
  785.         textprintf (page, font, inventory_x, inventory_y + 22, list[1].sacks ? layout_color (LC_SACKS) : layout_color (LC_EMPTY),
  786.             "Magic sacks     %2i", list[1].sacks);
  787.         textprintf (page, font, inventory_x, inventory_y + 44, list[1].potions ? layout_color (LC_POTIONS) : layout_color (LC_NOPOTIONS),
  788.             "Healing potions %2i", list[1].potions);
  789.     }
  790.  
  791.     if (USE_DRS)
  792.     {
  793.         acquire_screen ();
  794.         map_blit_DRs ();
  795.         if (messages_updated ())
  796.         {
  797.             blit (page, screen, 0, 0, 0, 0, SCREEN_W, 18);
  798.         }
  799.         if (stats_redraw)
  800.         {
  801.             if (swordrun)
  802.                 blit (page, screen, 0, 40, 0, 40, SCREEN_W, 8);
  803.             blit (page, screen, 0, 54, 0, 54, SCREEN_W, 8);
  804.             blit (page, screen, 0, SCREEN_H - 90, 0, SCREEN_H - 90, SCREEN_W, 90);
  805.             stats_redraw = 0;
  806.         }
  807.         release_screen ();
  808.     }
  809.     else
  810.     {
  811.         DR_n = 0;
  812.         blit (page, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
  813.     }
  814. }
  815.