Given a potential chain lightning zap, moves it one square forward in the given direction, then adds it to the queue unless it would hit an invalid square or is out of power. zap is passed by value, so the move-forward doesn't change the passed argument. */
| 949 | zap is passed by value, so the move-forward doesn't change the passed |
| 950 | argument. */ |
| 951 | staticfn void |
| 952 | propagate_chain_lightning( |
| 953 | struct chain_lightning_queue *clq, |
| 954 | struct chain_lightning_zap zap) |
| 955 | { |
| 956 | struct monst *mon; |
| 957 | |
| 958 | zap.x += xdir[zap.dir]; |
| 959 | zap.y += ydir[zap.dir]; |
| 960 | |
| 961 | if (clq->tail >= CHAIN_LIGHTNING_LIMIT) |
| 962 | return; /* zap has covered too many squares */ |
| 963 | if (!CHAIN_LIGHTNING_POS(zap.x, zap.y)) |
| 964 | return; /* zap can't go to this square */ |
| 965 | |
| 966 | mon = m_at(zap.x, zap.y); |
| 967 | if (mon && mon->mpeaceful) |
| 968 | return; /* chain lightning avoids peaceful and tame monsters */ |
| 969 | |
| 970 | /* When hitting a monster that isn't electricity-resistant, a |
| 971 | particular chain lightning zap regains all its power, allowing it to |
| 972 | chain to other monsters; upon hitting a shock-resistant monster it |
| 973 | can't continue any further, but we let it hit the monster to show |
| 974 | the shield effect */ |
| 975 | if (mon && !resists_elec(mon) && !defended(mon, AD_ELEC)) |
| 976 | zap.strength = 3; |
| 977 | else if (mon) |
| 978 | zap.strength = 0; |
| 979 | |
| 980 | /* Unless it hits a monster, the last square of a zap isn't drawn on |
| 981 | screen and can't propagate further, so it may as well be discarded |
| 982 | now */ |
| 983 | if (!mon && !zap.strength) |
| 984 | return; |
| 985 | |
| 986 | /* The same square can't be chained to twice. */ |
| 987 | for (int i = 0; i < clq->tail; i++) { |
| 988 | if (clq->q[i].x == zap.x && clq->q[i].y == zap.y) |
| 989 | return; |
| 990 | } |
| 991 | |
| 992 | /* This array access must be inbounds due to the CHAIN_LIGHTNING_LIMIT |
| 993 | check earlier. */ |
| 994 | clq->q[clq->tail++] = zap; |
| 995 | |
| 996 | /* Draw it. */ |
| 997 | tmp_at(DISP_CHANGE, zapdir_to_glyph(xdir[zap.dir], ydir[zap.dir], |
| 998 | clq->displayed_beam)); |
| 999 | tmp_at(zap.x, zap.y); |
| 1000 | } |
| 1001 | |
| 1002 | staticfn void |
| 1003 | cast_chain_lightning(void) |
no test coverage detected