hit the monster next to you and the monsters to the left and right of it; return False if the primary target is killed, True otherwise */
| 648 | /* hit the monster next to you and the monsters to the left and right of it; |
| 649 | return False if the primary target is killed, True otherwise */ |
| 650 | staticfn boolean |
| 651 | hitum_cleave( |
| 652 | struct monst *target, /* non-Null; forcefight at nothing doesn't cleave +*/ |
| 653 | struct attack *uattk) /*+ but we don't enforce that here; Null works ok */ |
| 654 | { |
| 655 | /* swings will be delivered in alternate directions; with consecutive |
| 656 | attacks it will simulate normal swing and backswing; when swings |
| 657 | are non-consecutive, hero will sometimes start a series of attacks |
| 658 | with a backswing--that doesn't impact actual play, just spoils the |
| 659 | simulation attempt a bit */ |
| 660 | static boolean clockwise = FALSE; |
| 661 | int i; |
| 662 | coord save_bhitpos; |
| 663 | boolean save_notonhead; |
| 664 | int count, umort, x = u.ux, y = u.uy; |
| 665 | |
| 666 | /* find the direction toward primary target */ |
| 667 | i = xytodir(u.dx, u.dy); |
| 668 | if (i == DIR_ERR) { |
| 669 | impossible("hitum_cleave: unknown target direction [%d,%d,%d]?", |
| 670 | u.dx, u.dy, u.dz); |
| 671 | return TRUE; /* target hasn't been killed */ |
| 672 | } |
| 673 | /* adjust direction by two so that loop's increment (for clockwise) |
| 674 | or decrement (for counter-clockwise) will point at the spot next |
| 675 | to primary target */ |
| 676 | i = clockwise ? DIR_LEFT2(i) : DIR_RIGHT2(i); |
| 677 | umort = u.umortality; /* used to detect life-saving */ |
| 678 | save_bhitpos = gb.bhitpos; |
| 679 | save_notonhead = gn.notonhead; |
| 680 | |
| 681 | /* |
| 682 | * Three attacks: adjacent to primary, primary, adjacent on other |
| 683 | * side. Primary target must be present or we wouldn't have gotten |
| 684 | * here (forcefight at thin air won't 'cleave'). However, the |
| 685 | * first attack might kill it (gas spore explosion, weak long worm |
| 686 | * occupying both spots) so we don't assume that it's still present |
| 687 | * on the second attack. |
| 688 | */ |
| 689 | for (count = 3; count > 0; --count) { |
| 690 | struct monst *mtmp; |
| 691 | int tx, ty, tmp, dieroll, mhit, attknum = 0, armorpenalty; |
| 692 | |
| 693 | /* ++i, wrap 8 to i=0 /or/ --i, wrap -1 to i=7 */ |
| 694 | i = clockwise ? DIR_RIGHT(i) : DIR_LEFT(i); |
| 695 | |
| 696 | tx = x + xdir[i], ty = y + ydir[i]; /* current target location */ |
| 697 | if (!isok(tx, ty)) |
| 698 | continue; |
| 699 | mtmp = m_at(tx, ty); |
| 700 | if (!mtmp) { |
| 701 | if (glyph_is_invisible(levl[tx][ty].glyph)) |
| 702 | (void) unmap_invisible(tx, ty); |
| 703 | continue; |
| 704 | } |
| 705 | |
| 706 | tmp = find_roll_to_hit(mtmp, uattk->aatyp, uwep, |
| 707 | &attknum, &armorpenalty); |
no test coverage detected