public bool KnockObjectBack(Actor a,List<Tile> line,int knockback_strength,Actor damage_source)
 {
     if(knockback_strength == 0){ //note that TURN_INTO_CORPSE should be set for 'a' - therefore it won't be removed and we can do what we want with it.
         return a.CollideWith(a.tile());
     }
     int i=0;
     while(true){
         Tile t = line[i];
         if(t.actor() == a){
             break;
         }
         ++i;
     }
     line.RemoveRange(0,i+1);
     if(line.Count == 0){
         return a.CollideWith(a.tile());
     }
     bool immobile = a.MovementPrevented(line[0]);
     string knocked_back_message = "";
     if(!a.HasAttr(AttrType.TELEKINETICALLY_THROWN,AttrType.SELF_TK_NO_DAMAGE) && !immobile && player.CanSee(a)){ //if the player can see it now, don't check CanSee later.
         knocked_back_message = a.YouAre() + " knocked back. ";
         //B.Add(a.YouAre() + " knocked back. ",a);
     }
     int dice = 1;
     int damage_dice_to_other = 1;
     if(a.HasAttr(AttrType.TELEKINETICALLY_THROWN)){
         dice = 3;
         damage_dice_to_other = 3;
     }
     if(a.HasAttr(AttrType.SELF_TK_NO_DAMAGE)){
         dice = 0;
     }
     if(a.type == ActorType.SPORE_POD){
         dice = 0;
         damage_dice_to_other = 0;
     }
     while(knockback_strength > 1){ //if the knockback strength is greater than 1, you're passing *over* at least one tile.
         Tile t = line[0];
         line.RemoveAt(0);
         immobile = a.MovementPrevented(t);
         if(immobile){
             if(player.CanSee(a.tile())){
                 B.Add(a.YouVisibleAre() + " knocked about. ",a);
             }
             if(a.type == ActorType.SPORE_POD){
                 return true;
             }
             return a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"crashing into the floor");
         }
         if(!t.passable){
             string deathstringname = t.AName(false);
             if(t.Is(TileType.CRACKED_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR) && !a.HasAttr(AttrType.SMALL)){
                 string tilename = t.TheName(true);
                 if(t.type == TileType.HIDDEN_DOOR){
                     tilename = "a hidden door";
                     t.Toggle(null);
                 }
                 if(player.CanSee(a.tile())){
                     B.Add(a.YouVisibleAre() + " knocked through " + tilename + ". ",a,t);
                 }
                 else{
                     B.Add(knocked_back_message);
                 }
                 knocked_back_message = "";
                 //knockback_strength -= 2; //removing the distance modification for now
                 t.Toggle(null);
                 a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname);
                 a.Move(t.row,t.col);
                 if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){
                     if(a.type == ActorType.HOMUNCULUS){
                         if(R.CoinFlip()){
                             t.AddFeature(FeatureType.OIL);
                         }
                     }
                     else{
                         if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){
                             t.color = a.BloodColor();
                         }
                     }
                 }
             }
             else{
                 if(player.CanSee(a.tile())){
                     B.Add(a.YouVisibleAre() + " knocked into " + t.TheName(true) + ". ",a,t);
                 }
                 else{
                     B.Add(knocked_back_message);
                 }
                 knocked_back_message = "";
                 if(a.type != ActorType.SPORE_POD){
                     Color blood = a.BloodColor();
                     if(blood != Color.Black && R.CoinFlip() && t.Is(TileType.WALL) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){
                         t.color = blood;
                     }
                     a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname);
                 }
                 if(!a.HasAttr(AttrType.SMALL)){
                     t.Bump(a.DirectionOf(t));
                 }
                 a.CollideWith(a.tile());
                 return !a.HasAttr(AttrType.CORPSE);
             }
         }
         else{
             if(t.actor() != null){
                 if(player.CanSee(a.tile()) || player.CanSee(t)){
                     B.Add(a.YouVisibleAre() + " knocked into " + t.actor().TheName(true) + ". ",a,t.actor());
                 }
                 else{
                     B.Add(knocked_back_message);
                 }
                 knocked_back_message = "";
                 string actorname = t.actor().AName(false);
                 string actorname2 = a.AName(false);
                 if(t.actor().type != ActorType.SPORE_POD && !t.actor().HasAttr(AttrType.SELF_TK_NO_DAMAGE)){
                     t.actor().TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(damage_dice_to_other,6),damage_source,"colliding with " + actorname2);
                 }
                 if(a.type != ActorType.SPORE_POD){
                     a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"colliding with " + actorname);
                 }
                 a.CollideWith(a.tile());
                 return !a.HasAttr(AttrType.CORPSE);
             }
             else{
                 if(t.Is(FeatureType.WEB) && !a.HasAttr(AttrType.SMALL)){
                     t.RemoveFeature(FeatureType.WEB);
                 }
                 a.Move(t.row,t.col,false);
                 if(t.Is(FeatureType.WEB) && a.HasAttr(AttrType.SMALL) && !a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED,AttrType.BURNING)){
                     knockback_strength = 0;
                 }
                 if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){
                     if(a.type == ActorType.HOMUNCULUS){
                         if(R.CoinFlip()){
                             t.AddFeature(FeatureType.OIL);
                         }
                     }
                     else{
                         if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){
                             t.color = a.BloodColor();
                         }
                     }
                 }
             }
         }
         M.Draw();
         knockback_strength--;
     }
     if(knockback_strength < 1){
         return !a.HasAttr(AttrType.CORPSE);
     }
     bool slip = false;
     int extra_slip_tiles = -1;
     bool slip_message_printed = false;
     do{
         Tile t = line[0];
         line.RemoveAt(0);
         immobile = a.MovementPrevented(t);
         if(immobile){
             if(player.CanSee(a.tile())){
                 B.Add(a.YouVisibleAre() + " knocked about. ",a);
             }
             if(a.type == ActorType.SPORE_POD){
                 return true;
             }
             return a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"crashing into the floor");
         }
         if(!t.passable){
             string deathstringname = t.AName(false);
             if(t.Is(TileType.CRACKED_WALL,TileType.DOOR_C,TileType.HIDDEN_DOOR) && !a.HasAttr(AttrType.SMALL)){
                 string tilename = t.TheName(true);
                 if(t.type == TileType.HIDDEN_DOOR){
                     tilename = "a hidden door";
                     t.Toggle(null);
                 }
                 if(player.CanSee(a.tile())){
                     B.Add(a.YouVisibleAre() + " knocked through " + tilename + ". ",a,t);
                 }
                 else{
                     B.Add(knocked_back_message);
                 }
                 knocked_back_message = "";
                 t.Toggle(null);
                 a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname);
                 a.Move(t.row,t.col);
                 if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){
                     if(a.type == ActorType.HOMUNCULUS){
                         if(R.CoinFlip()){
                             t.AddFeature(FeatureType.OIL);
                         }
                     }
                     else{
                         if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){
                             t.color = a.BloodColor();
                         }
                     }
                 }
                 return !a.HasAttr(AttrType.CORPSE);
             }
             else{
                 if(player.CanSee(a.tile())){
                     B.Add(a.YouVisibleAre() + " knocked into " + t.TheName(true) + ". ",a,t);
                 }
                 else{
                     B.Add(knocked_back_message);
                 }
                 knocked_back_message = "";
                 if(a.type != ActorType.SPORE_POD){
                     Color blood = a.BloodColor();
                     if(blood != Color.Black && R.CoinFlip() && t.Is(TileType.WALL) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){
                         t.color = blood;
                     }
                     a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"slamming into " + deathstringname);
                 }
                 if(!a.HasAttr(AttrType.SMALL)){
                     t.Bump(a.DirectionOf(t));
                 }
                 a.CollideWith(a.tile());
                 return !a.HasAttr(AttrType.CORPSE);
             }
         }
         else{
             if(t.actor() != null){
                 if(player.CanSee(a.tile()) || player.CanSee(t)){
                     B.Add(a.YouVisibleAre() + " knocked into " + t.actor().TheName(true) + ". ",a,t.actor());
                 }
                 else{
                     B.Add(knocked_back_message);
                 }
                 knocked_back_message = "";
                 string actorname = t.actor().AName(false);
                 string actorname2 = a.AName(false);
                 if(t.actor().type != ActorType.SPORE_POD && !t.actor().HasAttr(AttrType.SELF_TK_NO_DAMAGE)){
                     t.actor().TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(damage_dice_to_other,6),damage_source,"colliding with " + actorname2);
                 }
                 if(a.type != ActorType.SPORE_POD){
                     a.TakeDamage(DamageType.NORMAL,DamageClass.PHYSICAL,R.Roll(dice,6),damage_source,"colliding with " + actorname);
                 }
                 a.CollideWith(a.tile());
                 return !a.HasAttr(AttrType.CORPSE);
             }
             else{
                 slip = false;
                 if(t.IsSlippery()){
                     B.Add(knocked_back_message);
                     knocked_back_message = "";
                     slip = true;
                     if(!slip_message_printed){
                         slip_message_printed = true;
                         B.Add(a.You("slide") + "! ");
                     }
                 }
                 else{
                     if(extra_slip_tiles > 0){
                         extra_slip_tiles--;
                     }
                     if(extra_slip_tiles == -1 && a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED) && !t.IsWater()){
                         B.Add(knocked_back_message);
                         knocked_back_message = "";
                         extra_slip_tiles = 2;
                         if(!slip_message_printed){
                             slip_message_printed = true;
                             B.Add(a.You("slide") + "! ");
                         }
                     }
                 }
                 /*if(extra_slip_tiles > 0){
                     extra_slip_tiles--;
                 }
                 if(t.IsSlippery()){
                     B.Add(knocked_back_message);
                     knocked_back_message = "";
                     slip = true;
                     if(!slip_message_printed){
                         slip_message_printed = true;
                         B.Add(a.You("slide") + "! ");
                     }
                 }
                 else{
                     if(extra_slip_tiles == -1 && a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED)){
                         B.Add(knocked_back_message);
                         knocked_back_message = "";
                         extra_slip_tiles = 2;
                         if(!slip_message_printed){
                             slip_message_printed = true;
                             B.Add(a.You("slide") + "! ");
                         }
                     }
                 }*/
                 bool interrupted = false;
                 if(t.inv != null && t.inv.type == ConsumableType.DETONATION){ //this will cause a new knockback effect and end the current one
                     B.Add(knocked_back_message);
                     knocked_back_message = "";
                     interrupted = true;
                 }
                 if(t.IsTrap()){
                     if(t.type == TileType.FLING_TRAP){ //otherwise you'd teleport around, continuing to slide from your previous position.
                         interrupted = true;
                     }
                     B.Add(knocked_back_message);
                     knocked_back_message = "";
                 }
                 if(t.Is(FeatureType.WEB) && !a.HasAttr(AttrType.SMALL)){
                     t.RemoveFeature(FeatureType.WEB);
                 }
                 a.Move(t.row,t.col);
                 if(a.HasAttr(AttrType.BLEEDING) && !a.HasAttr(AttrType.SHIELDED,AttrType.INVULNERABLE,AttrType.SELF_TK_NO_DAMAGE)){
                     if(a.type == ActorType.HOMUNCULUS){
                         if(R.CoinFlip()){
                             t.AddFeature(FeatureType.OIL);
                         }
                     }
                     else{
                         if(t.symbol == '.' && t.color == Color.White && R.CoinFlip()){
                             t.color = a.BloodColor();
                         }
                     }
                 }
                 if(a.HasAttr(AttrType.FROZEN)){
                     interrupted = true;
                 }
                 if(a.HasAttr(AttrType.SMALL) && t.Is(FeatureType.WEB) && !a.HasAttr(AttrType.SLIMED,AttrType.OIL_COVERED,AttrType.BURNING)){
                     B.Add(knocked_back_message);
                     interrupted = true;
                 }
                 else{
                     if(a.tile().IsWater()){
                         interrupted = true;
                     }
                     B.Add(knocked_back_message);
                     a.CollideWith(a.tile());
                 }
                 knocked_back_message = "";
                 if(interrupted){
                     return !a.HasAttr(AttrType.CORPSE);
                 }
             }
         }
         M.Draw();
     }
     while(slip || extra_slip_tiles > 0);
     if(knocked_back_message != ""){
         B.Add(knocked_back_message); //this probably never happens
     }
     return !a.HasAttr(AttrType.CORPSE);
 }