int main(void) { World *w = new_world("Adventure In C"); struct room *current = cached_read_room(w, "start"); struct player me; initPlayer(&me, w); read_player(&me); push_alias(&me, "l", "look"); push_alias(&me, "u", "up"); push_alias(&me, "d", "down"); push_alias(&me, "lo", "look"); // Just an extra alias push_alias(&me, "h", "help"); push_alias(&me, "ex", "examine"); me.currentRoom = current; printf("%s enters the world.\n\n",me.name); look_player(&me); loop_player(&me); }
// Move the enemy void ENEMY::move() { // Advance the animation if(!chase && !burning) anim += 0.10f; else anim += 0.20f; if((int)anim > 3 || kicked) anim = 0.0f; // Advance the dying animation if we're actually dying if(dying) { die_anim -= 0.03f; // Create the blue "burning down" effect float px = get_real_x(); float py = get_real_y(); for(int f=0; f < RAND(2,10); f++) { float rnd = RANDF(-0.3f, 0.3f); VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py); pos.x += rnd; pos.z -= rnd; if(pos.y < 0.0f) pos.y = 0.0f; if(turning) pos.y += (turning_raise * 0.85f); VECT dir = 0.0f; float c1[4] = { 0.1f, 0.7f, 1, 1 }; float c2[4] = { 0.1f, 0.7f, 1, 0 }; add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star); } if(die_anim < 0.0f) { die_anim = 0.0f; alive = false; } return; } // Create some particle fire from the burning enemies if(burning) { VECT ppos(get_real_x(), 0.5f, get_real_y()); create_fire(ppos); } // Advance the turning animation if(turning) { // Raise up if(turning == 1) { turning_raise += 0.035f; if(turning_raise >= 1.0f) { turning_raise = 1.0f; turning++; } } // Turn else if(turning == 2) { turning_counter++; if(turning_counter == 5) { dir = nextdir; nextdir = dir + 1; if(nextdir > DIR_W) nextdir = DIR_N; } else if(turning_counter == 10) { dir = nextdir; turning++; } } // Go down else if(turning == 3) { turning_raise -= 0.035f; if(turning_raise <= 0.0f) { turning_raise = 0.0f; turning = 0; } } // Check the collision between the player #1 if(p1.alive && !p1.jumping) { float dx = get_real_x() - p1.get_real_x(); float dy = get_real_y() - p1.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p1.die(); die(); } } // Check the collision between the player #2 if(alive && two_players && p2.alive && !p2.jumping) { float dx = get_real_x() - p2.get_real_x(); float dy = get_real_y() - p2.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p2.die(); die(); } } return; } // If there is the lightning special power in progress, don't move the enemies which are // suffering from the lightning strikes if(special_power_pause && which_special_power == BLUE_POWER_LIGHTNING) { // Check if we're a target for(int f=0; f<ENEMY_AMOUNT; f++) { if(sp_lightning.targets[f] == this) { anim += 0.30f; if((int)anim > 3) anim = 0.0f; return; } } } // Don't move if the level is finished if(level_pause) return; // Check the traps if(traplist.size() > 0) { list<TRAP>::iterator t; for(t = traplist.begin(); t != traplist.end(); ++t) { if(x == (*t).x && y == (*t).y) { die(); return; } } } // Handle the burning, that is run around aimlessly if(burning) { if(!kicked) { // Reduce the burning time burn_time--; if(burn_time == 0) { die(); return; } // Choose a random direction if(RAND(0,100) > 50 && offset == 0.0f) { if(RAND(0,100) > 50) dir++; else dir--; if(dir > DIR_W) dir = DIR_N; else if(dir < DIR_N) dir = DIR_W; } // Move one step if(tx == x && ty == y) { offset = 0.0f; // Don't stop until there's a wall. switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check if the target is passable? if(map_solid(tx, ty)) { // Stop and choose a new dir tx = x; ty = y; dir += RAND(-1,1); if(dir < DIR_N) dir = DIR_W; else if(dir > DIR_W) dir = DIR_N; return; } } // Move towards the target tile if(offset < 1.0f && (tx != x || ty != y)) { offset += speed; // Check the collision between the player #1 if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p1.get_real_x(); float dy = get_real_y() - p1.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Turn around and run tx = x; ty = y; offset = 0.0f; dir += 2; if(dir > DIR_W) dir -= 4; } } // Check the collision between the player #2 if(two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p2.get_real_x(); float dy = get_real_y() - p2.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Turn around and run tx = x; ty = y; offset = 0.0f; dir += 2; if(dir > DIR_W) dir -= 4; } } // Check the collision between the potato men if(potatoman.collide_with(this) && !kicked) { // Potatoman "kicked" us potatoman.kick(this); } // If we're reached the target tile, move again if(offset >= 1.0f) { x = tx; y = ty; offset = 0.0f; } } } // Check collisions with other enemies and spread the fire bool burnt_somebody = false; list<ENEMY>::iterator e; for(e = enemylist.begin(); e != enemylist.end(); ++e) { if(this != &(*e) && !(*e).burning) { // Check the distance float dx = get_real_x() - (*e).get_real_x(); float dy = get_real_y() - (*e).get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Burn the other enemy (*e).burning = true; (*e).burn_time = enemy_burn_time; (*e).speed += 0.06f; burnt_somebody = true; } } } // Play the burning sound if(burnt_somebody) play_sound(SND_WILDFIRE, false); if(!kicked) return; } // Not burning below here // Choose a random destination if(path_pos == -1) { // Choose a valid target int dx = RAND(0, MAP_W-1); int dy = RAND(0, MAP_H-1); while(map_solid(dx, dy) || dx == x || dy == y) { dx = RAND(0, MAP_W-1); dy = RAND(0, MAP_H-1); } // Calculate the path if(pf.find_path(x, y, dx, dy) == PATH_FAILED) { // Well, tough luck. We'll just wait and try again later. return; } // Now we've got a nice path for us! path_pos = 0; offset = 0.0f; tx = pf.path[0].x; ty = pf.path[0].y; dir = get_dir(tx - x, ty - y); look_player(); } // Move one step if(tx == x && ty == y && path_pos > -1) { offset = 0.0f; // Follow the path if we're not chasing if(chase == 0 && !kicked) { path_pos++; tx = pf.path[path_pos].x; ty = pf.path[path_pos].y; dir = get_dir(tx - x, ty - y); look_player(); } else if(chase && !kicked) { // We are chasing. Don't stop until there's a wall. switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check if the target is passable? if(map_solid(tx, ty)) { // Stop and choose a new path tx = x; ty = y; path_pos = -1; chase = 0; speed -= 0.03f; } } else if(kicked) { // Potatoman has kicked us. "Fly" straight until we hit a wall. switch(dir) { default: case DIR_N: tx = x; ty = y - 1; break; case DIR_E: tx = x + 1; ty = y; break; case DIR_S: tx = x; ty = y + 1; break; case DIR_W: tx = x - 1; ty = y; break; } // Check for the wall if(map_solid(tx, ty)) { die(); return; } } } // Move towards the target tile if(offset < 1.0f && (tx != x || ty != y) && path_pos > -1) { offset += speed; // Check the collision between the player #1 if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p1.get_real_x(); float dy = get_real_y() - p1.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p1.die(); die(); } } // Check the collision between the player #2 if(alive && two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) { float dx = get_real_x() - p2.get_real_x(); float dy = get_real_y() - p2.get_real_y(); if(dx*dx + dy*dy <= 0.9f) { // Collision happened! // Kill the player and die p2.die(); die(); } } // Check the collision between the potato men if(potatoman.collide_with(this) && !kicked) { // Potatoman "kicked" us potatoman.kick(this); } // If we're reached the target tile, move again if(offset >= 1.0f) { x = tx; y = ty; offset = 0.0f; // If this is the final destination, stay put and choose a new path // on the next cycle if(x == pf.dx && y == pf.dy && !chase && !kicked) path_pos = -1; } } }
struct commandResult execute_command(struct player * me, char * cmd_buffer, char * cmd_param) { World *w = me->world; struct commandResult result; int ret = 0; int moved = 0; if(strlen(cmd_buffer) == 0) { printf("What?\n"); } else if(has_exit(me->currentRoom, cmd_buffer)) { printf("You go: %s\n", cmd_buffer); char room_file[30]; memset(&room_file, '\0', sizeof(char)*30); get_exit(&room_file, me->currentRoom, cmd_buffer); //free currentRoom.. struct room * nextRoom = cached_read_room(w, room_file); if(nextRoom != NULL) { // Also free links, items etc //free(me->currentRoom); me->currentRoom=NULL; me->currentRoom = nextRoom; moved = 1; } else { printf("You didn't move.\n"); } } else if(strcmp(cmd_buffer, "examine") == 0) { if((me->currentRoom)->items == NULL) { printf("You do not notice anything.\n"); } else { printf("You notice:-\n"); struct item * itemPtr = (me->currentRoom)->items; do { printf("%s\n", itemPtr->name); itemPtr = itemPtr->link; } while(itemPtr != NULL); } } else if(strcmp(cmd_buffer, "look") == 0) { if(cmd_param != NULL && strlen(cmd_param) > 0) { // printf("%s\n", cmd_param); if(strcmp(cmd_param, "me") == 0) { time_t now; time(&now); int seconds = (int)difftime(now, me->connectionTime); printf( "================================================================================\n" "Player: %s\n" "================================================================================\n" "Current room: %s\n" "Connected for: %d seconds\n", me->name, (me->currentRoom)->name, seconds); } else { printf("You do not notice anything special about: '%s'.\n", cmd_param); } } else { look_player(me); } } else if(strcmp(cmd_buffer, "mem") == 0) { printf("World: %s\n\n", w->name); LoadedRoom *head = w->rooms; printf("Loaded rooms:\n"); do { printf("- %s\n", (head->current)->fileName); head = head->next; } while(head != NULL); // && head->next!=NULL); } else if(strcmp(cmd_buffer, "help") == 0) { showHelp(); } else if(strcmp(cmd_buffer, "quit")==0) { ret = 1; } else { char expanded[30]; if(find_alias(&expanded, cmd_buffer, me)) { printf("Using alias %s.\n", expanded); struct commandResult childResult = execute_command(me, &expanded, cmd_param); ret = childResult.exit; moved = childResult.moved; } else { printf("I do not understand: '%s'.. ?\n", cmd_buffer); } } result.exit = ret; result.moved = moved; return result; }