HEADER_DECLARE bool Term_exact_eq(Term* a, Term* b){ a = chase(a); b = chase(b); if(a->type != b->type){ return false; } switch(a->type){ case MOVED: fatal_error("Found a moved term when comparing terms"); case VAR: return a == b; case INTEGER: return a->data.integer == b->data.integer; case STRING: return !Buffer_cmp(&a->data.string, &b->data.string); case FUNCTOR: if(a->data.functor.atom != b->data.functor.atom){ return false; } if(a->data.functor.size != b->data.functor.size){ return false; } for(int i = 0; i < a->data.functor.size; i++){ if(!Term_exact_eq(a->data.functor.args[i], b->data.functor.args[i])){ return false; } } return true; case DICT: fatal_error("unimplemented: exact_eq dict"); } UNREACHABLE; }
int pushsnake(void) { int i, bonus; int issame = 0; struct point tmp; /* * My manual says times doesn't return a value. Furthermore, the * snake should get his turn every time no matter if the user is * on a fast terminal with typematic keys or not. * So I have taken the call to times out. */ for (i = 4; i >= 0; i--) if (same(&snake[i], &snake[5])) issame++; if (!issame) pchar(&snake[5], ' '); /* Need the following to catch you if you step on the snake's tail */ tmp.col = snake[5].col; tmp.line = snake[5].line; for (i = 4; i >= 0; i--) snake[i + 1] = snake[i]; chase(&snake[0], &snake[1]); pchar(&snake[1], SNAKETAIL); pchar(&snake[0], SNAKEHEAD); for (i = 0; i < 6; i++) { if ((same(&snake[i], &you)) || (same(&tmp, &you))) { surround(&you); i = (cashvalue) % 10; bonus = arc4random_uniform(10); mvprintw(lcnt + 1, 0, "%d\n", bonus); refresh(); delay(30); if (bonus == i) { spacewarp(1); #ifdef LOGGING logit("bonus"); #endif flushinp(); return(1); } flushinp(); endwin(); if (loot >= penalty) { printf("\nYou and your $%d have been eaten\n", cashvalue); } else { printf("\nThe snake ate you. You owe $%d.\n", -cashvalue); } #ifdef LOGGING logit("eaten"); #endif length(moves); snscore(TOPN); close(rawscores); exit(0); } } return(0); }
HEADER_DECLARE hash_t hash_rec(Term* term, hash_t hash){ term = chase(term); switch(term->type){ case INTEGER: return hash_integer(term->data.integer, hash); case FUNCTOR: hash = hash_atom(term->data.functor.atom, hash); functor_size_t size = term->data.functor.size; if(size){ hash = hash_byte(size, hash); for(functor_size_t i = 0; i < size; i++){ hash = hash_rec(term->data.functor.args[i], hash); } } return hash; case STRING: return hash_string(&term->data.string, hash); case VAR: fatal_error("Cannot hash variable '%s'", term->data.var.name); case DICT: fatal_error("unimplemented: hash dict"); case MOVED: fatal_error("Cannot hash a moved term"); } UNREACHABLE; }
void cksignal(Signal *s) { int i, j, pin, wc; float length, cap, rise_time, prop_delay, ok_length, delay_per; Wire *w; Chip *c; Line *l; if((s->type != NORMSIG) || (s->n == 0)) return; cap = device_cap(s); for (w = s->wires; w; w = w->next) for(i = 0; i < w->ninf; i++) for(j=0; j<s->n; j++) if (pteq(w->inflections[i].p, s->pins[j].p)) if ((c = (Chip *) symlook(s->coords[j].chip, S_CHIP, (void *) 0)) == 0) f_major("chip %s not found", s->coords[j].chip); else if (isdriver(c->type->tt[s->coords[j].pin-1])) { rise_time = get_rise(c->type->family); l = (Line *) pinlook(XY(s->pins[j].p.x, s->pins[j].p.y), 0); length = chase(l, 0); prop_delay = sqrt(L0 * length * (C0 * length + cap)); delay_per = sqrt(L0 * (C0 + cap / length)); ok_length = (rise_time * 1000.0) / (konstant * delay_per); if (length > ok_length) fprint(1, "%s (%C): %f mils > %f mils, z = %f\n", s->name, s->coords[j], length, ok_length, sqrt((L0 * length) / (C0 * length + cap))); /***fprint(1, "%s : %C = %f > %f, %f, %f, %f = %f\n", s -> name, s->coords[j], length, ok_length, L0 * length, C0 * length, cap, prop_delay); ***/ } }
float chase(Line *l, int level) { Line *connecting; Wire *w; int ip; float l_length, r_length, max_length; Point lastPt; if (!l) return(0.0); if (l -> length > 0.0) return(l -> length); max_length = 0.0; for(; l; l = l->connect) { l_length = r_length = 0.0; w = l->wire; lastPt = w->inflections[0].p; for(ip=0; ip<w->ninf; ip++) { if (ip <= l->inf) l_length += Euclidian(lastPt, w->inflections[ip].p); else r_length += Euclidian(lastPt, w->inflections[ip].p); lastPt = w->inflections[ip].p; } l -> length = max(l_length, r_length); l_length = r_length = 0.0; for(ip=0; ip<w->ninf; ip++) if (ip != l->inf) for (connecting = (Line *) pinlook(XY(w->inflections[ip].p.x, w->inflections[ip].p.y), 0); connecting; connecting = connecting -> connect) if (connecting -> wire != w) r_length = max(r_length, chase(connecting, level+1)); l -> length += r_length; max_length = max(max_length, l -> length); } return(max_length); }
HEADER_DECLARE integer_t Integer_get(Term* term){ term = chase(term); if(term->type != INTEGER){ fatal_error("expected integer"); } return term->data.integer; }
//Return a reaction based on state Enemy::Reaction Enemy::ruminate() { //Update player presence player_ = getPlayer_(); play_ = (player_ != nullptr); //Change states based on behaviour float hpf = (float)getHP() / (float)(startingHP_); //Distance to player, if she's there float between = FLT_MAX; if (play_) between = (getPosition() - player_->getPosition()).Length(); //If the player's dead, hang ten if (!play_) stateOfMind_ = IDLE; //Flee if hurt else if (hpf < ouch_[brainStem_.pain_tolerance]) stateOfMind_ = FLEE; //Otherwise think about what we should do else switch (stateOfMind_) { //If we're running, check if we're healthy enough to stop case FLEE: if (hpf > ouch_[brainStem_.pain_tolerance]) stateOfMind_ = IDLE; //If we're chilling, check if the player is messing with the bull case IDLE: if (play_ && between < 128 && between <= chaseRange_[brainStem_.personal_space] || angry_ == angryMAX_) stateOfMind_ = CHASE; //If we're chasing, make sure we can still see him case CHASE: if (play_ && between > chaseRangeMAX_[brainStem_.perserverance]) stateOfMind_ = IDLE; } //Execute our current mood switch (stateOfMind_) { case IDLE: //std::cout << "idle" << std::endl; return idle(); break; case CHASE: //std::cout << "chase" << std::endl; return chase(); break; case FLEE: //std::cout << "flee" << std::endl; return flee(); break; } return Reaction(); }
HEADER_DECLARE atom_t intern(Term* str){ FRAME_ENTER_1(str); assert(str->type == STRING, "cannot intern non-string"); FRAME_LOCAL(term) = chase(HashTable_get(root.interned, str)); if(!Var_is_terminal(term)){ guarantee(is_Atom(term), "interned term is not an atom"); D_ATOM{ debug("already interned `%s' as %lu\n", str->data.string.ptr, term->data.functor.atom); } FRAME_RETURN(atom_t, term->data.functor.atom); }
int checkDetectionRadius(glm:: mat4 tar[], float tarBR[] , int nTargets) { for (int i = 0; i < nTargets; i++) { if (collision(tar[i], tarBR[i], 0)) { chase(tar[i]); printf("MISSILE FOUND SITE %d\n",i); return i; } } return -1; }
//------------------------------------------------------------------------------ int __attribute__((OS_main)) main(void) { DDRC = 0xFF; PORTC = 0xFF; DDRB = 0xFF; PORTB = 0xFF; DDRD = 0xFF; PORTD = 0xFF; H_SLEEP; rnaInit(); sei(); TCCR0B = 1<<CS00; _delay_ms(100); srand( TCNT0 ); TIMSK0 = 1<<TOIE0; // enable the interrupt for( unsigned char i=0; i<16; i++ ) { intensity[i] = 0x0; } for(;;) { compute(20); glowPick(16); chase(1); glowRandom(20); chase(2); randomPick(128); chase(1); } }
void Ghost::navigate(Direction directions) { Direction opposite = NONE; if (direction) { switch (direction) { case UP: opposite = DOWN; break; case DOWN: opposite = UP; break; case LEFT: opposite = RIGHT; break; case RIGHT: opposite = LEFT; break; } directions = (Direction)(directions & ~opposite); if (directions == NONE) directions = opposite; } switch (directions) { case UP: direction = UP; return; case DOWN: direction = DOWN; return; case LEFT: direction = LEFT; return; case RIGHT: direction = RIGHT; return; default: break; } switch (mode) { case INACTIVE: break; case CHASE: direction = chase(targetX, targetY, directions); break; case SCATTER: direction = chase(homeX, homeY, directions); break; case AFRAID: direction = flee(directions); break; case HOME: break; } }
void Ghost::move() { if(isInsideGhostHouse()) { if(isFree()) { if(!isCaught()) { release(); } } } else if(isOnTheMove()) localMove(); else if(isCaught()) goHome(); else if(areGhostsScared()) escape(); else if(isScattering()) scatter(); else chase(); }
unsigned int Thief::think() { switch( _state ) { case SEEK: seek(); // Procura por uma vítima break; case CHASE: chase(); // Persegue uma vítima break; case STEAL: steal(); // Rouba o meteorito break; } return 0; }
void zombie::move() { last_pos = pos; if(chasing) { chase(); } else { int new_pos_x[4],new_pos_y[4]; if(pos.x!=0) { new_pos_x[0]=pos.x-1; new_pos_y[0]=pos.y; } else { new_pos_x[0]=-1; new_pos_y[0]=-1; } if(pos.x!=X-1) { new_pos_x[2]=pos.x+1; new_pos_y[2]=pos.y; } else { new_pos_x[2]=-1; new_pos_y[2]=-1; } if(pos.y!=0) { new_pos_x[3]=pos.x; new_pos_y[3]=pos.y-1; } else { new_pos_x[3]=-1; new_pos_y[3]=-1; } if(pos.y!=X-1) { new_pos_x[1]=pos.x; new_pos_y[1]=pos.y+1; } else { new_pos_x[1]=-1; new_pos_y[1]=-1; } int decision = decide( (new_pos_x[0]!=-1 && new_pos_y[0]!=-1)?1.0:0 ,(new_pos_x[1]!=-1 && new_pos_y[1]!=-1)?1.0:0,(new_pos_x[2]!=-1 && new_pos_y[2]!=-1)?1.0:0,(new_pos_x[3]!=-1 && new_pos_y[3]!=-1)?1.0:0); switch(decision) { case 0:moving(*it_zombie,grid[pos.x-1][pos.y]); break; case 1:moving(*it_zombie,grid[pos.x][pos.y-1]); break; case 2:moving(*it_zombie,grid[pos.x+1][pos.y]); break; case 3:moving(*it_zombie,grid[pos.x][pos.y+1]); break; } } }
//Lennard-Jones based AI void Enemy::ljpTest() { b2Vec2 sum(0, 0); b2Vec2 flock(0, 0); b2Vec2 chase(0, 0); b2Vec2 fire(0, 0); //Chase and fire at player? Shape* player = getPlayer_(); if (player) { b2Vec2 myPos = getPosition(); b2Vec2 pPos = player->getPosition(); b2Vec2 between = (pPos - myPos); float dist = between.Length(); if (!chasing_ && dist < chaseRange_[3]) { chasing_ = true; } if (chasing_ && dist < chaseRangeMAX_[4]) { chase = LJP(pPos, 100.f, 200.f, 1.0, 1.8); } else chasing_ = false; //Fire if in visible range if (dist < visRange_[3]) { fire = LJP(pPos, 100, 0, 2.0, 0); } } if (chasing_) orient(chase); //Swarm to shapes int count = 0; for (Enemy* v : swarm_) { if (v != this) { b2Vec2 myPos = getPosition(); b2Vec2 theirPos = v->getPosition(); b2Vec2 between = theirPos - myPos; float minDist = v->getSize() + size_; float dist = between.Length(); if (between.Length() < flockRange_) { b2Vec2 steer(0, 0); if (!chasing_) steer = LJP(theirPos, 75.f, 300.f, 1.0f, 1.8f); else if (v->getVertices() == vertices_) steer = LJP(theirPos, 0, 100.f, 0, 1.8f); else steer = LJP(theirPos, 0, 100.f, 0, 1.8f); if (steer.x != 0 && steer.y != 0) { sum += steer; count++; } } } } //get average if (count > 0) { sum.x /= static_cast<float>(count); sum.y /= static_cast<float>(count); } else sum = b2Vec2_zero; //If we didn't want to fire float seePlayer = fire.Length(); if (seePlayer == 0) { angry_ -= angryMAX_ / triggerSatisfaction_[4]; } else { orient(fire); chill_ = 0; angry_ += seePlayer; } //If we're mad enough float ammo = (float)getWeaponBar() / (float)getWeaponBarMAX(); if (angry_ > angryMAX_ && seePlayer != 0) { if (fireAt(fire, 0.2f)) { angry_ -= triggerSatisfaction_[4]; } else release(); if (ammo< 0.1f) reup(); } angry_ = fmax(angry_, 0); //Chill out when idle if (angry_ == 0 && seePlayer == 0) { chill_ -= 1; if (chill_ <= chillMIN_) { if (ammo < 1.f) reup(); spin(-0.05f); } } chill_ = fmax(chill_, chillMIN_); move(chase + sum); }
void AI_main(struct RoboAI *ai, struct blob *blobs, void *state) { /************************************************************************* You will be working with a state-based AI. You are free to determine how many states there will be, what each state will represent, and what actions the robot will perform based on the state as well as the state transitions. You must *FULLY* document your state representation in the report Here two states are defined: State 0,100,200 - Before robot ID has taken place (this state is the initial state, or is the result of pressing 'r' to reset the AI) State 1,101,201 - State after robot ID has taken place. At this point the AI knows where the robot is, as well as where the opponent and ball are (if visible on the playfield) Relevant UI keyboard commands: 'r' - reset the AI. Will set AI state to zero and re-initialize the AI data structure. 't' - Toggle the AI routine (i.e. start/stop calls to AI_main() ). 'o' - Robot immediate all-stop! - do not allow your NXT to get damaged! ** Do not change the behaviour of the robot ID routine ** **************************************************************************/ if (ai->st.state == 0 || ai->st.state == 100 || ai->st.state == 200) // Initial set up - find own, ball, and opponent blobs { // Carry out self id process. fprintf(stderr, "Initial state, self-id in progress...\n"); id_bot(ai, blobs); if ((ai->st.state % 100) != 0) // The id_bot() routine will change the AI state to initial state + 1 { // if robot identification is successful. if (ai->st.self->cx[0] >= 512) ai->st.side = 1; else ai->st.side = 0; all_stop(); clear_motion_flags(ai); fprintf(stderr, "Self-ID complete. Current position: (%f,%f), current heading: [%f, %f], AI state=%d\n", ai->st.self->cx[0], ai->st.self->cy[0], ai->st.self->mx, ai->st.self->my, ai->st.state); } } else { /**************************************************************************** TO DO: You will need to replace this 'catch-all' code with actual program logic to have the robot do its work depending on its current state. After id_bot() has successfully completed its work, the state should be 1 - if the bot is in SOCCER mode 101 - if the bot is in PENALTY mode 201 - if the bot is in CHASE mode Your AI code needs to handle these states and their associated state transitions which will determine the robot's behaviour for each mode. *****************************************************************************/ // track_agents(ai,blobs); // Currently, does nothing but endlessly track // fprintf(stderr,"Just trackin'!\n"); // bot, opponent, and ball. switch(ai->st.state){ case 101: kick(); sleep(2); break; case 201: chase(ai); break; } } }
void do_chase(struct thing *th, int flee) { struct room *rer; /* room of chaser */ struct room *ree; /* room of chasee */ struct room *old_room; /* old room of monster */ struct room *new_room; /* new room of monster */ int i, mindist = INT_MAX, maxdist = INT_MIN, dist = INT_MIN; int last_door = -1; /* Door we just came from */ int stoprun = FALSE; /* TRUE means we are there */ int rundoor; /* TRUE means run to a door */ int hit_bad = FALSE; /* TRUE means hit bad monster */ int mon_attack; /* TRUE means find a monster to hit */ char sch; struct linked_list *item; coord this; /* Temporary destination for chaser */ if (!th->t_ischasing) return; /* Make sure the monster can move */ if (th->t_no_move != 0) { th->t_no_move--; return; } /* * Bad monsters check for a good monster to hit, friendly monsters * check for a bad monster to hit. */ mon_attack = FALSE; if (good_monster(*th)) { hit_bad = TRUE; mon_attack = TRUE; } else if (on(*th, ISMEAN)) { hit_bad = FALSE; mon_attack = TRUE; } if (mon_attack) { struct linked_list *mon_to_hit; mon_to_hit = f_mons_a(th->t_pos.y, th->t_pos.x, hit_bad); if (mon_to_hit) { mon_mon_attack(th, mon_to_hit, pick_weap(th), NOTHROWN); return; } } /* no nearby monster to hit */ rer = roomin(th->t_pos); /* Find room of chaser */ ree = roomin(th->t_chasee->t_pos); /* Find room of chasee */ /* * We don't count doors as inside rooms for this routine */ if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR) rer = NULL; this = th->t_chasee->t_pos; /* * If we are not in a corridor and not a phasing monster, then if we * are running after the player, we run to a door if he is not in the * same room. If we are fleeing, we run to a door if he IS in the * same room. Note: We don't bother with doors in mazes. Phasing * monsters don't need to look for doors. There are no doors in mazes * and throne rooms. */ if (levtype != MAZELEV && levtype != THRONE && rer != NULL && off(*th, CANINWALL)) { if (flee) rundoor = (rer == ree); else rundoor = (rer != ree); } else rundoor = FALSE; if (rundoor) { coord d_exit; /* A particular door */ int exity, exitx; /* Door's coordinates */ if (th->t_doorgoal != -1) { /* Do we already have the goal? */ this = rer->r_exit[th->t_doorgoal]; dist = 0; /* Indicate that we have our door */ } else for (i = 0; i < rer->r_nexits; i++) { /* Loop through doors */ d_exit = rer->r_exit[i]; exity = d_exit.y; exitx = d_exit.x; /* Avoid secret doors */ if (mvwinch(stdscr, exity, exitx) == DOOR) { /* Were we just on this door? */ if (ce(d_exit, th->t_oldpos)) last_door = i; else { dist = DISTANCE(th->t_chasee->t_pos, d_exit); /* * If fleeing, we want to * maximize distance from * door to what we flee, and * minimize distance from * door to us. */ if (flee) dist-=DISTANCE(th->t_pos,d_exit); /* * Maximize distance if * fleeing, otherwise * minimize it */ if ((flee && (dist > maxdist)) || (!flee && (dist < mindist))) { th->t_doorgoal = i; /* Use this door */ this = d_exit; mindist = maxdist = dist; } } } } /* Could we not find a door? */ if (dist == INT_MIN) { /* If we were on a door, go ahead and use it */ if (last_door != -1) { th->t_doorgoal = last_door; this = th->t_oldpos; dist = 0; /* Indicate that we found a door */ } } /* Indicate that we do not want to flee from the door */ if (dist != INT_MIN) flee = FALSE; } else th->t_doorgoal = -1; /* Not going to any door */ /* * this now contains what we want to run to this time so we run to * it. If we hit it we either want to fight it or stop running */ if (!chase(th, &this, flee)) { if (ce(th->t_nxtpos, hero)) { /* merchants try to sell something */ if (on(*th, CANSELL)) { sell(th); return; } else if (off(*th, ISFRIENDLY) && off(*th, ISCHARMED) && (off(*th, CANFLY) || (on(*th, CANFLY) && rnd(2)))) attack(th, pick_weap(th), FALSE); return; } else if (on(*th, NOMOVE)) stoprun = TRUE; } if (!curr_mons) return; /* Did monster get itself killed? */ if (on(*th, NOMOVE)) return; /* If we have a scavenger, it can pick something up */ if ((item = find_obj(th->t_nxtpos.y, th->t_nxtpos.x)) != NULL) { struct linked_list *node, *top = item; struct object *obt; while(top) { /* grab all objects that qualify */ struct object *obj = OBJPTR(item); obt = OBJPTR(top); node = obt->next_obj; if (on(*th, ISSCAVENGE) || ((on(*th, CANWIELD) || on(*th, CANSHOOT)) && (obj->o_type == WEAPON || obj->o_type == ARMOR)) || (on(*th, CANCAST) && is_magic(obj))) { rem_obj(top, FALSE); attach(th->t_pack, top); } top = node; } light(&hero); } mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch); sch = CCHAR( mvwinch(cw, th->t_nxtpos.y, th->t_nxtpos.x) ); /* Get old and new room of monster */ old_room = roomin(th->t_pos); new_room = roomin(th->t_nxtpos); /* If the monster can illuminate rooms, check for a change */ if (on(*th, HASFIRE)) { /* Is monster entering a room? */ if (old_room != new_room && new_room != NULL) { new_room->r_flags |= HASFIRE; new_room->r_fires++; if (cansee(th->t_nxtpos.y, th->t_nxtpos.x) && new_room->r_fires==1) light(&hero); } /* Is monster leaving a room? */ if (old_room != new_room && old_room != NULL) { if (--(old_room->r_fires) <= 0) { old_room->r_flags &= ~HASFIRE; if (cansee(th->t_pos.y, th->t_pos.x)) light(&th->t_pos); } } } /* * If monster is entering player's room and player can see it, stop * the player's running. */ if (new_room != old_room && new_room != NULL && new_room == ree && cansee(th->t_nxtpos.y, th->t_nxtpos.x) && (off(*th, ISINVIS) || (off(*th, ISSHADOW) || rnd(10) == 0) || on(player, CANSEE)) && off(*th, CANSURPRISE)) running = FALSE; if (rer != NULL && (rer->r_flags & ISDARK) && !(rer->r_flags & HASFIRE) && sch == FLOOR && DISTANCE(th->t_nxtpos, th->t_pos) < see_dist && off(player, ISBLIND)) th->t_oldch = ' '; else th->t_oldch = sch; if (cansee(th->t_nxtpos.y, th->t_nxtpos.x) && off(*th, ISINWALL) && ((off(*th, ISINVIS) && (off(*th, ISSHADOW) || rnd(100) < 10)) || on(player, CANSEE)) && off(*th, CANSURPRISE)) mvwaddch(cw, th->t_nxtpos.y, th->t_nxtpos.x, th->t_type); mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' '); mvwaddch(mw, th->t_nxtpos.y, th->t_nxtpos.x, th->t_type); /* Record monster's last position (if new one is different) */ if (!ce(th->t_nxtpos, th->t_pos)) th->t_oldpos = th->t_pos; th->t_pos = th->t_nxtpos; /* Mark the monster's new position */ /* If the monster is on a trap, trap it */ sch = CCHAR(mvinch(th->t_nxtpos.y, th->t_nxtpos.x)); if (isatrap(sch)) { debug("Monster trapped by %c.", sch); if (cansee(th->t_nxtpos.y, th->t_nxtpos.x)) th->t_oldch = sch; be_trapped(th, th->t_nxtpos); } /* And stop running if need be */ if (stoprun && ce(th->t_pos, th->t_chasee->t_pos)) { th->t_ischasing = FALSE; turn_off(*th, ISRUN); } }
/*! \brief Actions for one entity * \date 20040310 PH added TARGET movemode, broke out chase into separate function * * Process an individual active entity. If the entity in question * is #0 (main character) and the party is not automated, then allow * for player input. * * \param target_entity Index of entity * \date 20040310 PH added TARGET movemode, broke out chase into separate function */ static void process_entity(t_entity target_entity) { s_entity *ent = &g_ent[target_entity]; s_player *player = 0; ent->scount = 0; if (!ent->active) { return; } if (!ent->moving) { if (target_entity == 0 && !autoparty) { player_move(); if (ent->moving && display_desc == 1) { display_desc = 0; } return; } switch (ent->movemode) { case MM_STAND: return; case MM_WANDER: wander(target_entity); break; case MM_SCRIPT: entscript(target_entity); break; case MM_CHASE: chase(target_entity); break; case MM_TARGET: target(target_entity); break; } } else /* if (.moving==0) */ { if (ent->tilex * TILE_W > ent->x) { ++ent->x; } if (ent->tilex * TILE_W < ent->x) { --ent->x; } if (ent->tiley * TILE_H > ent->y) { ++ent->y; } if (ent->tiley * TILE_H < ent->y) { --ent->y; } ent->movcnt--; if (ent->framectr < 20) { ent->framectr++; } else { ent->framectr = 0; } if (ent->movcnt == 0) { ent->moving = 0; if (target_entity < PSIZE) { player = &party[pidx[target_entity]]; if (steps < STEPS_NEEDED) { steps++; } if (player->sts[S_POISON] > 0) { if (player->hp > 1) { player->hp--; } play_effect(21, 128); } if (player->eqp[EQP_SPECIAL] == I_REGENERATOR) { if (player->hp < player->mhp) { player->hp++; } } } if (target_entity == 0) { zone_check(); } } if (target_entity == 0 && vfollow == 1) { calc_viewport(0); } } }
/* * do_chase: * Make one thing chase another. */ int do_chase(THING *th) { coord *cp; struct room *rer, *ree; /* room of chaser, room of chasee */ int mindist = 32767, curdist; int stoprun = FALSE; /* TRUE means we are there */ int door; THING *obj; coord this; /* Temporary destination for chaser */ rer = th->t_room; /* Find room of chaser */ if (on(*th, ISGREED) && rer->r_goldval == 0) th->t_dest = &hero; /* If gold has been taken, run after hero */ if (th->t_dest == &hero) /* Find room of chasee */ ree = proom; else ree = roomin(th->t_dest); /* * We don't count doors as inside rooms for this routine */ door = (chat(th->t_pos.y, th->t_pos.x) == DOOR); /* * If the object of our desire is in a different room, * and we are not in a corridor, run to the door nearest to * our goal. */ over: if (rer != ree) { for (cp = rer->r_exit; cp < &rer->r_exit[rer->r_nexits]; cp++) { curdist = dist_cp(th->t_dest, cp); if (curdist < mindist) { this = *cp; mindist = curdist; } } if (door) { rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM]; door = FALSE; goto over; } } else { this = *th->t_dest; /* * For dragons check and see if (a) the hero is on a straight * line from it, and (b) that it is within shooting distance, * but outside of striking range. */ if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x || abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x)) && dist_cp(&th->t_pos, &hero) <= BOLT_LENGTH * BOLT_LENGTH && !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0) { delta.y = sign(hero.y - th->t_pos.y); delta.x = sign(hero.x - th->t_pos.x); if (has_hit) endmsg(); fire_bolt(&th->t_pos, &delta, "flame"); running = FALSE; count = 0; quiet = 0; if (to_death && !on(*th, ISTARGET)) { to_death = FALSE; kamikaze = FALSE; } return(0); } } /* * This now contains what we want to run to this time * so we run to it. If we hit it we either want to fight it * or stop running */ if (!chase(th, &this)) { if (ce(this, hero)) { return( attack(th) ); } else if (ce(this, *th->t_dest)) { for (obj = lvl_obj; obj != NULL; obj = next(obj)) if (th->t_dest == &obj->o_pos) { detach(lvl_obj, obj); attach(th->t_pack, obj); chat(obj->o_pos.y, obj->o_pos.x) = (th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR; th->t_dest = find_dest(th); break; } if (th->t_type != 'F') stoprun = TRUE; } } else { if (th->t_type == 'F') return(0); } relocate(th, &ch_ret); /* * And stop running if need be */ if (stoprun && ce(th->t_pos, *(th->t_dest))) th->t_flags &= ~ISRUN; return(0); }
int main(int argc, char *argv[]) { struct sigaction sa; int ch, i; if (pledge("stdio rpath wpath cpath tty", NULL) == -1) err(1, "pledge"); #ifdef LOGGING const char *home; home = getenv("HOME"); if (home == NULL || *home == '\0') err(1, "getenv"); snprintf(logpath, sizeof(logpath), "%s/%s", home, ".snake.log"); logfile = fopen(logpath, "a"); #endif while ((ch = getopt(argc, argv, "hl:stw:")) != -1) switch ((char)ch) { case 'w': /* width */ ccnt = strtonum(optarg, 1, INT_MAX, NULL); break; case 'l': /* length */ lcnt = strtonum(optarg, 1, INT_MAX, NULL); break; case 's': /* score */ if (readscores(0)) snscore(0); else printf("no scores so far\n"); return 0; break; case 't': /* slow terminal */ fast = 0; break; case 'h': default: fprintf(stderr, "usage: %s [-st] [-l length] " "[-w width]\n", getprogname()); return 1; } readscores(1); penalty = loot = 0; initscr(); #ifdef KEY_LEFT keypad(stdscr, TRUE); #endif nonl(); cbreak(); noecho(); if (!lcnt || lcnt > LINES - 2) lcnt = LINES - 2; if (!ccnt || ccnt > COLS - 3) ccnt = COLS - 3; i = lcnt < ccnt ? lcnt : ccnt; if (i < 4) { endwin(); errx(1, "screen too small for a fair game."); } /* * chunk is the amount of money the user gets for each $. * The formula below tries to be fair for various screen sizes. * We only pay attention to the smaller of the 2 edges, since * that seems to be the bottleneck. * This formula is a hyperbola which includes the following points: * (24, $25) (original scoring algorithm) * (12, $40) (experimentally derived by the "feel") * (48, $15) (a guess) * This will give a 4x4 screen $99/shot. We don't allow anything * smaller than 4x4 because there is a 3x3 game where you can win * an infinite amount of money. */ if (i < 12) i = 12; /* otherwise it isn't fair */ /* * Compensate for border. This really changes the game since * the screen is two squares smaller but we want the default * to be $25, and the high scores on small screens were a bit * much anyway. */ i += 2; chunk = (675.0 / (i + 6)) + 2.5; /* min screen edge */ memset(&sa, 0, sizeof sa); sigemptyset(&sa.sa_mask); sa.sa_handler = stop; sigaction(SIGINT, &sa, NULL); snrand(&finish); snrand(&you); snrand(&money); snrand(&snake[0]); for (i = 1; i < 6; i++) chase(&snake[i], &snake[i - 1]); setup(); mainloop(); return 0; }
int do_chase(struct thing *th) { struct room *rer, *ree; /* room of chaser, room of chasee */ int mindist = 32767, i, dist; int stoprun = FALSE; /* TRUE means we are there */ int sch; coord this; /* Temporary destination for chaser */ rer = roomin(&th->t_pos); /* Find room of chaser */ ree = roomin(th->t_dest); /* Find room of chasee */ /* * We don't count doors as inside rooms for this routine */ if (CMVWINCH(stdscr, th->t_pos.y, th->t_pos.x) == DOOR) rer = NULL; this = *th->t_dest; /* * If the object of our desire is in a different room, * than we are and we ar not in a corridor, run to the * door nearest to our goal. */ if (rer != NULL && rer != ree) for (i = 0; i < rer->r_nexits; i++) /* loop through doors */ { dist = DISTANCE(th->t_dest->y, th->t_dest->x, rer->r_exit[i].y, rer->r_exit[i].x); if (dist < mindist) /* minimize distance */ { this = rer->r_exit[i]; mindist = dist; } } /* * this now contains what we want to run to this time * so we run to it. If we hit it we either want to fight it * or stop running */ if (!chase(th, &this)) { if (ce(this, hero)) { return( attack(th) ); } else if (th->t_type != 'F') stoprun = TRUE; } else if (th->t_type == 'F') return(0); mvwaddrawch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch); sch = CMVWINCH(cw, ch_ret.y, ch_ret.x); if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR && DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3 && off(player, ISBLIND)) th->t_oldch = ' '; else th->t_oldch = sch; if (cansee(unc(ch_ret)) && !on(*th, ISINVIS)) mvwaddrawch(cw, ch_ret.y, ch_ret.x, th->t_type); mvwaddrawch(mw, th->t_pos.y, th->t_pos.x, ' '); mvwaddrawch(mw, ch_ret.y, ch_ret.x, th->t_type); th->t_pos = ch_ret; /* * And stop running if need be */ if (stoprun && ce(th->t_pos, *(th->t_dest))) th->t_flags &= ~ISRUN; return(0); }
/* * do_chase: * Make one thing chase another. */ void do_chase(struct thing *th, int flee) { register struct room *rer, *ree, /* room of chaser, room of chasee */ *old_room, /* old room of monster */ *new_room; /* new room of monster */ register int mindist = MAXINT, maxdist = MININT, dist = MININT, i, last_door = -1; /* Door we just came from */ register int stoprun = FALSE, /* TRUE means we are there */ rundoor; /* TRUE means run to a door */ int mdead = 0; register int sch; coord this; /* Temporary destination for chaser */ /* Make sure the monster can move */ if (th->t_no_move != 0) { th->t_no_move--; return; } rer = roomin(&th->t_pos); /* Find room of chaser */ ree = roomin(th->t_dest); /* Find room of chasee */ /* * We don't count doors as inside rooms for this routine */ if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR) rer = NULL; this = *th->t_dest; /* * If we are not in a corridor and not a Xorn, then if we are running * after the player, we run to a door if he is not in the same room. * If we are fleeing, we run to a door if he IS in the same room. * Note: We don't bother with doors in mazes. */ if (levtype != MAZELEV && rer != NULL && off(*th, CANINWALL)) { if (flee) rundoor = (rer == ree); else rundoor = (rer != ree); } else rundoor = FALSE; if (rundoor) { coord exit; /* A particular door */ int exity, exitx; /* Door's coordinates */ if (th->t_doorgoal != -1) { /* Do we already have the goal? */ this = rer->r_exit[th->t_doorgoal]; dist = 0; /* Indicate that we have our door */ } else for (i = 0; i < rer->r_nexits; i++) { /* Loop through doors */ exit = rer->r_exit[i]; exity = exit.y; exitx = exit.x; /* Avoid secret doors */ if (mvwinch(stdscr, exity, exitx) == DOOR) { /* Were we just on this door? */ if (ce(exit, th->t_oldpos)) last_door = i; else { dist = DISTANCE(th->t_dest->y, th->t_dest->x, exity, exitx); /* If fleeing, we want to maximize distance from door to * what we flee, and minimize distance from door to us. */ if (flee) dist -= DISTANCE(th->t_pos.y, th->t_pos.x, exity, exitx); /* Maximize distance if fleeing, otherwise minimize it */ if ((flee && (dist > maxdist)) || (!flee && (dist < mindist))) { th->t_doorgoal = i; /* Use this door */ this = exit; mindist = maxdist = dist; } } } } /* Could we not find a door? */ if (dist == MININT) { /* If we were on a door, go ahead and use it */ if (last_door != -1) { th->t_doorgoal = last_door; this = th->t_oldpos; dist = 0; /* Indicate that we found a door */ } } /* Indicate that we do not want to flee from the door */ if (dist != MININT) flee = FALSE; } else th->t_doorgoal = -1; /* Not going to any door */ /* * this now contains what we want to run to this time * so we run to it. If we hit it we either want to fight it * or stop running */ if (!chase(th, &this, flee, &mdead)) { if (ce(ch_ret, hero)) { /* merchants try to sell something */ if (on(*th, CANSELL)) sell(th); else if (on(*th, ISCHARMED)) {} /* future enhancements */ else if (on(*th, ISFRIENDLY)) {} else attack(th, NULL, FALSE); return; } else if (on(*th, NOMOVE)) stoprun = TRUE; } if (on(*th, ISDEAD)) return; /* Did monster get itself killed? */ if (on(*th, NOMOVE)) return; /* If we have a scavenger, it can pick something up */ if (on(*th, ISSCAVENGE)) { register struct linked_list *item; if ((item = find_obj(ch_ret.y, ch_ret.x)) != NULL) { register int floor = (roomin(&ch_ret) == NULL) ? PASSAGE : FLOOR; detach(lvl_obj, item); mvaddch(ch_ret.y, ch_ret.x, floor); mvwaddch(cw, ch_ret.y, ch_ret.x, floor); attach(th->t_pack, item); } } mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch); sch = CCHAR( mvwinch(cw, ch_ret.y, ch_ret.x) ); /* Get old and new room of monster */ old_room=roomin(&th->t_pos); new_room=roomin(&ch_ret); /* If the monster can illuminate rooms, check for a change */ if (on(*th, HASFIRE)) { /* Is monster entering a room? */ if (old_room != new_room && new_room != NULL) { new_room->r_flags |= HASFIRE; new_room->r_fires++; if (cansee(ch_ret.y, ch_ret.x) && new_room->r_fires == 1) light(&hero); } /* Is monster leaving a room? */ if (old_room != new_room && old_room != NULL) { if (--(old_room->r_fires) <= 0) { old_room->r_flags &= ~HASFIRE; if (cansee(th->t_pos.y, th->t_pos.x)) light(&th->t_pos); } } } /* If monster is entering player's room and player can see it, * stop the player's running. */ if (new_room != old_room && new_room != NULL && new_room == ree && cansee(unc(ch_ret)) && (off(*th, ISINVIS) || (off(*th, ISSHADOW) || rnd(10) == 0) || on(player, CANSEE)) && off(*th, CANSURPRISE)) running = FALSE; if (rer != NULL && (rer->r_flags & ISDARK) && !(rer->r_flags & HASFIRE) && sch == FLOOR && DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < see_dist && off(player, ISBLIND)) th->t_oldch = ' '; else th->t_oldch = sch; if (cansee(unc(ch_ret)) && off(*th, ISINWALL) && ((off(*th, ISINVIS) && (off(*th, ISSHADOW) || rnd(100) < 10)) || on(player, CANSEE)) && off(*th, CANSURPRISE)) mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type); mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' '); mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type); /* Record monster's last position (if new one is different) */ if (!ce(ch_ret, th->t_pos)) th->t_oldpos = th->t_pos; th->t_pos = ch_ret; /* Mark the monster's new position */ /* If the monster is on a trap, trap it */ sch = CCHAR( mvinch(ch_ret.y, ch_ret.x) ); if (isatrap(sch)) { debug("Monster trapped by %c.", sch); if (cansee(ch_ret.y, ch_ret.x)) th->t_oldch = sch; be_trapped(th, &ch_ret); } /* * And stop running if need be */ if (stoprun && ce(th->t_pos, *(th->t_dest))) turn_off(*th, ISRUN); }