static bitboard getPieceBitboard(const position * const pos, const int piece) { bitboard b = 0; int colour = COLOUR(piece); if(IS_KING(piece)) { b = pos->king[colour]; } else if(IS_PAWN(piece)) { b = pos->pawns[colour]; } else if(IS_KNIGHT(piece)) { b = pos->knights[colour]; } else if(IS_BISHOP(piece)) { b = pos->bishops[colour]; } else if(IS_ROOK(piece)) { b = pos->rooks[colour]; } else if(IS_QUEEN(piece)) { b = pos->queens[colour]; } else { /* Something is wrong, I don't know which piece this is. * This must NEVER happen; move generation is screwed. */ assert(0); } return b; }
static int movePiece(position *pos, const move * const m, const int player) { int piece; int castleBits; piece = m->thisPiece; /* move piece to new location */ pos->board[m->to] = pos->board[m->from]; pos->board[m->from] = 0; CLR_BIT(pos->pieces[player], m->from); SET_BIT(pos->pieces[player], m->to); if(IS_KING(piece)) { CLR_BIT(pos->king[player], m->from); SET_BIT(pos->king[player], m->to); /* king position is tracked using kingSquare too */ pos->kingSquare[player] = m->to; if(IS_CASTLE(m)) { moveCastlingExtra(pos, m); } /* king has moved, cannot castle now */ castleBits = CASTLE_BITS(player); pos->castleFlags &= ~castleBits; } else if(IS_PAWN(piece)) { /* move the pawn as usual */ CLR_BIT(pos->pawns[player], m->from); SET_BIT(pos->pawns[player], m->to); /* handle ep, promotion if required */ movePawnExtra(pos, m, player); } else if(IS_KNIGHT(piece)) { CLR_BIT(pos->knights[player], m->from); SET_BIT(pos->knights[player], m->to); } else if(IS_BISHOP(piece)) { CLR_BIT(pos->bishops[player], m->from); SET_BIT(pos->bishops[player], m->to); } else if(IS_ROOK(piece)) { CLR_BIT(pos->rooks[player], m->from); SET_BIT(pos->rooks[player], m->to); /* disable castling if required */ moveRookExtra(pos, m, player); } else if(IS_QUEEN(piece)) { CLR_BIT(pos->queens[player], m->from); SET_BIT(pos->queens[player], m->to); } else { printPosition(pos); printMove(m); fprintf(stderr, "Piece = %d\n", piece); /* Something is wrong, I don't know which piece this is. * This must NEVER happen; move generation is screwed. */ assert(0); } return 0; }
static void movePawnExtra(position *pos, const move * const m, const int player) { /* if ep, remove the opponents pawn */ if(IS_EP(m)) { if(WHITE == player) { CLR_BIT(pos->pieces[BLACK], pos->epSquare - 8); CLR_BIT(pos->pawns[BLACK], pos->epSquare - 8); pos->board[pos->epSquare - 8] = 0; } else { CLR_BIT(pos->pieces[WHITE], pos->epSquare + 8); CLR_BIT(pos->pawns[WHITE], pos->epSquare + 8); pos->board[pos->epSquare + 8] = 0; } } else if(IS_PROMOTION(m)) { /* if promotion, replace 'to' pawn by promoted piece */ pos->board[m->to] = m->promoteTo; /* change board */ CLR_BIT(pos->pawns[player], m->to); /* pawn gone */ /* add new piece to its bitmap */ if(IS_KNIGHT(m->promoteTo)) { SET_BIT(pos->knights[player], m->to); } else if(IS_BISHOP(m->promoteTo)) { SET_BIT(pos->bishops[player], m->to); } else if(IS_ROOK(m->promoteTo)) { SET_BIT(pos->rooks[player], m->to); } else if(IS_QUEEN(m->promoteTo)) { SET_BIT(pos->queens[player], m->to); } else { assert(0); } } else { /* check if double advance and set ep square */ if(16 == abs(m->to - m->from)) { if(WHITE == player) { pos->epSquare = m->to - 8; } else { pos->epSquare = m->to + 8; } } } }
bool psionic_mob_fight(struct creature *ch, struct creature *precious_vict) { struct creature *vict = NULL; if (!is_fighting(ch)) return false; // pick an enemy if (!(vict = choose_opponent(ch, precious_vict))) return false; int aggression = calculate_mob_aggression(ch, vict); // Psions can't really do anything when there's a psishield in place if (AFF3_FLAGGED(vict, AFF3_PSISHIELD) && can_cast_spell(ch, SPELL_PSIONIC_SHATTER)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSIONIC_SHATTER); return true; } // Prioritize healing with aggression if (GET_HIT(ch) < (GET_MAX_HIT(ch) * MIN(20, MAX(80, aggression)) / 100) && can_cast_spell(ch, SPELL_WOUND_CLOSURE)) { cast_spell(ch, ch, NULL, NULL, SPELL_WOUND_CLOSURE); return true; } if (aggression > 75) { // extremely aggressive - just attack hard if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return true; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return true; } } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (GET_MANA(ch) < GET_MAX_MANA(ch) / 2 && can_cast_spell(ch, SKILL_PSIDRAIN) && can_psidrain(ch, vict, NULL, false)) { perform_psidrain(ch, vict); return true; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_CRUSH) && can_cast_spell(ch, SPELL_PSYCHIC_CRUSH)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_CRUSH); return true; } else if (!affected_by_spell(vict, SPELL_MOTOR_SPASM) && can_cast_spell(ch, SPELL_MOTOR_SPASM)) { cast_spell(ch, vict, NULL, NULL, SPELL_MOTOR_SPASM); return true; } else if (!affected_by_spell(ch, SPELL_ADRENALINE) && can_cast_spell(ch, SPELL_ADRENALINE)) { cast_spell(ch, ch, NULL, NULL, SPELL_ADRENALINE); return true; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return true; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return true; } } if (aggression > 25) { // not very aggressive - play more defensively if (IS_PSIONIC(vict) && !affected_by_spell(ch, SPELL_PSYCHIC_RESISTANCE) && can_cast_spell(ch, SPELL_PSYCHIC_RESISTANCE)) { cast_spell(ch, ch, NULL, NULL, SPELL_PSYCHIC_RESISTANCE); return true; } else if (!IS_CONFUSED(vict) && can_cast_spell(ch, SPELL_CONFUSION) && (IS_MAGE(vict) || IS_PSIONIC(vict) || IS_CLERIC(vict) || IS_KNIGHT(vict) || IS_PHYSIC(vict))) { cast_spell(ch, vict, NULL, NULL, SPELL_CONFUSION); return true; } else if (GET_MOVE(ch) < GET_MAX_MOVE(ch) / 4 && can_cast_spell(ch, SPELL_ENDURANCE)) { cast_spell(ch, ch, NULL, NULL, SPELL_ENDURANCE); return true; } else if (GET_MOVE(ch) < GET_MAX_MOVE(ch) / 4 && can_cast_spell(ch, SPELL_DERMAL_HARDENING)) { cast_spell(ch, ch, NULL, NULL, SPELL_DERMAL_HARDENING); return true; } else if (!AFF2_FLAGGED(ch, AFF2_VERTIGO) && can_cast_spell(ch, SPELL_VERTIGO)) { cast_spell(ch, vict, NULL, NULL, SPELL_VERTIGO); return true; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_FEEDBACK) && can_cast_spell(ch, SPELL_PSYCHIC_FEEDBACK)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_FEEDBACK); return true; } else if (!affected_by_spell(vict, SPELL_WEAKNESS) && can_cast_spell(ch, SPELL_WEAKNESS)) { cast_spell(ch, vict, NULL, NULL, SPELL_WEAKNESS); return true; } else if (!affected_by_spell(vict, SPELL_CLUMSINESS) && can_cast_spell(ch, SPELL_CLUMSINESS)) { cast_spell(ch, vict, NULL, NULL, SPELL_CLUMSINESS); return true; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return true; } } if (aggression > 5) { // attempt to neutralize or get away if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_MELATONIC_FLOOD)) { cast_spell(ch, vict, NULL, NULL, SPELL_MELATONIC_FLOOD); return true; } else if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return true; } else if (can_cast_spell(ch, SPELL_AMNESIA)) { cast_spell(ch, vict, NULL, NULL, SPELL_AMNESIA); return true; } else if (can_cast_spell(ch, SPELL_FEAR)) { cast_spell(ch, vict, NULL, NULL, SPELL_FEAR); return true; } } return false; }
void psionic_best_attack(struct creature *ch, struct creature *vict) { int aggression = calculate_mob_aggression(ch, vict); // Psions can't really do anything when there's a psishield in place if (AFF3_FLAGGED(vict, AFF3_PSISHIELD) && can_cast_spell(ch, SPELL_PSIONIC_SHATTER)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSIONIC_SHATTER); return; } if (aggression > 75) { // extremely aggressive - just attack hard if (!affected_by_spell(vict, SPELL_PSYCHIC_SURGE) && can_cast_spell(ch, SPELL_PSYCHIC_SURGE)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_SURGE); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return; } } if (aggression > 50) { // somewhat aggressive - balance attacking with crippling if (!affected_by_spell(vict, SPELL_PSYCHIC_CRUSH) && can_cast_spell(ch, SPELL_PSYCHIC_CRUSH)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_CRUSH); return; } else if (!affected_by_spell(vict, SPELL_MOTOR_SPASM) && can_cast_spell(ch, SPELL_MOTOR_SPASM)) { cast_spell(ch, vict, NULL, NULL, SPELL_MOTOR_SPASM); return; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } } if (aggression > 25) { // not very aggressive - play more defensively if (!IS_CONFUSED(vict) && can_cast_spell(ch, SPELL_CONFUSION) && (IS_MAGE(vict) || IS_PSIONIC(vict) || IS_CLERIC(vict) || IS_KNIGHT(vict) || IS_PHYSIC(vict))) { cast_spell(ch, vict, NULL, NULL, SPELL_CONFUSION); return; } else if (!AFF2_FLAGGED(ch, AFF2_VERTIGO) && can_cast_spell(ch, SPELL_VERTIGO)) { cast_spell(ch, vict, NULL, NULL, SPELL_VERTIGO); return; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_FEEDBACK) && can_cast_spell(ch, SPELL_PSYCHIC_FEEDBACK)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_FEEDBACK); return; } else if (nullpsi_is_advisable(vict) && can_cast_spell(ch, SPELL_NULLPSI)) { cast_spell(ch, vict, NULL, NULL, SPELL_NULLPSI); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } } if (aggression > 5) { // attempt to neutralize or get away if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_MELATONIC_FLOOD)) { cast_spell(ch, vict, NULL, NULL, SPELL_MELATONIC_FLOOD); return; } else if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return; } else if (can_cast_spell(ch, SPELL_AMNESIA)) { cast_spell(ch, vict, NULL, NULL, SPELL_AMNESIA); return; } else if (can_cast_spell(ch, SPELL_FEAR)) { cast_spell(ch, vict, NULL, NULL, SPELL_FEAR); return; } } // desperation - just attack full force, as hard as possible if (!affected_by_spell(vict, SPELL_PSYCHIC_SURGE) && can_cast_spell(ch, SPELL_PSYCHIC_SURGE)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_SURGE); return; } else if (!affected_by_spell(vict, SPELL_PSYCHIC_CRUSH) && can_cast_spell(ch, SPELL_PSYCHIC_CRUSH)) { cast_spell(ch, vict, NULL, NULL, SPELL_PSYCHIC_CRUSH); return; } else if (!affected_by_spell(vict, SPELL_MOTOR_SPASM) && can_cast_spell(ch, SPELL_MOTOR_SPASM)) { cast_spell(ch, vict, NULL, NULL, SPELL_MOTOR_SPASM); return; } else if (can_cast_spell(ch, SKILL_PSIBLAST)) { perform_offensive_skill(ch, vict, SKILL_PSIBLAST); return; } else if (GET_POSITION(vict) > POS_SITTING && can_cast_spell(ch, SPELL_EGO_WHIP)) { cast_spell(ch, vict, NULL, NULL, SPELL_EGO_WHIP); return; } else if (GET_POSITION(vict) > POS_SLEEPING && can_cast_spell(ch, SPELL_MELATONIC_FLOOD)) { cast_spell(ch, vict, NULL, NULL, SPELL_MELATONIC_FLOOD); return; } else if (can_cast_spell(ch, SPELL_ASTRAL_SPELL)) { cast_spell(ch, vict, NULL, NULL, SPELL_ASTRAL_SPELL); return; } else if (can_cast_spell(ch, SPELL_AMNESIA)) { cast_spell(ch, vict, NULL, NULL, SPELL_AMNESIA); return; } else if (can_cast_spell(ch, SPELL_FEAR)) { cast_spell(ch, vict, NULL, NULL, SPELL_FEAR); return; } else { hit(ch, vict, TYPE_UNDEFINED); } }
static void clearCapturedPiece(position *pos, const move * const m) { int piece; int colour; int castleBits; /* ep is handled in movePiece(...) method and not here this only handles the "simple" capture TODO: change later? */ piece = m->capturedPiece; colour = COLOUR(piece); assert(!IS_KING(piece)); /* clear all pieces bitboard */ CLR_BIT(pos->pieces[colour], m->to); /* Do NOT set m->to to 0, as board[m->to] contains the moved piece! Just update the bitboards. */ if(IS_PAWN(piece)) { CLR_BIT(pos->pawns[colour], m->to); } else if(IS_KNIGHT(piece)) { CLR_BIT(pos->knights[colour], m->to); } else if(IS_BISHOP(piece)) { CLR_BIT(pos->bishops[colour], m->to); } else if(IS_ROOK(piece)) { CLR_BIT(pos->rooks[colour], m->to); } else if(IS_QUEEN(piece)) { CLR_BIT(pos->queens[colour], m->to); } else { /* Something is wrong, I don't know which piece this is. * This must NEVER happen; move generation is screwed. */ assert(0); } /* check if rook square has been captured and disable castling */ if(m->to == 0) { castleBits = CASTLE_WK; pos->castleFlags &= ~castleBits; } else if(m->to == 7) { castleBits = CASTLE_WQ; pos->castleFlags &= ~castleBits; } else if(m->to == 56) { castleBits = CASTLE_BK; pos->castleFlags &= ~castleBits; } else if(m->to == 63) { castleBits = CASTLE_BQ; pos->castleFlags &= ~castleBits; } }
static bitboard getAttackRange(const int piece, const int type, const int sq, const bitboard allPieces, const int epSquare) { bitboard attackRange = 0; int state = 0; int rank; int file; bitboard rotAllPieces = 0; bitboard rot_a1h8_allPieces = 0; bitboard rot_h1a8_allPieces = 0; const bitboard *table1 = 0; const bitboard *table2 = 0; const bitboard *table_attack = 0; /* supports only normal and capture */ assert(NORMAL == type || CAPTURE == type); if(IS_KING(piece)) { attackRange = _king[sq]; } else if(IS_PAWN(piece)) { if(WHITE == COLOUR(piece)) { table1 = _wpawn_advance1; table2 = _wpawn_advance2; table_attack = _wpawn_attack; } else { table1 = _bpawn_advance1; table2 = _bpawn_advance2; table_attack = _bpawn_attack; } if(NORMAL == type) { attackRange = table1[sq] & ~allPieces; if(attackRange) { attackRange |= table2[sq] & ~allPieces; } } else { /* capture */ attackRange = table_attack[sq]; /* check for ep */ if(epSquare != -1) { if(table_attack[sq] & _mask[epSquare]) { attackRange |= _mask[epSquare]; } } } } else if(IS_KNIGHT(piece)) { attackRange = _knight[sq]; } else if(IS_BISHOP(piece)) { rot_a1h8_allPieces = rotate_a1h8(allPieces); state = A1H8_STATE(rot_a1h8_allPieces, sq); attackRange = _a1h8[sq][state]; rot_h1a8_allPieces = rotate_h1a8(allPieces); state = H1A8_STATE(rot_h1a8_allPieces, sq); attackRange |= _h1a8[sq][state]; } else if(IS_ROOK(piece)) { rank = sq / 8; file = sq % 8; state = RANK_STATE(allPieces, rank); attackRange = _horz[sq][state]; rotAllPieces = rotate(allPieces); state = FILE_STATE(rotAllPieces, file); attackRange |= _vert[sq][state]; } else if(IS_QUEEN(piece)) { /* rook like moves */ rank = sq / 8; file = sq % 8; state = RANK_STATE(allPieces, rank); attackRange = _horz[sq][state]; rotAllPieces = rotate(allPieces); state = FILE_STATE(rotAllPieces, file); attackRange |= _vert[sq][state]; /* bishop like moves */ rot_a1h8_allPieces = rotate_a1h8(allPieces); state = A1H8_STATE(rot_a1h8_allPieces, sq); attackRange |= _a1h8[sq][state]; rot_h1a8_allPieces = rotate_h1a8(allPieces); state = H1A8_STATE(rot_h1a8_allPieces, sq); attackRange |= _h1a8[sq][state]; } else { /* Something is wrong, I don't know which piece this is. * This must NEVER happen; move generation is screwed. */ assert(0); } return attackRange; }
int invalid_char_class(struct creature *ch, struct obj_data *obj) { // Protected object if (IS_PC(ch) && obj->shared->owner_id != 0 && obj->shared->owner_id != GET_IDNUM(ch)) { return true; } // Unapproved object if (!OBJ_APPROVED(obj) && !is_tester(ch) && GET_LEVEL(ch) < LVL_IMMORT) return true; // Anti class restrictions if ((IS_OBJ_STAT(obj, ITEM_ANTI_MAGIC_USER) && IS_MAGIC_USER(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_CLERIC) && IS_CLERIC(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_WARRIOR) && IS_WARRIOR(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_THIEF) && IS_THIEF(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_BARB) && IS_BARB(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_PSYCHIC) && IS_PSYCHIC(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_PHYSIC) && IS_PHYSIC(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_CYBORG) && IS_CYBORG(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_KNIGHT) && IS_KNIGHT(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_RANGER) && IS_RANGER(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_BARD) && IS_BARD(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_MONK) && IS_MONK(ch)) || (IS_OBJ_STAT2(obj, ITEM2_ANTI_MERC) && IS_MERC(ch))) return true; // Required class restrictions - any one of them must be met if ((IS_OBJ_STAT3(obj, ITEM3_REQ_MAGE) && IS_MAGE(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_CLERIC) && IS_CLERIC(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_THIEF) && IS_THIEF(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_WARRIOR) && IS_WARRIOR(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_BARB) && IS_BARB(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_PSIONIC) && IS_PSIONIC(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_PHYSIC) && IS_PHYSIC(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_CYBORG) && IS_CYBORG(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_KNIGHT) && IS_KNIGHT(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_RANGER) && IS_RANGER(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_BARD) && IS_BARD(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_MONK) && IS_MONK(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_VAMPIRE) && IS_VAMPIRE(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_MERCENARY) && IS_MERC(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_SPARE1) && IS_SPARE1(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_SPARE2) && IS_SPARE2(ch)) || (IS_OBJ_STAT3(obj, ITEM3_REQ_SPARE3) && IS_SPARE3(ch))) return false; // A required class existed and the creature didn't fulfill any if (IS_OBJ_STAT3(obj, ITEM3_REQ_MAGE | ITEM3_REQ_CLERIC | ITEM3_REQ_THIEF | ITEM3_REQ_WARRIOR | ITEM3_REQ_BARB | ITEM3_REQ_PSIONIC | ITEM3_REQ_PHYSIC | ITEM3_REQ_CYBORG | ITEM3_REQ_KNIGHT | ITEM3_REQ_RANGER | ITEM3_REQ_BARD | ITEM3_REQ_MONK | ITEM3_REQ_VAMPIRE | ITEM3_REQ_MERCENARY | ITEM3_REQ_SPARE1 | ITEM3_REQ_SPARE2 | ITEM3_REQ_SPARE3)) return true; // Passes all tests return false; }