@@ -15,8 +15,8 @@ use crate::{
1515 vm:: variables:: { F64_DEG_RAD , F64_RAD_DEG } ,
1616 } ,
1717 types:: {
18- ContentType , Point2 , Team ,
19- colors:: { f32_to_double_bits, f64_from_double_bits} ,
18+ ContentType , LAccess , Point2 , Team ,
19+ colors:: { self , f32_to_double_bits, f64_from_double_bits} ,
2020 content,
2121 } ,
2222} ;
@@ -87,7 +87,7 @@ impl Instruction for InstructionBuilder {
8787 var
8888 }
8989 }
90- ast:: Value :: String ( value) => LVar :: Constant ( LValue :: String ( value. into ( ) ) ) ,
90+ ast:: Value :: String ( value) => LVar :: Constant ( LValue :: RcString ( value. into ( ) ) ) ,
9191 ast:: Value :: Number ( value) => LVar :: Constant ( value. into ( ) ) ,
9292 ast:: Value :: None => LVar :: Constant ( LValue :: Null ) ,
9393 } ;
@@ -132,6 +132,15 @@ impl Instruction for InstructionBuilder {
132132 result : lvar ( result) ,
133133 index : lvar ( index) ,
134134 } ) ,
135+ ast:: Instruction :: Sensor {
136+ result,
137+ target,
138+ sensor,
139+ } => Box :: new ( Sensor {
140+ result : lvar ( result) ,
141+ target : lvar ( target) ,
142+ sensor : lvar ( sensor) ,
143+ } ) ,
135144
136145 // operations
137146 ast:: Instruction :: Set { to, from } => Box :: new ( Set {
@@ -245,13 +254,15 @@ impl Print {
245254 n. to_string ( )
246255 } )
247256 }
248- LValue :: String ( s) => Cow :: Borrowed ( s) ,
257+ LValue :: RcString ( s) => Cow :: Borrowed ( s) ,
258+ LValue :: StaticString ( s) => Cow :: from ( * s) ,
249259 LValue :: Content ( content) => Cow :: Borrowed ( content. name ( ) ) ,
250- LValue :: Team ( team) => team. name ( ) ,
260+ LValue :: Team ( team) => Cow :: from ( team. as_ref ( ) ) ,
251261 LValue :: Building ( position) => vm
252262 . building ( * position)
253263 . map ( |b| Cow :: Borrowed ( b. block . name . as_str ( ) ) )
254264 . unwrap_or ( Cow :: from ( "null" ) ) ,
265+ LValue :: Sensor ( sensor) => Cow :: from ( sensor. as_ref ( ) ) ,
255266 }
256267 }
257268}
@@ -360,6 +371,166 @@ impl SimpleInstruction for GetLink {
360371 }
361372}
362373
374+ struct Sensor {
375+ result : LVar ,
376+ target : LVar ,
377+ sensor : LVar ,
378+ }
379+
380+ impl Sensor {
381+ fn sense_processor ( sensor : LAccess , state : & ProcessorState ) -> LValue {
382+ match sensor {
383+ LAccess :: Enabled => state. enabled ( ) . into ( ) ,
384+ _ => LValue :: Null ,
385+ }
386+ }
387+ }
388+
389+ impl SimpleInstruction for Sensor {
390+ fn execute ( & self , state : & mut ProcessorState , vm : & LogicVM ) {
391+ use LAccess :: * ;
392+
393+ let target = self . target . get ( state) ;
394+ let sensor = self . sensor . get ( state) ;
395+
396+ let result = match sensor {
397+ // normal sensors
398+ LValue :: Sensor ( sensor) => match target {
399+ // dead
400+ LValue :: Null if sensor == Dead => true . into ( ) ,
401+
402+ // senseable
403+ LValue :: Content ( content) => match content {
404+ // TODO: color, health, maxHealth, solid, powerCapacity
405+ Content :: Block ( block) => match sensor {
406+ Size => block. size . into ( ) ,
407+ ItemCapacity => block. item_capacity . into ( ) ,
408+ LiquidCapacity => block. liquid_capacity . into ( ) ,
409+ Id => block. logic_id . into ( ) ,
410+ Name => LValue :: StaticString ( & block. name ) ,
411+ _ => LValue :: Null ,
412+ } ,
413+
414+ // TODO: color
415+ Content :: Item ( item) => match sensor {
416+ Id => item. logic_id . into ( ) ,
417+ Name => LValue :: StaticString ( & item. name ) ,
418+ _ => LValue :: Null ,
419+ } ,
420+
421+ // TODO: color
422+ Content :: Liquid ( liquid) => match sensor {
423+ Id => liquid. logic_id . into ( ) ,
424+ Name => LValue :: StaticString ( & liquid. name ) ,
425+ _ => LValue :: Null ,
426+ } ,
427+
428+ // TODO: health, maxHealth, size, itemCapacity, speed, payloadCapacity
429+ Content :: Unit ( unit) => match sensor {
430+ Id => unit. logic_id . into ( ) ,
431+ Name => LValue :: StaticString ( & unit. name ) ,
432+ _ => LValue :: Null ,
433+ } ,
434+ } ,
435+
436+ LValue :: Team ( team) => match sensor {
437+ Name => LValue :: StaticString ( team. into ( ) ) ,
438+ Id => team. id ( ) . into ( ) ,
439+ Color => team. color ( ) . into ( ) ,
440+ _ => LValue :: Null ,
441+ } ,
442+
443+ LValue :: Building ( position) => match vm. building ( position) {
444+ // TODO: solid, health, maxHealth, powerCapacity
445+ Some ( building) => match sensor {
446+ X => building. position . x . into ( ) ,
447+ Y => building. position . y . into ( ) ,
448+ Color => colors:: TEAM_SHARDED . into ( ) ,
449+ Dead => false . into ( ) ,
450+ Team => crate :: types:: Team :: Sharded . id ( ) . into ( ) ,
451+ Efficiency => 1 . into ( ) ,
452+ Timescale => 1 . into ( ) ,
453+ Range => building. block . range . into ( ) ,
454+ Rotation => 0 . into ( ) ,
455+ TotalItems | TotalLiquids | TotalPower => 0 . into ( ) ,
456+ ItemCapacity => building. block . item_capacity . into ( ) ,
457+ LiquidCapacity => building. block . liquid_capacity . into ( ) ,
458+ PowerNetIn | PowerNetOut | PowerNetStored | PowerNetCapacity => 0 . into ( ) ,
459+ Controlled => false . into ( ) ,
460+ PayloadCount => 0 . into ( ) ,
461+ Size => building. block . size . into ( ) ,
462+ CameraX | CameraY | CameraWidth | CameraHeight => 0 . into ( ) ,
463+ Type => Content :: Block ( building. block ) . into ( ) ,
464+ FirstItem => LValue :: Null ,
465+ PayloadType => LValue :: Null ,
466+
467+ _ => match building. data . try_borrow ( ) . as_deref ( ) . as_ref ( ) {
468+ Ok ( BuildingData :: Processor ( processor) ) => {
469+ Self :: sense_processor ( sensor, & processor. state )
470+ }
471+ // if the building is already mutably borrowed, we're sensing @this
472+ Err ( _) => Self :: sense_processor ( sensor, state) ,
473+
474+ Ok ( BuildingData :: Memory ( memory) ) => match sensor {
475+ MemoryCapacity => memory. len ( ) . into ( ) ,
476+ Enabled => true . into ( ) ,
477+ _ => LValue :: Null ,
478+ } ,
479+
480+ Ok ( BuildingData :: Message ( buf) ) => match sensor {
481+ BufferSize => buf. len ( ) . into ( ) ,
482+ Enabled => true . into ( ) ,
483+ _ => LValue :: Null ,
484+ } ,
485+
486+ Ok ( BuildingData :: Switch ( enabled) ) => match sensor {
487+ Enabled => ( * enabled) . into ( ) ,
488+ _ => LValue :: Null ,
489+ } ,
490+
491+ Ok ( BuildingData :: Unknown {
492+ senseable_config, ..
493+ } ) => match sensor {
494+ Config => senseable_config. clone ( ) . unwrap_or ( LValue :: Null ) ,
495+ Enabled => true . into ( ) ,
496+ _ => LValue :: Null ,
497+ } ,
498+ } ,
499+ } ,
500+ None => LValue :: Null ,
501+ } ,
502+
503+ // string length
504+ LValue :: RcString ( string) if matches ! ( sensor, BufferSize | Size ) => {
505+ string. len ( ) . into ( )
506+ }
507+ LValue :: StaticString ( string) if matches ! ( sensor, BufferSize | Size ) => {
508+ string. len ( ) . into ( )
509+ }
510+
511+ _ => LValue :: Null ,
512+ } ,
513+
514+ // if target doesn't implement Senseable, write null
515+ _ if !matches ! (
516+ target,
517+ LValue :: Content ( _) | LValue :: Team ( _) | LValue :: Building ( _)
518+ ) =>
519+ {
520+ LValue :: Null
521+ }
522+
523+ // items/liquids aren't implemented, so always write null if sensing content
524+ LValue :: Content ( _) => LValue :: Null ,
525+
526+ // if target is Senseable and sensor isn't Content or LAccess, do not write to result
527+ _ => return ,
528+ } ;
529+
530+ self . result . set ( state, result) ;
531+ }
532+ }
533+
363534// operations
364535
365536struct Set {
0 commit comments